1 /*******************************************************************************
\r
2 * Copyright (c) 2005 Oracle Corporation.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * Oracle Corporation - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.eclipse.jst.pagedesigner.dtmanager.converter.internal;
\r
13 import java.net.URL;
\r
14 import java.util.HashMap;
\r
15 import java.util.Map;
\r
17 import javax.servlet.jsp.el.ELException;
\r
18 import javax.xml.xpath.XPath;
\r
19 import javax.xml.xpath.XPathConstants;
\r
20 import javax.xml.xpath.XPathExpressionException;
\r
21 import javax.xml.xpath.XPathFactory;
\r
23 import org.eclipse.core.runtime.ISafeRunnable;
\r
24 import org.eclipse.core.runtime.SafeRunner;
\r
25 import org.eclipse.jface.resource.ImageDescriptor;
\r
26 import org.eclipse.jst.jsf.common.metadata.Trait;
\r
27 import org.eclipse.jst.jsf.common.metadata.internal.IImageDescriptorProvider;
\r
28 import org.eclipse.jst.jsf.common.metadata.internal.IMetaDataSourceModelProvider;
\r
29 import org.eclipse.jst.jsf.common.metadata.internal.IResourceURLProvider;
\r
30 import org.eclipse.jst.pagedesigner.PDPlugin;
\r
31 import org.eclipse.jst.pagedesigner.converter.IConverterFactory;
\r
32 import org.eclipse.jst.pagedesigner.converter.ITagConverter;
\r
33 import org.eclipse.jst.pagedesigner.dtmanager.DTManager;
\r
34 import org.eclipse.jst.pagedesigner.dtmanager.IDTInfo;
\r
35 import org.eclipse.jst.pagedesigner.dtmanager.converter.ITagConverterDecorator;
\r
36 import org.eclipse.jst.pagedesigner.dtmanager.dtinfo.ResolveAttributeValue;
\r
37 import org.eclipse.jst.pagedesigner.dtmanager.dtinfo.TagDecorateInfo;
\r
38 import org.eclipse.jst.pagedesigner.preview.PageExpressionContext;
\r
39 import org.w3c.dom.Element;
\r
40 import org.w3c.dom.Node;
\r
41 import org.w3c.dom.NodeList;
\r
42 import org.w3c.dom.Text;
\r
45 * ITagConverterDecorator implementation for DTTagConverter.
\r
47 * @author Ian Trimble - Oracle
\r
49 public class DTTagConverterDecorator implements ITagConverterDecorator
\r
52 private static final String DECORATE_INFO_ID_DESIGN = "vpd-decorate-design"; //$NON-NLS-1$
\r
53 private static final String DECORATE_INFO_ID_PREVIEW = "vpd-decorate-preview"; //$NON-NLS-1$
\r
54 private static final String MD_PLUGIN_LOCATION = "$metadata-plugin-location$"; //$NON-NLS-1$
\r
60 * org.eclipse.jst.pagedesigner.dtmanager.converter.ITagConverterDecorator
\r
61 * #decorate(org.eclipse.jst.pagedesigner.converter.ITagConverter)
\r
63 public void decorate(ITagConverter tagConverter)
\r
65 if (!(tagConverter instanceof DTTagConverter))
\r
67 throw new IllegalArgumentException(
\r
68 "ITagConverter argument must be an instance of DTTagConverter"); //$NON-NLS-1$
\r
70 DTTagConverter dtTagConverter = (DTTagConverter) tagConverter;
\r
72 if (dtTagConverter.getMode() == IConverterFactory.MODE_DESIGNER)
\r
74 decorateFromDTInfo(dtTagConverter, DECORATE_INFO_ID_DESIGN);
\r
75 } else if (dtTagConverter.getMode() == IConverterFactory.MODE_PREVIEW)
\r
77 decorateFromDTInfo(dtTagConverter, DECORATE_INFO_ID_PREVIEW);
\r
80 if (tagConverter.getResultElement() == null
\r
81 && tagConverter.isVisualByHTML())
\r
83 createUnknownTagRepresentation(dtTagConverter);
\r
88 * Performs decoration of the specified DTTagConverter instance from IDTInfo
\r
89 * (metadata) for the specified (by ID) TagDecorateInfo.
\r
91 * @param dtTagConverter
\r
92 * DTTagConverter instance.
\r
93 * @param tagDecorateInfoID
\r
94 * ID of the TagDecorateInfo to be located in metadata.
\r
96 protected void decorateFromDTInfo(DTTagConverter dtTagConverter,
\r
97 String tagDecorateInfoID)
\r
99 Element srcElement = dtTagConverter.getHostElement();
\r
100 DTManager dtManager = DTManager.getInstance();
\r
101 IDTInfo dtInfo = dtManager.getDTInfo(srcElement);
\r
102 if (dtInfo != null)
\r
104 TagDecorateInfo tdInfo = dtInfo
\r
105 .getTagDecorateInfo(tagDecorateInfoID);
\r
106 if (tdInfo != null)
\r
108 dtTagConverter.setMultiLevel(tdInfo.isMultiLevel());
\r
109 dtTagConverter.setNeedBorderDecorator(tdInfo
\r
110 .isNeedBorderDecorator());
\r
111 dtTagConverter.setNeedTableDecorator(tdInfo
\r
112 .isNeedTableDecorator());
\r
113 if (tdInfo.isNonVisual())
\r
115 setNonVisual(dtTagConverter, dtInfo, tdInfo
\r
116 .getNonVisualImagePath());
\r
118 if (tdInfo.isResolveChildText())
\r
120 resolveChildText(dtTagConverter.getResultElement(), dtInfo);
\r
122 if (tdInfo.isSetNonVisualChildElements())
\r
124 setNonVisualChildElements(dtTagConverter, srcElement);
\r
126 dtTagConverter.setWidget(tdInfo.isWidget());
\r
127 dtTagConverter.setMinHeight(tdInfo.getMinHeight());
\r
128 dtTagConverter.setMinWidth(tdInfo.getMinWidth());
\r
129 ResolveAttributeValue resAttrValue = tdInfo
\r
130 .getResolveAttributeValue();
\r
131 if (resAttrValue != null)
\r
133 String attributeName = resAttrValue.getAttributeName();
\r
134 if (attributeName != null && attributeName.length() > 0)
\r
136 resolveAttributeValue(dtTagConverter.getHostElement(),
\r
137 dtTagConverter.getResultElement(),
\r
138 attributeName, dtInfo, tagDecorateInfoID);
\r
146 * Creates a visual representation result Element for an unknown tag.
\r
148 * @param dtTagConverter
\r
149 * DTTagConverter instance.
\r
151 protected void createUnknownTagRepresentation(DTTagConverter dtTagConverter)
\r
153 Element element = dtTagConverter.createElement("span"); //$NON-NLS-1$
\r
154 element.setAttribute("style", "color:red;font-weight:bold;"); //$NON-NLS-1$ //$NON-NLS-2$
\r
155 Text text = dtTagConverter
\r
156 .createText("<" + dtTagConverter.getHostElement().getTagName() + "/>"); //$NON-NLS-1$ //$NON-NLS-2$
\r
157 element.appendChild(text);
\r
158 dtTagConverter.setResultElement(element);
\r
159 dtTagConverter.setWidget(true);
\r
163 * Adds child Elements of the specified source Element to the specified
\r
164 * DTTagConverter instance's collection of non-visual children.
\r
166 * @param dtTagConverter
\r
167 * DTTagConverter instance.
\r
168 * @param srcElement
\r
169 * Source Element for which child Elements are to be added.
\r
171 protected void setNonVisualChildElements(DTTagConverter dtTagConverter,
\r
172 Element srcElement)
\r
174 NodeList childNodes = srcElement.getChildNodes();
\r
175 for (int i = 0; i < childNodes.getLength(); i++)
\r
177 Node curNode = childNodes.item(i);
\r
178 if (curNode.getNodeType() == Node.ELEMENT_NODE)
\r
180 dtTagConverter.addNonVisualChildElement((Element) curNode);
\r
186 * Performs simple EL resolution for the child Text Node of the specified
\r
187 * source Element instance.
\r
189 * @param srcElement
\r
190 * Source Element for which child Text Node EL resolution is to
\r
193 * IDTInfo instance.
\r
195 protected void resolveChildText(Element srcElement, IDTInfo dtInfo)
\r
197 if (srcElement != null)
\r
199 NodeList childNodes = srcElement.getChildNodes();
\r
200 for (int i = 0; i < childNodes.getLength(); i++)
\r
202 Node childNode = childNodes.item(i);
\r
203 if (childNode.getNodeType() == Node.TEXT_NODE)
\r
205 Text textNode = (Text) childNode;
\r
206 String textNodeValue = textNode.getNodeValue();
\r
209 String newTextNodeValue;
\r
210 if (textNodeValue.contains(MD_PLUGIN_LOCATION))
\r
212 newTextNodeValue = resolveMDPluginLocation(
\r
213 textNodeValue, dtInfo);
\r
216 //Bug 319317 - Third-party plug-in providing javax.servlet.jsp.el version 2.1 or greater breaks WPE preview
\r
217 Map options = new HashMap();
\r
218 options.put("ELEMENT", srcElement); //$NON-NLS-1$
\r
219 newTextNodeValue = (String) PageExpressionContext
\r
220 .getCurrent().evaluateExpression(
\r
221 textNodeValue, String.class, options);
\r
223 if (newTextNodeValue != null
\r
224 && !textNodeValue.equals(newTextNodeValue))
\r
226 textNode.setNodeValue(newTextNodeValue);
\r
228 } catch (Exception ex)
\r
230 // ignore - could not resolve, do not change existing
\r
239 * Performs simple EL resolution for the value of the specified attribute of
\r
240 * the specified Element.
\r
242 * @param srcElement
\r
244 * @param targetElement
\r
245 * Source Element instance.
\r
246 * @param attributeName
\r
247 * Name of attribute for which the value should be resolved.
\r
249 * IDTInfo instance.
\r
250 * @param tagDecorateInfoID
\r
252 protected void resolveAttributeValue(Element srcElement,
\r
253 Element targetElement, String attributeName, IDTInfo dtInfo,
\r
254 String tagDecorateInfoID)
\r
256 if (targetElement != null)
\r
258 String oldAttributeValue = null;
\r
259 String targetAttributeName = attributeName;
\r
260 // determine if attributeName is XPath and re-target as appropriate
\r
261 if (attributeName.contains("/")) { //$NON-NLS-1$
\r
262 int lastSlashPos = attributeName.lastIndexOf("/"); //$NON-NLS-1$
\r
263 String xPathExpression = attributeName.substring(0,
\r
265 XPath xPath = XPathFactory.newInstance().newXPath();
\r
268 Object resultObject = xPath.evaluate(xPathExpression,
\r
269 targetElement, XPathConstants.NODE);
\r
270 if (resultObject instanceof Element)
\r
272 targetElement = (Element) resultObject;
\r
273 targetAttributeName = attributeName
\r
274 .substring(lastSlashPos + 1);
\r
276 else if (resultObject instanceof Text)
\r
278 Node parentNode = ((Text)resultObject).getParentNode();
\r
279 if (parentNode instanceof Element)
\r
281 parentNode.normalize();
\r
282 targetAttributeName = IAttributeValueResolver.TEXT_NODE_KEY;
\r
283 oldAttributeValue = ((Text)resultObject).getNodeValue();
\r
287 catch (XPathExpressionException xee)
\r
289 // could not evaluate - leave targetElement and
\r
290 // targetAttributeName unchanged
\r
295 if (!IAttributeValueResolver.TEXT_NODE_KEY.equals(targetAttributeName))
\r
297 oldAttributeValue = targetElement.getAttribute(targetAttributeName);
\r
300 if (oldAttributeValue != null && oldAttributeValue.length() > 0)
\r
302 String newAttributeValue;
\r
303 if (oldAttributeValue.contains(MD_PLUGIN_LOCATION))
\r
305 newAttributeValue = resolveMDPluginLocation(
\r
306 oldAttributeValue, dtInfo);
\r
310 newAttributeValue = resolveAttributeValue(srcElement,
\r
311 targetElement, targetAttributeName,
\r
312 oldAttributeValue, tagDecorateInfoID);
\r
314 if (newAttributeValue != null
\r
315 && !oldAttributeValue.equals(newAttributeValue))
\r
317 if (IAttributeValueResolver.TEXT_NODE_KEY
\r
318 .equals(targetAttributeName))
\r
320 for (int i = targetElement.getChildNodes().getLength()-1; i >= 0; i--)
\r
322 Node childNode = targetElement.getChildNodes().item(i);
\r
323 if (childNode.getNodeType() == Node.TEXT_NODE)
\r
325 targetElement.removeChild(childNode);
\r
328 targetElement.appendChild(targetElement.getOwnerDocument().createTextNode(newAttributeValue));
\r
332 targetElement.setAttribute(targetAttributeName,
\r
333 newAttributeValue);
\r
340 private String resolveAttributeValue(final Element originalElement,
\r
341 final Element convertedElement,
\r
342 final String convertedAttributeName, final String oldAttributeValue,
\r
343 final String tagDecorateInfoID)
\r
345 String newValue = null;
\r
346 boolean valueResolved = false;
\r
347 final String[] result = new String[1];
\r
349 for (final IAttributeValueResolver resolver : AttributeValueResolverRegistryReader
\r
350 .getInstance().getExtensions())
\r
352 SafeRunner.run(new ISafeRunnable()
\r
354 public void handleException(Throwable exception)
\r
358 "While resolving attribute in converter decorator", exception); //$NON-NLS-1$
\r
361 public void run() throws Exception
\r
363 if (resolver.canResolve(originalElement,
\r
364 convertedElement, convertedAttributeName, oldAttributeValue))
\r
366 result[0] = resolver.resolveAttribute(
\r
367 originalElement, convertedElement,
\r
368 convertedAttributeName, oldAttributeValue);
\r
372 if (result[0] != null)
\r
374 newValue = result[0];
\r
375 valueResolved = true;
\r
380 if (!valueResolved &&
\r
381 // maintain backward compatibility: only do this default
\r
382 // behaviour for the preview
\r
383 tagDecorateInfoID.equals(DECORATE_INFO_ID_PREVIEW))
\r
385 // fall- through to default case.
\r
389 PageExpressionContext current = PageExpressionContext.getCurrent();
\r
390 if (current != null)
\r
392 //Bug 319317 - Third-party plug-in providing javax.servlet.jsp.el version 2.1 or greater breaks WPE preview
\r
393 Map options = new HashMap();
\r
394 options.put("ELEMENT", originalElement); //$NON-NLS-1$
\r
395 return (String) current
\r
396 .evaluateExpression(oldAttributeValue, String.class, options);
\r
398 } catch (ELException e)
\r
400 // ignore. we will just return null since couldn't resolve
\r
407 * Resolves any instance of MD_PLUGIN_LOCATION in input String.
\r
412 * IDTInfo instance.
\r
413 * @return Input String with any instance of MD_PLUGIN_LOCATION resolved.
\r
415 protected String resolveMDPluginLocation(String input, IDTInfo dtInfo)
\r
417 String output = input;
\r
418 if (input != null && input.contains(MD_PLUGIN_LOCATION))
\r
420 int tokenStart = input.indexOf(MD_PLUGIN_LOCATION);
\r
421 int tokenEnd = tokenStart + MD_PLUGIN_LOCATION.length();
\r
422 String prefix = input.substring(0, tokenStart);
\r
423 String suffix = input.substring(tokenEnd);
\r
424 Trait trait = dtInfo.getTrait();
\r
425 IMetaDataSourceModelProvider mdSourceModelProvider = trait
\r
426 .getSourceModelProvider();
\r
427 IResourceURLProvider resourceURLProvider = (IResourceURLProvider) mdSourceModelProvider
\r
428 .getAdapter(IResourceURLProvider.class);
\r
429 URL url = resourceURLProvider.getResourceURL("/META-INF/"); //$NON-NLS-1$
\r
430 String resolvedToken = url.toExternalForm();
\r
431 resolvedToken = resolvedToken.substring(0,
\r
432 resolvedToken.length() - 10);
\r
433 output = prefix + resolvedToken + suffix;
\r
439 * Sets DTTagConverter instance as non-visual as HTML and sets the
\r
440 * ImageDescriptor instance that DTTagConverter will use to return an Image
\r
443 * @param dtTagConverter
\r
444 * DTTagConverter instance.
\r
446 * IDTInfo instance.
\r
448 * Image path, relative to declaring plug-in.
\r
450 protected void setNonVisual(DTTagConverter dtTagConverter, IDTInfo dtInfo,
\r
453 dtTagConverter.setVisualByHTML(false);
\r
454 if (imagePath != null && imagePath.length() > 0)
\r
456 Trait trait = dtInfo.getTrait();
\r
457 IImageDescriptorProvider imgDescProvider = (IImageDescriptorProvider) trait
\r
458 .getSourceModelProvider().getAdapter(
\r
459 IImageDescriptorProvider.class);
\r
460 if (imgDescProvider != null)
\r
462 ImageDescriptor imageDescriptor = imgDescProvider
\r
463 .getImageDescriptor(imagePath);
\r
464 dtTagConverter.setVisualImageDescriptor(imageDescriptor);
\r