1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.xmlhammer.gui.xpath;
23
24 import java.awt.Font;
25 import java.awt.event.ItemEvent;
26 import java.awt.event.ItemListener;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import javax.swing.Box;
31 import javax.swing.Icon;
32 import javax.swing.ImageIcon;
33 import javax.swing.JComboBox;
34 import javax.swing.JLabel;
35 import javax.swing.JPanel;
36 import javax.swing.JTextField;
37 import javax.swing.border.EmptyBorder;
38 import javax.swing.event.DocumentEvent;
39 import javax.swing.event.DocumentListener;
40 import javax.xml.xpath.XPathExpressionException;
41 import javax.xml.xpath.XPathFactory;
42 import javax.xml.xpath.XPathFactoryConfigurationException;
43
44 import org.apache.log4j.Logger;
45 import org.bounce.FormConstraints;
46 import org.bounce.FormLayout;
47 import org.bounce.image.ImageLoader;
48 import org.xmlhammer.PreferencesHandler;
49 import org.xmlhammer.gui.Page;
50 import org.xmlhammer.gui.history.HistoryComboBox;
51 import org.xmlhammer.gui.history.HistoryComboBoxModel;
52 import org.xmlhammer.gui.history.HistoryUtilities;
53 import org.xmlhammer.gui.overview.ComboBoxNode;
54 import org.xmlhammer.gui.overview.OverviewNode;
55 import org.xmlhammer.gui.overview.OverviewTreeModel;
56 import org.xmlhammer.gui.util.UndoableComboBoxItemListener;
57 import org.xmlhammer.model.jaxp.Feature;
58 import org.xmlhammer.model.jaxp.JAXPXPathFactory;
59 import org.xmlhammer.model.jaxp.Mapping;
60 import org.xmlhammer.model.project.Project;
61 import org.xmlhammer.model.tools.xpath.XPath;
62
63 /***
64 * Input Panel.
65 *
66 * Allows to select either one URI, multiple URIs or
67 * a range of files.
68 *
69 * @version $Revision$, $Date$
70 * @author Edwin Dankert <edankert@gmail.com>
71 */
72
73 public class XPathPanel extends JPanel {
74 private static final long serialVersionUID = -6021755010826846525L;
75
76 private static final ImageIcon ERROR_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/obj16/error_obj.gif");
77 private static final ImageIcon TEXT_FIELD_ICON = ImageLoader.get().getImage( "/org/xmlhammer/gui/icons/elcl16/textfield_obj.gif");
78 private static final String[] RETURN_TYPES = { "BOOLEAN", "NODE", "NODESET", "NUMBER", "STRING"};
79
80 private Page page = null;
81 private JLabel errorLabel = null;
82 private ArrayList<OverviewNode> nodes = null;
83 private HistoryComboBox xpathField = null;
84 private JComboBox returnTypeField = null;
85 private XPathNode node = null;
86
87 /***
88 * @param view the underlying view.
89 */
90 public XPathPanel(XPathPage page) {
91 super(new FormLayout( 10, 2));
92
93 this.page = page;
94 setBorder( new EmptyBorder( 10, 10, 20, 10));
95
96 xpathField = new HistoryComboBox(page, new HistoryComboBoxModel(HistoryUtilities.getInstance().getExpressions()));
97 ((JTextField)xpathField.getEditor().getEditorComponent()).getDocument().addDocumentListener(new DocumentListener() {
98 public void insertUpdate(DocumentEvent event) {
99 checkXPath();
100 }
101
102 public void removeUpdate(DocumentEvent arg0) {
103 checkXPath();
104 }
105
106 public void changedUpdate(DocumentEvent arg0) {}
107 });
108 xpathField.setToolTipText( "Specify the XPath expression.");
109
110 errorLabel = new JLabel(ERROR_ICON);
111 errorLabel.setVisible(false);
112 errorLabel.setHorizontalAlignment(JLabel.LEFT);
113
114 if (page != null) {
115 page.getProjectView().getFieldManager().addField( xpathField);
116 }
117
118 returnTypeField = new JComboBox( RETURN_TYPES);
119 returnTypeField.setFont( returnTypeField.getFont().deriveFont(Font.PLAIN));
120 returnTypeField.setToolTipText( "Specify the XPath return type.");
121
122 if (page != null) {
123 page.getProjectView().getFieldManager().addField(returnTypeField);
124 }
125
126 returnTypeField.addItemListener(new UndoableComboBoxItemListener(page, returnTypeField));
127
128 add( new JLabel( "Expression:"), new FormConstraints( FormConstraints.LEFT, FormConstraints.RIGHT));
129 add( xpathField, FormLayout.RIGHT_FILL);
130 add( new JLabel(" "), FormLayout.LEFT);
131 add( errorLabel, FormLayout.RIGHT_FILL);
132 add( Box.createVerticalStrut(10), FormLayout.FULL_FILL);
133 add( new JLabel( "Return Type:"), new FormConstraints( FormConstraints.LEFT, FormConstraints.RIGHT));
134 add( returnTypeField, FormLayout.RIGHT);
135
136 nodes = new ArrayList<OverviewNode>();
137 node = new XPathNode(page, xpathField);
138 nodes.add(node);
139 nodes.add(new ComboBoxNode(page, returnTypeField, "returnType"));
140 }
141
142 private void checkXPath() {
143 Throwable cause = null;
144
145 try {
146 errorLabel.setVisible(false);
147 node.setError(null);
148 compileXPath(xpathField.getValue());
149 } catch (XPathFactoryConfigurationException e) {
150 cause = e;
151 } catch (XPathExpressionException e) {
152 cause = e;
153 } catch (Exception e) {
154
155 Logger.getLogger(getClass()).debug(e);
156 }
157
158 if (cause != null) {
159 while (cause.getCause() != null) {
160 cause = cause.getCause();
161 }
162
163 errorLabel.setText(cause.getMessage());
164 errorLabel.setVisible(true);
165 node.setError(cause.getMessage());
166 }
167 }
168
169 /***
170 * @return the XPath settings.
171 */
172 public XPath getXPath() {
173 XPath path = new XPath();
174
175 path.setExpression( xpathField.getValue());
176 path.setReturnType( (String)returnTypeField.getSelectedItem());
177
178 return path;
179 }
180
181 public void setXPath(XPath xpath) {
182 Logger.getLogger(this.getClass()).debug( "setXPath( "+xpath+")");
183 if ( xpath != null) {
184 xpathField.setValue( xpath.getExpression());
185 returnTypeField.setSelectedItem( xpath.getReturnType());
186
187
188 } else {
189 xpathField.setValue( null);
190 returnTypeField.setSelectedItem( RETURN_TYPES[2]);
191 }
192 }
193
194 String getXPathValue() {
195 return xpathField.getValue();
196 }
197
198 String getReturnType() {
199 return (String)returnTypeField.getSelectedItem();
200 }
201
202
203
204
205 public ArrayList<OverviewNode> getChildNodes() {
206 return nodes;
207 }
208
209 public void dispose() {
210
211 }
212
213 public void preferencesUpdated() {
214 checkXPath();
215 node.nodeChanged();
216 }
217
218 private class XPathNode implements OverviewNode, ItemListener, DocumentListener {
219 private OverviewNode parent = null;
220 private JComboBox xpathField = null;
221 private String error = null;
222
223 public XPathNode( OverviewNode parent, JComboBox xpathField) {
224 this.xpathField = xpathField;
225 this.parent = parent;
226
227 ((JTextField)xpathField.getEditor().getEditorComponent()).getDocument().addDocumentListener( this);
228 }
229
230 public String getNodeName() {
231 return (String)xpathField.getEditor().getItem() + " (expression)";
232 }
233
234 public ArrayList<OverviewNode> getChildNodes() {
235 return new ArrayList<OverviewNode>();
236 }
237
238 public OverviewNode getParentNode() {
239 return parent;
240 }
241
242 public Icon getNodeIcon() {
243
244
245
246
247 return TEXT_FIELD_ICON;
248 }
249
250 public void itemStateChanged( ItemEvent e) {
251 nodeChanged();
252 }
253
254 public void nodeChanged() {
255 OverviewNode node = parent;
256
257 while (node != null && !(node.getParentNode() instanceof OverviewTreeModel)) {
258 node = node.getParentNode();
259 }
260
261 if (node != null) {
262 ((OverviewTreeModel)node.getParentNode()).nodePathChanged( this);
263 }
264 }
265
266 public void setError(String error) {
267 this.error = error;
268 }
269
270 public String getError() {
271 return error;
272 }
273
274 public void insertUpdate(DocumentEvent arg0) {
275 nodeChanged();
276 }
277
278 public void removeUpdate(DocumentEvent arg0) {
279 nodeChanged();
280 }
281
282 public void changedUpdate(DocumentEvent arg0) {}
283 }
284
285 public XPathFactory getXPathFactory() throws XPathFactoryConfigurationException {
286 String objectModel = XPathFactory.DEFAULT_OBJECT_MODEL_URI;
287 JAXPXPathFactory.Settings settings = getXPathFactorySettings();
288
289 if ( settings.getValue() != null) {
290 System.setProperty( XPathFactory.DEFAULT_PROPERTY_NAME, settings.getValue());
291 }
292
293 if ( settings.getObjectModel() != null) {
294 objectModel = settings.getObjectModel();
295 }
296
297
298
299 XPathFactory factory = XPathFactory.newInstance( objectModel);
300
301 List<Feature> features = getXPathFactoryFeatures();
302
303 for ( Feature feature : features) {
304 factory.setFeature( feature.getName(), feature.isEnabled());
305 }
306
307 return factory;
308 }
309
310 private void compileXPath(String value) throws XPathFactoryConfigurationException, XPathExpressionException {
311 XPathFactory factory = getXPathFactory();
312
313 javax.xml.xpath.XPath xpath = factory.newXPath();
314
315 NamespaceContextMap nsMap = new NamespaceContextMap();
316
317 List<Mapping> mappings = getXPathFactoryMappings();
318
319 for (Mapping mapping : mappings) {
320 nsMap.put( mapping.getPrefix(), mapping.getUri());
321 }
322
323 xpath.setNamespaceContext( nsMap);
324
325 xpath.compile(value);
326 }
327
328 /***
329 * @return the JAXPXPathFactory.Settings, project specific if defined, otherwise from global preferences.
330 */
331 private JAXPXPathFactory.Settings getXPathFactorySettings() {
332 if (page != null) {
333 Project project = page.getProjectView().getProject();
334
335 if (project.getJAXPSettings().getJAXPXPathFactory().getSettings() != null) {
336 return project.getJAXPSettings().getJAXPXPathFactory().getSettings();
337 }
338 }
339
340 return PreferencesHandler.getInstance().getPreferences().getJAXPSettings().getJAXPXPathFactory().getSettings();
341 }
342
343 /***
344 * @return the JAXPXPathFactory.Features, project specific if defined, otherwise from global preferences.
345 */
346 private List<Feature> getXPathFactoryFeatures() {
347 if (page != null) {
348 Project project = page.getProjectView().getProject();
349 if ( project.getJAXPSettings().getJAXPXPathFactory().getFeatures() != null) {
350 return project.getJAXPSettings().getJAXPXPathFactory().getFeatures().getFeature();
351 }
352 }
353
354 return PreferencesHandler.getInstance().getPreferences().getJAXPSettings().getJAXPXPathFactory().getFeatures().getFeature();
355 }
356
357 /***
358 * @return the JAXPXPathFactory.Mappings, project specific if defined, otherwise from global preferences.
359 */
360 private List<Mapping> getXPathFactoryMappings() {
361 if (page != null) {
362 Project project = page.getProjectView().getProject();
363 if ( project.getJAXPSettings().getJAXPXPathFactory().getMappings() != null) {
364 return project.getJAXPSettings().getJAXPXPathFactory().getMappings().getMapping();
365 }
366 }
367
368 return PreferencesHandler.getInstance().getPreferences().getJAXPSettings().getJAXPXPathFactory().getMappings().getMapping();
369 }
370 }