001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.xslt.model.impl;
021:
022: import java.util.ArrayList;
023: import java.util.Collection;
024: import java.util.Collections;
025: import java.util.List;
026:
027: import javax.xml.namespace.QName;
028:
029: import org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent;
030: import org.netbeans.modules.xml.xam.dom.Attribute;
031: import org.netbeans.modules.xslt.model.AttributeValueTemplate;
032: import org.netbeans.modules.xslt.model.ContentElement;
033: import org.netbeans.modules.xslt.model.QualifiedNameable;
034: import org.netbeans.modules.xslt.model.ReferenceableXslComponent;
035: import org.netbeans.modules.xslt.model.SequenceConstructor;
036: import org.netbeans.modules.xslt.model.SequenceElement;
037: import org.netbeans.modules.xslt.model.XslComponent;
038: import org.netbeans.modules.xslt.model.XslReference;
039: import org.netbeans.modules.xslt.model.XslVisitor;
040: import org.netbeans.modules.xslt.model.enums.EnumValue;
041: import org.w3c.dom.Comment;
042: import org.w3c.dom.Element;
043: import org.w3c.dom.Node;
044: import org.w3c.dom.NodeList;
045: import org.w3c.dom.Text;
046:
047: /**
048: * @author ads
049: *
050: */
051: abstract class XslComponentImpl extends
052: AbstractDocumentComponent<XslComponent> implements XslComponent {
053:
054: XslComponentImpl(XslModelImpl model, Element e) {
055: super (model, e);
056: myAttributeAccess = new AttributeAccess(this );
057: }
058:
059: XslComponentImpl(XslModelImpl model, XslElements type) {
060: this (model, createNewElement(type, model));
061: }
062:
063: public abstract Class<? extends XslComponent> getComponentType();
064:
065: public abstract void accept(XslVisitor visitor);
066:
067: /***************************************************************************
068: *
069: * The methods below are frequently used in specific impls. So I place them here.
070: *
071: ***************************************************************************
072: */
073:
074: public AttributeValueTemplate createTemplate(QName qName) {
075: return AttributeValueTemplateImpl
076: .creatAttributeValueTemplate(qName);
077: }
078:
079: public AttributeValueTemplate createTemplate(String value) {
080: return AttributeValueTemplateImpl.creatAttributeValueTemplate(
081: this , value);
082: }
083:
084: public String getSelect() {
085: return getAttribute(XslAttributes.SELECT);
086: }
087:
088: public void setSelect(String select) {
089: setAttribute(XslAttributes.SELECT, select);
090: }
091:
092: /* (non-Javadoc)
093: * @see org.netbeans.modules.xslt.model.ContentElement#getContent()
094: */
095: public String getContent() {
096: StringBuilder text = new StringBuilder();
097: NodeList nodeList = getPeer().getChildNodes();
098: for (int i = 0; i < nodeList.getLength(); i++) {
099: Node node = nodeList.item(i);
100: if (node instanceof Element) {
101: break;
102: }
103: if (node instanceof Text && !(node instanceof Comment)) {
104: text.append(node.getNodeValue());
105: }
106: }
107: return text.toString();
108: }
109:
110: /* (non-Javadoc)
111: * @see org.netbeans.modules.xslt.model.ContentElement#setContent(java.lang.String)
112: */
113: public void setContent(String text) {
114: verifyWrite();
115: StringBuilder oldValue = new StringBuilder();
116: ArrayList<Node> toRemove = new ArrayList<Node>();
117: NodeList nodeList = getPeer().getChildNodes();
118:
119: Element ref = null;
120: for (int i = 0; i < nodeList.getLength(); i++) {
121: Node node = nodeList.item(i);
122: if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
123: ref = (Element) node;
124: break;
125: }
126: if (node instanceof Text
127: && node.getNodeType() != Node.COMMENT_NODE) {
128: toRemove.add(node);
129: oldValue.append(node.getNodeValue());
130: }
131: }
132:
133: getModel().getAccess()
134: .removeChildren(getPeer(), toRemove, this );
135: if (text != null) {
136: Text newNode = getModel().getDocument()
137: .createTextNode(text);
138: if (ref != null) {
139: getModel().getAccess().insertBefore(getPeer(), newNode,
140: ref, this );
141: } else {
142: getModel().getAccess().appendChild(getPeer(), newNode,
143: this );
144: }
145: }
146:
147: firePropertyChange(ContentElement.TEXT_CONTENT_PROPERTY,
148: oldValue == null ? null : oldValue.toString(), text);
149: fireValueChanged();
150: }
151:
152: /* (non-Javadoc)
153: * @see org.netbeans.modules.xslt.model.SequenceElement#getTrailingText()
154: */
155: public String getTrailingText() {
156: XslComponentImpl parent = getParent();
157: if (parent == null) {
158: return null;
159: }
160: return parent.getTrailingText(this );
161: }
162:
163: /* (non-Javadoc)
164: * @see org.netbeans.modules.xslt.model.SequenceElement#setTrailingText(java.lang.String)
165: */
166: public void setTrailingText(String text) {
167: XslComponentImpl parent = getParent();
168: if (parent == null) {
169: throw new IllegalStateException(
170: "Trailing text cannot be set for " + // NOI18N
171: "component that doesn't have parent element"); // NOI18N
172: }
173: parent.setTrailingText(SequenceElement.TEXT_CONTENT_PROPERTY,
174: text, this );
175: }
176:
177: /*
178: ***************************************************************************
179: */
180:
181: /*
182: * (non-Javadoc)
183: * @see org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent#getModel()
184: */
185: @Override
186: public XslModelImpl getModel() {
187: return (XslModelImpl) super .getModel();
188: }
189:
190: /* (non-Javadoc)
191: * @see org.netbeans.modules.xml.xam.AbstractComponent#getParent()
192: */
193: @Override
194: public XslComponentImpl getParent() {
195: return (XslComponentImpl) super .getParent();
196: }
197:
198: /* (non-Javadoc)
199: * @see org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent#lookupNamespaceURI(java.lang.String)
200: */
201: @Override
202: public String lookupNamespaceURI(String prefix) {
203: return lookupNamespaceURI(prefix, true);
204: }
205:
206: /* (non-Javadoc)
207: * @see org.netbeans.modules.xslt.model.XslComponent#createReferenceTo(org.netbeans.modules.xslt.model.ReferenceableXslComponent, java.lang.Class)
208: */
209: @SuppressWarnings("unchecked")
210: public <T extends ReferenceableXslComponent> XslReference<T> createReferenceTo(
211: T referenced, Class<T> type) {
212: // currently we only know how to resolve QualifiedNameable elements.
213: // later this impl could be changed respectively.
214: assert type.isAssignableFrom(QualifiedNameable.class);
215: return new GlobalReferenceImpl((QualifiedNameable) referenced,
216: type, this );
217: }
218:
219: /* (non-Javadoc)
220: * @see org.netbeans.modules.xslt.model.XslComponent#fromSameModel(org.netbeans.modules.xslt.model.XslComponent)
221: */
222: public boolean fromSameModel(XslComponent other) {
223: return getModel().equals(other.getModel());
224: }
225:
226: protected void setAttribute(XslAttributes attribute, EnumValue value) {
227: assert value == null || !value.isInvalid() : "Attempt to set up invalid enumeration value"; // NOI18N
228: setAttribute(attribute, (Object) value);
229: }
230:
231: protected void setAttribute(XslAttributes attribute,
232: AttributeValueTemplate avt) {
233: verifyWrite();
234: if (avt == null) {
235: setAttribute(attribute, (Object) null);
236: }
237: Object resultValue = avt;
238: if (!avt.isTemplate()) {
239: QName qName = avt.getQName();
240: if (qName != null) {
241: resultValue = getPrefixedName(qName.getNamespaceURI(),
242: qName.getLocalPart(), null, true);
243: }
244: }
245: if (resultValue instanceof String) {
246: Object old = null;
247: String s = getAttribute(attribute);
248: if (s != null) {
249: old = getAttributeValueOf(attribute, s);
250: }
251: setAttributeAndFireChange(attribute, (String) resultValue,
252: old, avt);
253: } else {
254: setAttribute(attribute, (Object) avt);
255: }
256: }
257:
258: protected void setAttribute(XslAttributes attribute, Object value) {
259: setAttribute(attribute.getName(), attribute, value);
260: }
261:
262: protected void setAttributeTokenList(XslAttributes attribute,
263: List<String> value) {
264: setAttribute(attribute, value, Lazy.SIMPLE_STRATEGY);
265: }
266:
267: protected void setAttribute(XslAttributes attribute,
268: XslReference<? extends ReferenceableXslComponent> value) {
269: verifyWrite();
270: if (value == null) {
271: setAttribute(attribute, (Object) null);
272: }
273: QName qName = value.getQName();
274: assert qName != null;
275: String resultValue = getPrefixedName(qName.getNamespaceURI(),
276: qName.getLocalPart(), null, true);
277: Object old = null;
278: String s = getAttribute(attribute);
279: if (s != null) {
280: old = getAttributeValueOf(attribute, s);
281: }
282: setAttributeAndFireChange(attribute, resultValue, old, value);
283: }
284:
285: protected <T extends QualifiedNameable> GlobalReferenceImpl<T> resolveGlobalReference(
286: Class<T> clazz, XslAttributes attrName) {
287: String value = getAttribute(attrName);
288: return getAtttributeAccess().resolveGlobalReference(clazz,
289: value);
290: }
291:
292: protected <T extends QualifiedNameable> List<XslReference<T>> resolveGlobalReferenceList(
293: Class<T> clazz, XslAttributes attrName) {
294: String value = getAttribute(attrName);
295: return getAtttributeAccess().resolveGlobalReferenceList(clazz,
296: value);
297: }
298:
299: @SuppressWarnings("unchecked")
300: protected <T extends ReferenceableXslComponent> void setAttributeList(
301: XslAttributes attr, List<XslReference<T>> collection) {
302: setAttribute(attr, collection, Lazy.REFERENCE_STRATEGY);
303: }
304:
305: protected void setAttribute(XslAttributes attr, List<QName> list) {
306: setAttribute(attr, list, Lazy.QNAME_STRATEGY);
307: }
308:
309: protected List<QName> getQNameList(String value) {
310: return getAtttributeAccess().getQNameList(value);
311: }
312:
313: /* (non-Javadoc)
314: * @see org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent#getAttributeValueOf(org.netbeans.modules.xml.xam.dom.Attribute, java.lang.String)
315: */
316: @Override
317: protected Object getAttributeValueOf(Attribute attr,
318: String stringValue) {
319: return getAtttributeAccess().getAttributeValueOf(attr,
320: stringValue);
321: }
322:
323: /* (non-Javadoc)
324: * @see org.netbeans.modules.xml.xam.dom.AbstractDocumentComponent#populateChildren(java.util.List)
325: */
326: @Override
327: protected void populateChildren(List<XslComponent> children) {
328: NodeList nl = getPeer().getChildNodes();
329: if (nl != null) {
330: for (int i = 0; i < nl.getLength(); i++) {
331: Node n = nl.item(i);
332: if (n instanceof Element) {
333: XslComponent comp = (XslComponent) getModel()
334: .getFactory().create((Element) n, this );
335: if (comp != null) {
336: children.add(comp);
337: }
338: }
339: }
340: }
341: }
342:
343: @Override
344: protected int findDomainIndex(Element e) {
345: int result = super .findDomainIndex(e);
346: if (result != -1) {
347: return result;
348: }
349:
350: // only sequence constructor could have non-xsl components.
351: if (!(this instanceof SequenceConstructor)) {
352: return -1;
353: }
354:
355: int domainInsertIndex = 0;
356: NodeList list = getPeer().getChildNodes();
357: for (int i = 0; i < list.getLength(); i++) {
358: Node node = list.item(i);
359: if (list.item(i) == e) {
360: return domainInsertIndex;
361: }
362: if (node instanceof Element) {
363: domainInsertIndex++;
364: }
365: }
366: return -1;
367: }
368:
369: protected String getTrailingText(XslComponent child) {
370: return getText(child, false, false);
371: }
372:
373: protected void setTrailingText(String propName, String text,
374: XslComponent child) {
375: setText(propName, text, child, false, false);
376: }
377:
378: protected static Element createNewElement(XslElements type,
379: XslModelImpl model) {
380: return model.getDocument().createElementNS(XSL_NAMESPACE,
381: type.getName());
382: }
383:
384: private AttributeAccess getAtttributeAccess() {
385: return myAttributeAccess;
386: }
387:
388: private <T> void setAttribute(XslAttributes attribute,
389: List<T> list, AttributeListValueStartegy<T> strategy) {
390: if (list == null) {
391: setAttribute(attribute, list);
392: }
393: verifyWrite();
394: StringBuilder builder = new StringBuilder();
395: for (T t : list) {
396: assert t != null;
397: String resultValue = strategy.toString(t, this );
398: builder.append(resultValue);
399: builder.append(" ");
400: }
401: String result = null;
402: if (builder.length() > 0) {
403: result = builder.substring(0, builder.length() - 1);
404: } else {
405: result = builder.toString();
406: }
407: Object old = null;
408: String s = getAttribute(attribute);
409: if (s != null) {
410: old = getAttributeValueOf(attribute, s);
411: }
412: setAttributeAndFireChange(attribute, result, old, list);
413: }
414:
415: private void setAttributeAndFireChange(XslAttributes attr,
416: String newStringValue, Object oldValue, Object newValue) {
417: setAttributeQuietly(attr, newStringValue);
418: firePropertyChange(attr.getName(), oldValue, newValue);
419: fireValueChanged();
420: }
421:
422: @SuppressWarnings("unchecked")
423: protected static final Collection<Class<? extends XslComponent>> EMPTY = Collections.EMPTY_LIST;
424:
425: protected static final Collection<Class<? extends XslComponent>> SEQUENCE_ELEMENTS = new ArrayList<Class<? extends XslComponent>>(
426: 1);
427:
428: private AttributeAccess myAttributeAccess;
429:
430: static {
431: SEQUENCE_ELEMENTS.add(SequenceElement.class);
432: }
433:
434: interface AttributeListValueStartegy<T> {
435:
436: String toString(T token, XslComponentImpl comp);
437: }
438:
439: static class SimpleStrategy implements
440: AttributeListValueStartegy<String> {
441:
442: public String toString(String token, XslComponentImpl comp) {
443: return token;
444: }
445: }
446:
447: static class ReferenceStrategy<T> implements
448: AttributeListValueStartegy<T> {
449:
450: public String toString(T token, XslComponentImpl comp) {
451: assert token instanceof XslReference;
452: QName qName = ((XslReference) token).getQName();
453: return comp.getPrefixedName(qName.getNamespaceURI(), qName
454: .getLocalPart(), null, true);
455: }
456: }
457:
458: static class QNameStrategy implements
459: AttributeListValueStartegy<QName> {
460:
461: public String toString(QName token, XslComponentImpl comp) {
462: return comp.getPrefixedName(token.getNamespaceURI(), token
463: .getLocalPart(), null, true);
464: }
465:
466: }
467:
468: static class Lazy {
469: static final SimpleStrategy SIMPLE_STRATEGY = new SimpleStrategy();
470:
471: static final ReferenceStrategy REFERENCE_STRATEGY = new ReferenceStrategy();
472:
473: static final QNameStrategy QNAME_STRATEGY = new QNameStrategy();
474: }
475: }
|