1
2
3
4
5
6
7
8
9
10
11
12
13
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
77
78
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
122
123
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
177
178 public XsAnalyzerApplicationModel getModel() {
179 return model;
180 }
181
182
183
184
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
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
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
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
289 if (lastPathComponent instanceof DefaultMutableTreeNode) {
290 lastPathComponent = ((DefaultMutableTreeNode) lastPathComponent).getUserObject();
291 }
292
293
294 if (lastPathComponent instanceof XSObject) {
295 parameters.put(XsElementPropertiesExecutor.OBJECT, (XSObject) lastPathComponent);
296 executor.execute(parameters);
297 }
298 }
299 }
300 }
301 }