View Javadoc

1   // $Id: AnnotationPanel.java 165 2009-05-28 21:46:38Z agony $
2   /*
3    * xsAnalyzer - XML schema analyzing tool. Copyright (C) 2008 Michael Engelhardt
4    * 
5    * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
6    * License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
7    * version.
8    * 
9    * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
10   * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11   * 
12   * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
13   * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14   */
15  /**
16   * 
17   */
18  package de.mindcrimeilab.xsanalyzer.ui.panels;
19  
20  import java.awt.Component;
21  import java.awt.Insets;
22  import java.awt.event.ActionEvent;
23  import java.awt.event.ActionListener;
24  import java.lang.reflect.Method;
25  import java.util.Arrays;
26  import java.util.List;
27  import java.util.Locale;
28  
29  import javax.swing.Box;
30  import javax.swing.DefaultListCellRenderer;
31  import javax.swing.JCheckBox;
32  import javax.swing.JComboBox;
33  import javax.swing.JEditorPane;
34  import javax.swing.JLabel;
35  import javax.swing.JList;
36  import javax.swing.JPanel;
37  import javax.swing.JScrollPane;
38  import javax.swing.JTextPane;
39  import javax.swing.ListCellRenderer;
40  
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  import org.apache.xerces.xs.XSAnnotation;
44  import org.apache.xerces.xs.XSObject;
45  import org.apache.xerces.xs.XSObjectList;
46  import org.springframework.context.support.MessageSourceAccessor;
47  import org.springframework.richclient.application.ApplicationServicesLocator;
48  import org.springframework.richclient.factory.ComponentFactory;
49  import org.springframework.richclient.layout.GridBagLayoutBuilder;
50  import org.springframework.richclient.list.ComboBoxListModel;
51  
52  import de.mindcrimeilab.xsanalyzer.xml.AnnotationContentHandler;
53  import de.mindcrimeilab.xsanalyzer.xml.XmlSchemaAnnotation;
54  
55  /**
56   * 
57   * @author Michael Engelhardt<me@mindcrime-ilab.de>
58   * @author $Author: agony $
59   * @version $Revision: 165 $
60   * 
61   */
62  public class AnnotationPanel {
63  
64      private static final Log logger = LogFactory.getLog("xsAnalyzerApplicationLogger");
65  
66      /** content view to display annotation contents */
67      private JTextPane jetDocumentation;
68  
69      /** combobox to select desired annotation because there might be several annotations per selected element */
70      private JComboBox jcbAnnotations;
71  
72      /** combobox model */
73      private final ComboBoxListModel annotationsListModel;
74  
75      /** checkbox to enable/disable html view */
76      private JCheckBox jcbEnableHtml;
77  
78      private static String NO_ANNOTATIONS = "No annotations";
79  
80      public AnnotationPanel() {
81          NO_ANNOTATIONS = getMessage("annotationToolWindow.annotations.noAnnotation");
82          this.annotationsListModel = new ComboBoxListModel(Arrays.asList(new String[] { NO_ANNOTATIONS}));
83          createDocumentationEditorPane();
84          createJcbAnnotations();
85          createJcbEnableHtml();
86          setupListeners();
87      }
88  
89      public JPanel getPanel() {
90          ComponentFactory cf = getComponentFactory();
91          JLabel label = cf.createLabelFor(getMessage("annotationToolWindow.annotations.comboBox.label"), this.jcbAnnotations);
92          GridBagLayoutBuilder builder = new GridBagLayoutBuilder();
93          builder.setAutoSpanLastComponent(false);
94          builder.setDefaultInsets(new Insets(5, 5, 5, 5));
95          builder.appendLabel(label).append(this.jcbAnnotations, 1, 1, false, false).append(Box.createHorizontalStrut(10), 1, 1, true, false).append(jcbEnableHtml, 1, 1, false, false, new Insets(5, 5, 5, 5)).nextLine();
96          builder.append(cf.createScrollPane(jetDocumentation, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), 4, 1, true, true).nextLine();
97  
98          return builder.getPanel();
99      }
100 
101     /**
102      * @return
103      */
104     private ComponentFactory getComponentFactory() {
105         return (ComponentFactory) ApplicationServicesLocator.services().getService(ComponentFactory.class);
106     }
107 
108     public String getMessage(String messageCode) {
109         return ((MessageSourceAccessor) ApplicationServicesLocator.services().getService(MessageSourceAccessor.class)).getMessage(messageCode, null, messageCode, Locale.getDefault());
110     }
111 
112     /**
113      * update content view
114      * 
115      * @param xso
116      *            object to extract annotations from
117      */
118     public void update(XSObject xso) {
119         try {
120             Method method = xso.getClass().getMethod("getAnnotations", new Class[] {});
121             XSObjectList annotations = (XSObjectList) method.invoke(xso, new Object[] {});
122             setAnnotations(annotations);
123         }
124         catch (Exception e) {
125             logger.info("No annotations found.", e);
126         }
127     }
128 
129     /**
130      * update annotations view
131      * 
132      * @param annotations
133      *            to display
134      */
135     private void setAnnotations(XSObjectList annotations) {
136         // no annotations at all - clear view
137         if (null == annotations || annotations.getLength() < 1) {
138             this.annotationsListModel.clear();
139             this.annotationsListModel.add(NO_ANNOTATIONS);
140             return;
141         }
142         // update and display annotations
143         for (int i = 0; i < annotations.getLength(); ++i) {
144             XSAnnotation annotation = (XSAnnotation) annotations.item(i);
145             logger.debug("Annotation #" + i + " [" + annotation + "]");
146             logger.debug("Annotation #" + i + " type=[" + annotation.getType() + "], value=[" + annotation.getAnnotationString() + "]");
147             AnnotationContentHandler contentHandler = new AnnotationContentHandler();
148             annotation.writeAnnotation(contentHandler, XSAnnotation.SAX_CONTENTHANDLER);
149 
150             List<XmlSchemaAnnotation> annotationsList = contentHandler.getAnnotations();
151             this.annotationsListModel.clear();
152             if (null == annotationsList || annotationsList.isEmpty()) {
153                 this.annotationsListModel.add(NO_ANNOTATIONS);
154             }
155             else {
156                 this.annotationsListModel.addAll(annotationsList);
157             }
158         }
159     }
160 
161     /**
162      * initialize annotations combobox
163      */
164     private final void createJcbAnnotations() {
165         this.jcbAnnotations = getComponentFactory().createComboBox();
166         this.jcbAnnotations.setModel(this.annotationsListModel);
167         this.jcbAnnotations.setRenderer(new AnnotationsListCellRenderer());
168         this.jcbAnnotations.setEnabled(false);
169     }
170 
171     /**
172      * initialize html view checkbox
173      */
174     private final void createJcbEnableHtml() {
175         this.jcbEnableHtml = new JCheckBox(getMessage("annotationToolWindow.annotations.enableHtmlCheckbox.label"));
176         this.jcbEnableHtml.setSelected(false);
177         this.jcbEnableHtml.setEnabled(false);
178     }
179 
180     /**
181      * initialize annotations view
182      */
183     private final void createDocumentationEditorPane() {
184         this.jetDocumentation = new JTextPane();
185         jetDocumentation.setEditable(false);
186         jetDocumentation.setText(NO_ANNOTATIONS);
187         jetDocumentation.setEnabled(false);
188     }
189 
190     /**
191      * setup listeners for internal components
192      */
193     private final void setupListeners() {
194         assert null != this.jetDocumentation;
195         assert null != this.jcbAnnotations;
196         assert null != this.jcbEnableHtml;
197         this.jcbAnnotations.addActionListener(new SelectAnnotationsActionListener(this.jetDocumentation, this.jcbEnableHtml));
198         this.jcbEnableHtml.addActionListener(new SwitchHtmlViewActionListener(this.jetDocumentation, this.jcbAnnotations));
199     }
200 
201     /**
202      * Internal listener handling selection events of the annotations combox.
203      * 
204      * @author Michael Engelhardt
205      * @author $Author: agony $
206      * @version $Revision: 165 $
207      */
208     private class SelectAnnotationsActionListener implements ActionListener {
209 
210         /** content view to update */
211         private final JEditorPane editorPane;
212 
213         /** switch for html view to update */
214         private final JCheckBox checkBox;
215 
216         /**
217          * ctor()
218          * 
219          * @param editorPane
220          *            to update
221          * @param checkBox
222          *            to uddate
223          */
224         SelectAnnotationsActionListener(JEditorPane editorPane, JCheckBox checkBox) {
225             this.editorPane = editorPane;
226             this.checkBox = checkBox;
227         }
228 
229         @Override
230         public void actionPerformed(ActionEvent evt) {
231             JComboBox comboBox = (JComboBox) evt.getSource();
232             Object item = comboBox.getSelectedItem();
233             final String text;
234             if (item instanceof XmlSchemaAnnotation) {
235                 text = ((XmlSchemaAnnotation) item).getContent();
236                 comboBox.setEnabled(true);
237             }
238             else {
239                 text = NO_ANNOTATIONS;
240 
241                 comboBox.setEnabled(false);
242             }
243             editorPane.setText(text);
244             editorPane.setEnabled(comboBox.isEnabled());
245             checkBox.setEnabled(comboBox.isEnabled());
246         }
247 
248     }
249 
250     /**
251      * Internal listener handling events of the enable/disable html view checkbox. For some reason the combox have to be
252      * reselected again in order to trigger propper update of the content view.
253      * 
254      * @author Michael Engelhardt
255      * @author $Author: agony $
256      * @version $Revision: 165 $
257      */
258     private class SwitchHtmlViewActionListener implements ActionListener {
259 
260         /** content view to update */
261         private final JEditorPane editorPane;
262 
263         /** combox to perform callback on */
264         private final JComboBox comboBox;
265 
266         /**
267          * ctor();
268          * 
269          * @param editorPane
270          *            to update
271          * @param comboBox
272          *            to update
273          */
274         SwitchHtmlViewActionListener(JEditorPane editorPane, JComboBox comboBox) {
275             this.editorPane = editorPane;
276             this.comboBox = comboBox;
277         }
278 
279         @Override
280         public void actionPerformed(ActionEvent evt) {
281             JCheckBox checkBox = (JCheckBox) evt.getSource();
282             if (checkBox.isSelected()) {
283                 editorPane.setContentType("text/html");
284             }
285             else {
286                 editorPane.setContentType("text/plain");
287             }
288             // trigger update of content view
289             comboBox.setSelectedIndex(jcbAnnotations.getSelectedIndex());
290         }
291 
292     }
293 
294     /**
295      * Renderer used by the annotations combox box.
296      * 
297      * @author Michael Engelhardt
298      * @author $Author: agony $
299      * @version $Revision: 165 $
300      */
301     private class AnnotationsListCellRenderer extends DefaultListCellRenderer implements ListCellRenderer {
302 
303         /**
304          * serial version uid
305          */
306         private static final long serialVersionUID = -1950469130279232642L;
307 
308         @Override
309         public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
310             JLabel cell = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
311             if (value instanceof XmlSchemaAnnotation) {
312                 switch (((XmlSchemaAnnotation) value).getType()) {
313                     case APPINFO:
314                         cell.setText("appinfo");
315                         break;
316                     case DOCUMENTATION:
317                         cell.setText("documentation");
318                         break;
319                     default:
320                         cell.setText("ERROR: unknown type");
321                 }
322             }
323             return cell;
324         }
325 
326     }
327 }