View Javadoc

1   // $Id: TypeUsageView.java 169 2010-08-26 18:59:04Z 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;
19  
20  import java.awt.Insets;
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import javax.swing.JComponent;
27  import javax.swing.JList;
28  import javax.swing.JPanel;
29  import javax.swing.JPopupMenu;
30  import javax.swing.JToolBar;
31  import javax.swing.JTree;
32  import javax.swing.ScrollPaneConstants;
33  import javax.swing.event.ListSelectionEvent;
34  import javax.swing.event.ListSelectionListener;
35  import javax.swing.event.TreeSelectionEvent;
36  import javax.swing.event.TreeSelectionListener;
37  import javax.swing.tree.DefaultMutableTreeNode;
38  import javax.swing.tree.TreePath;
39  
40  import org.apache.xerces.xs.XSObject;
41  import org.apache.xerces.xs.XSObjectList;
42  import org.apache.xerces.xs.XSTypeDefinition;
43  import org.springframework.binding.value.ValueModel;
44  import org.springframework.binding.value.support.ValueHolder;
45  import org.springframework.context.ApplicationEvent;
46  import org.springframework.context.ApplicationListener;
47  import org.springframework.richclient.application.PageComponentContext;
48  import org.springframework.richclient.application.support.AbstractView;
49  import org.springframework.richclient.command.CommandGroup;
50  import org.springframework.richclient.command.ParameterizableActionCommandExecutor;
51  import org.springframework.richclient.command.support.GlobalCommandIds;
52  import org.springframework.richclient.factory.ComponentFactory;
53  import org.springframework.richclient.layout.GridBagLayoutBuilder;
54  import org.springframework.richclient.list.FilteredListModel;
55  import org.springframework.richclient.list.ListSelectionValueModelAdapter;
56  import org.springframework.richclient.util.PopupMenuMouseListener;
57  
58  import de.mindcrimeilab.util.DefaultMutableTreeNodeAccessor;
59  import de.mindcrimeilab.xsanalyzer.actions.AbstractXSObjectCommand;
60  import de.mindcrimeilab.xsanalyzer.actions.TypeHierarchyCommand;
61  import de.mindcrimeilab.xsanalyzer.actions.TypeInspectionCommand;
62  import de.mindcrimeilab.xsanalyzer.actions.XsAnalyzerApplicationEvent;
63  import de.mindcrimeilab.xsanalyzer.actions.XsElementPropertiesExecutor;
64  import de.mindcrimeilab.xsanalyzer.model.FilteredTreeModel;
65  import de.mindcrimeilab.xsanalyzer.model.JListSelectionValueModelAdapter;
66  import de.mindcrimeilab.xsanalyzer.model.JTreeValueModelAdapter;
67  import de.mindcrimeilab.xsanalyzer.model.TreeSelectionValueModelAdapter;
68  import de.mindcrimeilab.xsanalyzer.model.UnusedTypesListModelAdapter;
69  import de.mindcrimeilab.xsanalyzer.model.UsedTypesTreeModelAdapter;
70  import de.mindcrimeilab.xsanalyzer.model.XsAnalyzerApplicationModel;
71  import de.mindcrimeilab.xsanalyzer.rules.constraints.SchemaTypeConstraint;
72  import de.mindcrimeilab.xsanalyzer.ui.filter.FilterToolbarFactory;
73  import de.mindcrimeilab.xsanalyzer.ui.renderer.SchemaElementsRenderer;
74  
75  /**
76   * @author Michael Engelhardt<me@mindcrime-ilab.de>
77   * @author $Author: agony $
78   * @version $Revision: 169 $
79   * 
80   */
81  public class TypeUsageView extends AbstractView implements ApplicationListener {
82  
83      private final ValueModel numUsedTypes = new ValueHolder(0);
84  
85      private final ValueModel numUnusedTypes = new ValueHolder(0);
86  
87      private JList jlUnusedTypes;
88  
89      private JTree jtUsedTypes;
90  
91      private XsAnalyzerApplicationModel model;
92  
93      private final XsElementPropertiesExecutor xsElementPropertiesExecutor = new XsElementPropertiesExecutor();
94  
95      private final AbstractXSObjectCommand unusedTypeHierarchyCommand = new TypeHierarchyCommand();
96  
97      private final AbstractXSObjectCommand usedTypeHierarchyCommand = new TypeHierarchyCommand();
98  
99      private final AbstractXSObjectCommand unusedTypeInspectionCommand = new TypeInspectionCommand();
100 
101     private final AbstractXSObjectCommand usedTypeInspectionCommand = new TypeInspectionCommand();
102 
103     private final SchemaTypeConstraint unusedTypesConstraint;
104 
105     private final SchemaTypeConstraint usedTypesConstraint;
106 
107     private final XsPropertiesSelectionListener xsPropertiesSelectionListener;
108 
109     public TypeUsageView() {
110         unusedTypesConstraint = new SchemaTypeConstraint();
111         usedTypesConstraint = new SchemaTypeConstraint(new DefaultMutableTreeNodeAccessor());
112         xsPropertiesSelectionListener = new XsPropertiesSelectionListener(xsElementPropertiesExecutor);
113     }
114 
115     @Override
116     protected void registerLocalCommandExecutors(PageComponentContext context) {
117         context.register(GlobalCommandIds.PROPERTIES, xsElementPropertiesExecutor);
118     }
119 
120     /*
121      * (non-Javadoc)
122      * 
123      * @see org.springframework.richclient.application.support.AbstractView#createControl ()
124      */
125     @Override
126     protected JComponent createControl() {
127         createUnusedTypesList();
128         createUsedTypesTree();
129 
130         final ComponentFactory cf = getComponentFactory();
131         final GridBagLayoutBuilder builder = new GridBagLayoutBuilder();
132         builder.setDefaultInsets(new Insets(2, 5, 2, 5));
133 
134         final JToolBar filterToolbar = FilterToolbarFactory.createFilterToolBar(new SchemaTypeConstraint[] { unusedTypesConstraint, usedTypesConstraint});
135         builder.append(filterToolbar, 1, 1, true, false).nextLine();
136 
137         builder.appendLabel(cf.createLabel("typeUsageView.label.unusedTypes", new ValueModel[] { numUnusedTypes})).nextLine();
138 
139         builder.append(cf.createScrollPane(jlUnusedTypes, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), 1, 1, 1, 1).nextLine();
140 
141         builder.appendSeparator();
142 
143         builder.appendLabel(cf.createLabel("typeUsageView.label.usedTypes", new ValueModel[] { numUsedTypes})).nextLine();
144 
145         builder.append(cf.createScrollPane(jtUsedTypes, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), 1, 1, 1, 2);
146 
147         builder.setAutoSpanLastComponent(true);
148         JPanel jpTypeUsage = builder.getPanel();
149 
150         return jpTypeUsage;
151     }
152 
153     private void createUnusedTypesList() {
154         jlUnusedTypes = getComponentFactory().createList();
155         jlUnusedTypes.setCellRenderer(new SchemaElementsRenderer());
156 
157         jlUnusedTypes.addListSelectionListener(xsPropertiesSelectionListener);
158 
159         final CommandGroup group = getWindowCommandManager().createCommandGroup("unusedTypeUsageCommandGroup", new Object[] { unusedTypeHierarchyCommand, unusedTypeInspectionCommand, "separator", GlobalCommandIds.PROPERTIES});
160         final JPopupMenu popup = group.createPopupMenu();
161         jlUnusedTypes.addMouseListener(new PopupMenuMouseListener(popup));
162     }
163 
164     private void createUsedTypesTree() {
165         jtUsedTypes = new JTree(new DefaultMutableTreeNode(getMessage("usedTypes.tree.noModel")));
166         jtUsedTypes.setCellRenderer(new SchemaElementsRenderer());
167 
168         final CommandGroup group = getWindowCommandManager().createCommandGroup("usedTypeUsageCommandGroup", new Object[] { usedTypeHierarchyCommand, usedTypeInspectionCommand, "separator", GlobalCommandIds.PROPERTIES});
169         final JPopupMenu popup = group.createPopupMenu();
170         jtUsedTypes.addMouseListener(new PopupMenuMouseListener(popup));
171 
172         jtUsedTypes.addTreeSelectionListener(xsPropertiesSelectionListener);
173     }
174 
175     /**
176      * @return the model
177      */
178     public XsAnalyzerApplicationModel getModel() {
179         return model;
180     }
181 
182     /**
183      * @param model
184      *            the model to set
185      */
186     public void setModel(XsAnalyzerApplicationModel model) {
187         this.model = model;
188         updateModel();
189     }
190 
191     private void updateModel() {
192         if (null != model) {
193             Set<XSTypeDefinition> unusedTypes = model.getUnusedTypes();
194             updateUnusedTypesView(unusedTypes);
195 
196             Map<XSObject, ? extends XSObjectList> usedTypes = model.getUsedTypes();
197             updateUsedTypesView(usedTypes);
198         }
199     }
200 
201     /**
202      * @param usedTypes
203      */
204     private void updateUsedTypesView(Map<XSObject, ? extends XSObjectList> usedTypes) {
205         if (null != usedTypes) {
206             final UsedTypesTreeModelAdapter usedTypesTreeModelAdapter = new UsedTypesTreeModelAdapter(usedTypes);
207             final FilteredTreeModel filteredModel = new FilteredTreeModel(usedTypesTreeModelAdapter, usedTypesConstraint);
208             jtUsedTypes.setModel(filteredModel);
209             // jtUsedTypes.setModel(usedTypesTreeModelAdapter);
210             numUsedTypes.setValue(usedTypesTreeModelAdapter.getChildCount(usedTypesTreeModelAdapter.getRoot()));
211 
212             final ValueModel selectionHolder = new TreeSelectionValueModelAdapter(jtUsedTypes.getSelectionModel());
213             final ValueModel vModel = new JTreeValueModelAdapter((TreeSelectionValueModelAdapter) selectionHolder);
214 
215             usedTypeHierarchyCommand.setValueModel(vModel);
216             usedTypeHierarchyCommand.setAccessor(new DefaultMutableTreeNodeAccessor());
217 
218             usedTypeInspectionCommand.setValueModel(vModel);
219             usedTypeInspectionCommand.setAccessor(new DefaultMutableTreeNodeAccessor());
220         }
221     }
222 
223     /**
224      * @param unusedTypes
225      */
226     private void updateUnusedTypesView(Set<XSTypeDefinition> unusedTypes) {
227         if (null != unusedTypes) {
228             final UnusedTypesListModelAdapter unusedTypesListModelAdapter = new UnusedTypesListModelAdapter(unusedTypes);
229             final FilteredListModel filteredModel = new FilteredListModel(unusedTypesListModelAdapter, unusedTypesConstraint);
230             jlUnusedTypes.setModel(filteredModel);
231             numUnusedTypes.setValue(unusedTypesListModelAdapter.getSize());
232 
233             final ValueModel selectionModel = new ListSelectionValueModelAdapter(jlUnusedTypes.getSelectionModel());
234             final ValueModel vModel = new JListSelectionValueModelAdapter(jlUnusedTypes.getModel(), (ListSelectionValueModelAdapter) selectionModel);
235             unusedTypeHierarchyCommand.setValueModel(vModel);
236             unusedTypeInspectionCommand.setValueModel(vModel);
237 
238         }
239     }
240 
241     private void invalidate() {
242         updateUnusedTypesView(Collections.<XSTypeDefinition> emptySet());
243         updateUsedTypesView(Collections.<XSObject, XSObjectList> emptyMap());
244     }
245 
246     @Override
247     public void onApplicationEvent(ApplicationEvent event) {
248         if (event instanceof XsAnalyzerApplicationEvent) {
249             switch (((XsAnalyzerApplicationEvent) event).getEventType()) {
250                 case TYPE_USAGE:
251                     XsAnalyzerApplicationModel appmodel = (XsAnalyzerApplicationModel) getApplicationContext().getBean("applicationModel");
252                     setModel(appmodel);
253                     break;
254                 case OPEN:
255                     invalidate();
256                     break;
257             }
258         }
259 
260     }
261 
262     private static class XsPropertiesSelectionListener implements ListSelectionListener, TreeSelectionListener {
263 
264         /**
265      * 
266      */
267         private final ParameterizableActionCommandExecutor executor;
268 
269         public XsPropertiesSelectionListener(ParameterizableActionCommandExecutor executor) {
270             this.executor = executor;
271         }
272 
273         @Override
274         public void valueChanged(ListSelectionEvent e) {
275             Map<String, XSObject> parameters = new HashMap<String, XSObject>();
276             JList list = (JList) e.getSource();
277             parameters.put(XsElementPropertiesExecutor.OBJECT, (XSObject) list.getSelectedValue());
278             executor.execute(parameters);
279         }
280 
281         @Override
282         public void valueChanged(TreeSelectionEvent e) {
283             TreePath path = e.getPath();
284             if (null != path) {
285                 Map<String, XSObject> parameters = new HashMap<String, XSObject>();
286                 Object lastPathComponent = path.getLastPathComponent();
287 
288                 // unwrap tree nodes
289                 if (lastPathComponent instanceof DefaultMutableTreeNode) {
290                     lastPathComponent = ((DefaultMutableTreeNode) lastPathComponent).getUserObject();
291                 }
292 
293                 // execute executor ;)
294                 if (lastPathComponent instanceof XSObject) {
295                     parameters.put(XsElementPropertiesExecutor.OBJECT, (XSObject) lastPathComponent);
296                     executor.execute(parameters);
297                 }
298             }
299         }
300     }
301 }