KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > schema > completion > util > CompletionUtil


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.xml.schema.completion.util;
20
21 import java.net.URI JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.StringTokenizer JavaDoc;
25 import javax.xml.XMLConstants JavaDoc;
26 import javax.xml.namespace.QName JavaDoc;
27 import org.netbeans.modules.xml.axi.AXIComponent;
28 import org.netbeans.modules.xml.axi.AXIDocument;
29 import org.netbeans.modules.xml.axi.AXIModel;
30 import org.netbeans.modules.xml.axi.AXIModelFactory;
31 import org.netbeans.modules.xml.axi.AbstractAttribute;
32 import org.netbeans.modules.xml.axi.AbstractElement;
33 import org.netbeans.modules.xml.axi.AnyAttribute;
34 import org.netbeans.modules.xml.axi.AnyElement;
35 import org.netbeans.modules.xml.axi.Attribute;
36 import org.netbeans.modules.xml.axi.Element;
37 import org.netbeans.modules.xml.schema.completion.*;
38 import org.netbeans.modules.xml.schema.completion.spi.CompletionContext;
39 import org.netbeans.modules.xml.schema.completion.spi.CompletionModelProvider.CompletionModel;
40 import org.netbeans.modules.xml.schema.model.Form;
41 import org.netbeans.modules.xml.text.syntax.SyntaxElement;
42 import org.netbeans.modules.xml.text.syntax.dom.StartTag;
43 import org.w3c.dom.Attr JavaDoc;
44 import org.w3c.dom.NamedNodeMap JavaDoc;
45
46 /**
47  *
48  * @author Samaresh (Samaresh.Panda@Sun.Com)
49  */

50 public class CompletionUtil {
51     
52     /**
53      * No instantiation.
54      */

55     private CompletionUtil() {
56     }
57     
58     /**
59      * Returns the StartTag corresponding to the root element.
60      */

61     public static StartTag getRoot(SyntaxElement se) {
62         StartTag root = null;
63         while( se != null) {
64             if(se instanceof StartTag) {
65                 root = (StartTag)se;
66             }
67             se = se.getPrevious();
68         }
69         
70         return root;
71     }
72     
73     /**
74      * For debugging purposes only.
75      */

76     public static void printPath(List JavaDoc<QName JavaDoc> path) {
77         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
78         for(QName JavaDoc item: path) {
79             if(buffer.toString().equals(""))
80                 buffer.append(item);
81             else
82                 buffer.append("/" + item);
83         }
84         //System.out.println(buffer);
85
}
86     
87     public static boolean isRoot(String JavaDoc tag, CompletionModel cm) {
88         if(cm == null)
89             return false;
90         AXIModel model = AXIModelFactory.getDefault().getModel(cm.getSchemaModel());
91         for(AbstractElement element : model.getRoot().getChildElements()) {
92             if(tag.endsWith(element.getName()))
93                 return true;
94         }
95         return false;
96     }
97     
98     /**
99      * Returns the prefix from the element's tag.
100      */

101     public static String JavaDoc getPrefixFromTag(String JavaDoc tagName) {
102         if(tagName == null) return null;
103         return (tagName.indexOf(":") == -1) ? null :
104             tagName.substring(0, tagName.indexOf(":"));
105     }
106     
107     /**
108      * Returns the local name from the element's tag.
109      */

110     public static String JavaDoc getLocalNameFromTag(String JavaDoc tagName) {
111         if(tagName == null) return null;
112         return (tagName.indexOf(":") == -1) ? tagName :
113             tagName.substring(tagName.indexOf(":")+1, tagName.length());
114     }
115     
116     /**
117      * Returns any prefix declared with this namespace. For example, if
118      * the namespace was declared as xmlns:po, the prefix 'po' will be returned.
119      * Returns null for declaration that contains no prefix.
120      */

121     public static String JavaDoc getPrefixFromNamespaceDeclaration(String JavaDoc namespace) {
122         if(namespace == null) return null;
123         return (namespace.indexOf(":") == -1) ?
124             null : namespace.substring(namespace.indexOf(":")+1);
125     }
126     
127     /**
128      * Returns the list of prefixes declared against the specified
129      * target namespace. For example a document may declare namespaces as follows:
130      * xmlns="tns" xmlns:a="tns" xmlns:b="tns"
131      * The returned list in this case will be [a, b, null]
132      */

133     public static List JavaDoc<String JavaDoc> getPrefixesAgainstTargetNamespace(
134             CompletionContextImpl context, String JavaDoc namespace) {
135         List JavaDoc<String JavaDoc> list = new ArrayList JavaDoc<String JavaDoc>();
136         NamedNodeMap JavaDoc attributes = context.getDocRootAttributes();
137         for(int index=0; index<attributes.getLength(); index++) {
138             Attr JavaDoc attr = (Attr JavaDoc)attributes.item(index);
139             if(!attr.getName().startsWith(XMLConstants.XMLNS_ATTRIBUTE))
140                 continue;
141             if(attr.getValue().equals(namespace)) {
142                 String JavaDoc prefix = getPrefixFromNamespaceDeclaration(attr.getName());
143                 list.add(prefix);
144             }
145         }
146         
147         return list;
148     }
149             
150     /**
151      * Populates schema URIs from schemaLocation and noNamespaceSchemaLocation
152      * attributes of the doc-root. For schemaLocation, uses the 2nd token, where as
153      * for the later, uses every token.
154      */

155     public static void loadSchemaURIs(String JavaDoc schemaLocation, List JavaDoc<URI JavaDoc> uris, boolean noNS) {
156         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(
157                 schemaLocation.replaceAll("\n", " "), " "); //NOI18N
158
while(st.hasMoreTokens()) {
159             URI JavaDoc uri = null;
160             try {
161                 String JavaDoc token1 = st.nextToken().trim();
162                 if(noNS) {
163                     uri = URI.create(token1); //every token is a schema
164
if(uri != null)
165                         uris.add(uri);
166                     continue;
167                 }
168                 if(st.hasMoreTokens()) {
169                     String JavaDoc token2 = st.nextToken().trim();
170                         uri = URI.create(token2); //every 2nd token is a schema
171
if(uri != null)
172                             uris.add(uri);
173                 }
174             } catch (Exception JavaDoc ex) {
175                 continue;
176             }
177         }
178     }
179     
180     /**
181      * Returns the list of attributes for a given element.
182      */

183     public static List JavaDoc<CompletionResultItem> getAttributes(
184             CompletionContextImpl context) {
185         Element element = findAXIElementAtContext(context);
186         if(element == null)
187             return null;
188         List JavaDoc<CompletionResultItem> results = new ArrayList JavaDoc<CompletionResultItem>();
189         String JavaDoc typedChars = context.getTypedChars();
190         for(AbstractAttribute aa: element.getAttributes()) {
191             if(aa.getTargetNamespace() == null) { //no namespace
192
results.add(createResultItem(aa, null, context));
193                 continue;
194             }
195             if(aa instanceof AnyAttribute) {
196                 results.addAll(substituteAny((AnyAttribute)aa, context));
197                 continue;
198             }
199             addNSAwareCompletionItems(aa,context,null,results);
200         }
201         return results;
202     }
203     
204     /**
205      * Returns the list of child-elements for a given element.
206      */

207     public static List JavaDoc<CompletionResultItem> getElements(
208             CompletionContextImpl context) {
209         Element element = findAXIElementAtContext(context);
210         if(element == null)
211             return null;
212         
213         List JavaDoc<CompletionResultItem> results = new ArrayList JavaDoc<CompletionResultItem>();
214         String JavaDoc typedChars = context.getTypedChars();
215         for(AbstractElement ae: element.getChildElements()) {
216             if(ae.getTargetNamespace() == null) { //no namespace
217
results.add(createResultItem(ae, null, context));
218                 continue;
219             }
220             if(ae instanceof AnyElement) {
221                 results.addAll(substituteAny((AnyElement)ae, context));
222                 continue;
223             }
224             addNSAwareCompletionItems(ae,context,null,results);
225         }
226         return results;
227     }
228     
229     private static void addNSAwareCompletionItems(AXIComponent axi, CompletionContextImpl context,
230             CompletionModel cm, List JavaDoc<CompletionResultItem> results) {
231         String JavaDoc typedChars = context.getTypedChars();
232         CompletionResultItem item = null;
233         if(!isFormQualified(axi)) {
234             item = createResultItem(axi, null, context);
235             if(typedChars == null) {
236                 results.add(item);
237             } else if(item.getReplacementText().startsWith(typedChars)) {
238                 results.add(item);
239             }
240             return;
241         }
242         //namespace aware items
243
List JavaDoc<String JavaDoc> prefixes = getPrefixes(context, axi, cm);
244         for(String JavaDoc prefix: prefixes) {
245             item = createResultItem(axi, prefix, context);
246             if(typedChars == null) {
247                 results.add(item);
248             } else if(item.getReplacementText().startsWith(typedChars)) {
249                 results.add(item);
250             }
251         }
252     }
253     
254     private static CompletionResultItem createResultItem(AXIComponent axi,
255             String JavaDoc prefix, CompletionContextImpl context) {
256         CompletionResultItem item = null;
257         if(axi instanceof AbstractElement) {
258             if(prefix == null)
259                 item = new ElementResultItem((AbstractElement)axi, context);
260             else
261                 item = new ElementResultItem((AbstractElement)axi, prefix, context);
262         }
263         
264         if(axi instanceof AbstractAttribute) {
265             if(prefix == null)
266                 item = new AttributeResultItem((AbstractAttribute)axi, context);
267             else
268                 item = new AttributeResultItem((AbstractAttribute)axi, prefix, context);
269         }
270         
271         return item;
272     }
273     
274     private static List JavaDoc<String JavaDoc> getPrefixes(CompletionContextImpl context, AXIComponent ae, CompletionModel cm) {
275         List JavaDoc<String JavaDoc> prefixes = null;
276         if(cm == null)
277             return getPrefixesAgainstTargetNamespace(context, ae.getTargetNamespace());
278         
279         prefixes = getPrefixesAgainstTargetNamespace(context, cm.getTargetNamespace());
280         if(prefixes.size() == 0)
281             prefixes.add(cm.getSuggestedPrefix());
282         
283         return prefixes;
284     }
285     
286     private static boolean isFormQualified(AXIComponent component) {
287         if(component instanceof Attribute) {
288             AXIComponent original = component.getOriginal();
289             if( ((Attribute)original).isReference() ||
290                 (original.getParent() instanceof AXIDocument) )
291                 return true;
292             
293             Attribute a = (Attribute)component;
294             return (a.getForm() == Form.QUALIFIED);
295         }
296         
297         if(component instanceof Element) {
298             AXIComponent original = component.getOriginal();
299             if( ((Element)original).isReference() ||
300                 (original.getParent() instanceof AXIDocument) )
301                 return true;
302             Element e = (Element)component;
303             return (e.getForm() == Form.QUALIFIED);
304         }
305         
306         return false;
307     }
308     
309     /**
310      * Returns the appropriate AXIOM element for a given context.
311      */

312     private static Element findAXIElementAtContext(
313             CompletionContextImpl context) {
314         List JavaDoc<QName JavaDoc> path = context.getPathFromRoot();
315         if(path == null || path.size() == 0)
316             return null;
317         
318         CompletionModel cm = null;
319         QName JavaDoc tag = context.getPathFromRoot().get(0);
320         String JavaDoc tns = tag.getNamespaceURI();
321         if(tns != null && tns.equals(XMLConstants.NULL_NS_URI)) {
322             cm = context.getActiveNoNSModel();
323         } else {
324             cm = context.getCompletionModelMap().get(tns);
325         }
326         if(cm == null)
327             return null;
328         
329         AXIModel am = AXIModelFactory.getDefault().getModel(cm.getSchemaModel());
330         AXIComponent parent = am.getRoot();
331         if(parent == null)
332             return null;
333         
334         AXIComponent child = null;
335         for(QName JavaDoc qname : path) {
336             child = findChildElement(parent, qname);
337             parent = child;
338         }
339         
340         if(child != null && (child instanceof Element))
341             return (Element)child;
342         
343         return null;
344     }
345     
346     private static AXIComponent findChildElement(AXIComponent parent,
347             QName JavaDoc qname) {
348         if(parent == null)
349             return null;
350         for(AbstractElement element : parent.getChildElements()) {
351             if(!(element instanceof Element))
352                 continue;
353             Element e = (Element)element;
354             if(qname.getLocalPart().endsWith(e.getName()))
355                 return element;
356         }
357         
358         return null;
359     }
360         
361     /**
362      * Substitue any or anyAttribute with a valid list of items.
363      */

364     private static List JavaDoc<CompletionResultItem> substituteAny(AXIComponent any,
365             CompletionContextImpl context) {
366         List JavaDoc<CompletionResultItem> items = new ArrayList JavaDoc<CompletionResultItem>();
367         String JavaDoc anyNamespace = any.getTargetNamespace();
368         String JavaDoc tns = any.getModel().getRoot().getTargetNamespace();
369         for(CompletionModel cm : context.getCompletionModels()) {
370             //##other => items from other namespaces
371
if(anyNamespace.equals("##other")) { //NOI18N
372
if(tns != null && !tns.equals(cm.getTargetNamespace()))
373                 populateItemsForAny(cm,any,context,items);
374             }
375
376             //##targetNamespace => items from target namespace
377
if(anyNamespace.equals("##targetNamespace")) { //NOI18N
378
if(tns != null && tns.equals(cm.getTargetNamespace()))
379                 populateItemsForAny(cm,any,context,items);
380             }
381             
382             //##local => unqualified items
383
if(anyNamespace.equals("##local") && //NOI18N
384
cm.getTargetNamespace() == null) {
385                 populateItemsForAny(cm,any,context,items);
386             }
387             
388             //only specfied namespaces
389
if(!anyNamespace.startsWith("##") && //NOI18N
390
cm.getTargetNamespace() != null &&
391                anyNamespace.indexOf(cm.getTargetNamespace()) != -1) {
392                 populateItemsForAny(cm,any,context,items);
393             }
394             
395             //##any => unconditional
396
if(anyNamespace.equals("##any")) { //NOI18N
397
populateItemsForAny(cm,any,context,items);
398             }
399         }
400         
401         return items;
402     }
403     
404     private static void populateItemsForAny(CompletionModel cm,
405             AXIComponent any, CompletionContextImpl context, List JavaDoc<CompletionResultItem> items) {
406         AXIModel am = AXIModelFactory.getDefault().getModel(cm.getSchemaModel());
407         if(any instanceof AnyElement) {
408             for(Element e : am.getRoot().getElements()) {
409                 addNSAwareCompletionItems(e,context,cm,items);
410             }
411         }
412         if(any instanceof AnyAttribute) {
413             for(Attribute a : am.getRoot().getAttributes()) {
414                 addNSAwareCompletionItems(a,context,cm,items);
415             }
416         }
417     }
418         
419 }
420
Popular Tags