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: package org.netbeans.modules.xslt.model.impl;
020:
021: import java.util.LinkedHashSet;
022: import java.util.List;
023:
024: import javax.xml.namespace.QName;
025:
026: import org.netbeans.modules.xml.xam.AbstractReference;
027: import org.netbeans.modules.xml.xam.Model;
028: import org.netbeans.modules.xslt.model.QualifiedNameable;
029: import org.netbeans.modules.xslt.model.ReferenceableXslComponent;
030: import org.netbeans.modules.xslt.model.Stylesheet;
031: import org.netbeans.modules.xslt.model.XslModel;
032: import org.netbeans.modules.xslt.model.XslReference;
033:
034: /**
035: *
036: * @author ads
037: *
038: */
039: class GlobalReferenceImpl<T extends QualifiedNameable> extends
040: AbstractReference<T> implements XslReference<T> {
041:
042: // used by XslComponentImpl#createReferenceTo method
043: GlobalReferenceImpl(T referenced, Class<T> referencedType,
044: XslComponentImpl parent) {
045: super (referenced, referencedType, parent);
046: }
047:
048: // used by resolve method
049: GlobalReferenceImpl(Class<T> referencedType,
050: XslComponentImpl parent, String ref) {
051: super (referencedType, parent, ref);
052: initReferenceString(ref);
053: }
054:
055: /* (non-Javadoc)
056: * @see org.netbeans.modules.xml.xam.Reference#get()
057: */
058: public T get() {
059: if (getReferenced() == null) {
060: setReferenced(find());
061: }
062: return super .getReferenced();
063: }
064:
065: @Override
066: public String getRefString() {
067: if (refString == null) {
068: T referenced = super .getReferenced();
069: assert referenced != null;
070: myQname = referenced.getName();
071: if (myQname != null) {
072: String result;
073: myPrefix = myQname.getPrefix();
074: myLocalPart = myQname.getLocalPart();
075: if (myPrefix == null || myPrefix.length() == 0) {
076: result = myLocalPart;
077: } else {
078: result = myPrefix + ":" + myLocalPart;
079: }
080:
081: if (getParent().isInDocumentModel()) {
082: refString = result;
083: } else {
084: return result;
085: }
086: }
087: }
088: return super .getRefString();
089: }
090:
091: /* (non-Javadoc)
092: * @see org.netbeans.modules.xslt.model.XslReference#getQName()
093: */
094: public QName getQName() {
095: checkParentNotRemovedFromModel();
096: if (myQname == null) {
097: T referenced = super .getReferenced();
098: myQname = referenced.getName();
099: }
100: return myQname;
101: }
102:
103: @Override
104: public boolean equals(Object obj) {
105: if (this == obj) {
106: return true;
107: } else if (!(obj instanceof GlobalReferenceImpl)) {
108: return false;
109: } else {
110: GlobalReferenceImpl<? extends ReferenceableXslComponent> ref = (GlobalReferenceImpl<? extends ReferenceableXslComponent>) obj;
111: return getParent().equals(ref.getParent())
112: && getQName().equals(ref.getQName());
113: }
114: }
115:
116: @Override
117: public int hashCode() {
118: return getParent().hashCode();
119: }
120:
121: @Override
122: public XslComponentImpl getParent() {
123: return (XslComponentImpl) super .getParent();
124: }
125:
126: @Override
127: public boolean references(T target) {
128: if (target instanceof QualifiedNameable) {
129: QualifiedNameable nameble = (QualifiedNameable) target;
130: return nameble.getName() != null
131: && nameble.getName().equals(getQName())
132: && !isBroken() && get() == target;
133: }
134: return super .references(target);
135: }
136:
137: public void refresh() {
138: getRefString();
139: setReferenced(null);
140: }
141:
142: protected T getReferenced() {
143: if (super .getReferenced() == null) {
144: checkParentPartOfModel();
145: } else {
146: if (super .getParent().getModel() == null) {
147: throw new IllegalStateException(
148: "Referencing component has been removed from model."); //NOI18N
149: }
150: if (super .getReferenced().getModel() == null) {
151: throw new IllegalStateException(
152: "Referenced component has been removed from model."); //NOI18N
153: }
154: }
155: return super .getReferenced();
156: }
157:
158: /**
159: * @exception IllegalStateException if parent is already removed from a model.
160: */
161: protected void checkParentNotRemovedFromModel() {
162: if (getParent().getModel() == null) {
163: throw new IllegalStateException(
164: "Referencing component has been removed from model."); // NOI18N
165: }
166: }
167:
168: /**
169: * @exception IllegalStateException if parent is not part of a model.
170: */
171: protected void checkParentPartOfModel() {
172: if (!getParent().isInDocumentModel()) {
173: throw new IllegalStateException(
174: "Referencing component is not part of model."); //NOI18N
175: }
176: }
177:
178: /**
179: * Calculate the QName based on the local information
180: * without loading the referenced object.
181: */
182: protected QName calculateQNameLocally() {
183: String prefix = getPrefix();
184: String localPart = getLocalPart();
185: String namespace = null;
186: namespace = getParent().lookupNamespaceURI(prefix);
187: if (namespace == null) {
188: // prefix part is namespace name, which could be the namespace uri
189: // itself
190: String temp = getParent().lookupPrefix(prefix);
191: if (temp != null) {
192: prefix = temp;
193: namespace = prefix;
194: }
195: }
196:
197: if (prefix == null) {
198: return new QName(namespace, localPart);
199: } else {
200: return new QName(namespace, localPart, prefix);
201: }
202: }
203:
204: private String getLocalPart() {
205: if (myLocalPart == null) {
206: String ref = getRefString();
207: if (ref == null) {
208: return null;
209: }
210: String[] parts = ref.split(":"); //NOI18N
211: if (parts.length == 2) {
212: return parts[1];
213: } else {
214: return parts[0];
215: }
216: } else {
217: return myLocalPart;
218: }
219: }
220:
221: private String getPrefix() {
222: if (myPrefix == null) {
223: String ref = getRefString();
224: if (ref == null) {
225: return null;
226: }
227: String[] parts = ref.split(":"); //NOI18N
228: if (parts.length == 2) {
229: return parts[0];
230: } else {
231: return null;
232: }
233: } else {
234: return myPrefix;
235: }
236: }
237:
238: private void initReferenceString(String ref) {
239: assert ref != null;
240: refString = ref;
241: String[] parts = refString.split(":"); //NOI18N
242: if (parts.length == 2) {
243: myPrefix = parts[0];
244: myLocalPart = parts[1];
245: } else {
246: myPrefix = null;
247: myLocalPart = parts[0];
248: }
249: }
250:
251: private T find() {
252: LinkedHashSet<XslModel> list = Utilities
253: .getAvailibleModels(getParent().getModel());
254: for (XslModel model : list) {
255: if (Model.State.VALID.equals(model.getState())) {
256: Stylesheet stylesheet = model.getStylesheet();
257: if (stylesheet == null) {
258: continue;
259: }
260: List<T> children = stylesheet.getChildren(getType());
261: T result = find(children);
262: if (result != null) {
263: return result;
264: }
265: }
266: }
267: return null;
268: }
269:
270: private T find(List<T> children) {
271: for (T t : children) {
272: QName name = t.getName();
273: if (name == null) {
274: continue;
275: }
276: String localPart = name.getLocalPart();
277: String ns = name.getNamespaceURI();
278: if (getLocalPart().equals(localPart)
279: && Utilities.equals(getQName().getNamespaceURI(),
280: ns)) {
281: return t;
282: }
283: }
284: return null;
285: }
286:
287: private QName myQname;
288:
289: private String myPrefix;
290:
291: private String myLocalPart;
292:
293: }
|