1 19 package org.netbeans.modules.xml.schema.completion.util; 20 21 import java.net.URI ; 22 import java.util.ArrayList ; 23 import java.util.List ; 24 import java.util.StringTokenizer ; 25 import javax.xml.XMLConstants ; 26 import javax.xml.namespace.QName ; 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 ; 44 import org.w3c.dom.NamedNodeMap ; 45 46 50 public class CompletionUtil { 51 52 55 private CompletionUtil() { 56 } 57 58 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 76 public static void printPath(List <QName > path) { 77 StringBuffer buffer = new StringBuffer (); 78 for(QName item: path) { 79 if(buffer.toString().equals("")) 80 buffer.append(item); 81 else 82 buffer.append("/" + item); 83 } 84 } 86 87 public static boolean isRoot(String 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 101 public static String getPrefixFromTag(String tagName) { 102 if(tagName == null) return null; 103 return (tagName.indexOf(":") == -1) ? null : 104 tagName.substring(0, tagName.indexOf(":")); 105 } 106 107 110 public static String getLocalNameFromTag(String tagName) { 111 if(tagName == null) return null; 112 return (tagName.indexOf(":") == -1) ? tagName : 113 tagName.substring(tagName.indexOf(":")+1, tagName.length()); 114 } 115 116 121 public static String getPrefixFromNamespaceDeclaration(String namespace) { 122 if(namespace == null) return null; 123 return (namespace.indexOf(":") == -1) ? 124 null : namespace.substring(namespace.indexOf(":")+1); 125 } 126 127 133 public static List <String > getPrefixesAgainstTargetNamespace( 134 CompletionContextImpl context, String namespace) { 135 List <String > list = new ArrayList <String >(); 136 NamedNodeMap attributes = context.getDocRootAttributes(); 137 for(int index=0; index<attributes.getLength(); index++) { 138 Attr attr = (Attr )attributes.item(index); 139 if(!attr.getName().startsWith(XMLConstants.XMLNS_ATTRIBUTE)) 140 continue; 141 if(attr.getValue().equals(namespace)) { 142 String prefix = getPrefixFromNamespaceDeclaration(attr.getName()); 143 list.add(prefix); 144 } 145 } 146 147 return list; 148 } 149 150 155 public static void loadSchemaURIs(String schemaLocation, List <URI > uris, boolean noNS) { 156 StringTokenizer st = new StringTokenizer ( 157 schemaLocation.replaceAll("\n", " "), " "); while(st.hasMoreTokens()) { 159 URI uri = null; 160 try { 161 String token1 = st.nextToken().trim(); 162 if(noNS) { 163 uri = URI.create(token1); if(uri != null) 165 uris.add(uri); 166 continue; 167 } 168 if(st.hasMoreTokens()) { 169 String token2 = st.nextToken().trim(); 170 uri = URI.create(token2); if(uri != null) 172 uris.add(uri); 173 } 174 } catch (Exception ex) { 175 continue; 176 } 177 } 178 } 179 180 183 public static List <CompletionResultItem> getAttributes( 184 CompletionContextImpl context) { 185 Element element = findAXIElementAtContext(context); 186 if(element == null) 187 return null; 188 List <CompletionResultItem> results = new ArrayList <CompletionResultItem>(); 189 String typedChars = context.getTypedChars(); 190 for(AbstractAttribute aa: element.getAttributes()) { 191 if(aa.getTargetNamespace() == null) { 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 207 public static List <CompletionResultItem> getElements( 208 CompletionContextImpl context) { 209 Element element = findAXIElementAtContext(context); 210 if(element == null) 211 return null; 212 213 List <CompletionResultItem> results = new ArrayList <CompletionResultItem>(); 214 String typedChars = context.getTypedChars(); 215 for(AbstractElement ae: element.getChildElements()) { 216 if(ae.getTargetNamespace() == null) { 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 <CompletionResultItem> results) { 231 String 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 List <String > prefixes = getPrefixes(context, axi, cm); 244 for(String 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 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 <String > getPrefixes(CompletionContextImpl context, AXIComponent ae, CompletionModel cm) { 275 List <String > 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 312 private static Element findAXIElementAtContext( 313 CompletionContextImpl context) { 314 List <QName > path = context.getPathFromRoot(); 315 if(path == null || path.size() == 0) 316 return null; 317 318 CompletionModel cm = null; 319 QName tag = context.getPathFromRoot().get(0); 320 String 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 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 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 364 private static List <CompletionResultItem> substituteAny(AXIComponent any, 365 CompletionContextImpl context) { 366 List <CompletionResultItem> items = new ArrayList <CompletionResultItem>(); 367 String anyNamespace = any.getTargetNamespace(); 368 String tns = any.getModel().getRoot().getTargetNamespace(); 369 for(CompletionModel cm : context.getCompletionModels()) { 370 if(anyNamespace.equals("##other")) { if(tns != null && !tns.equals(cm.getTargetNamespace())) 373 populateItemsForAny(cm,any,context,items); 374 } 375 376 if(anyNamespace.equals("##targetNamespace")) { if(tns != null && tns.equals(cm.getTargetNamespace())) 379 populateItemsForAny(cm,any,context,items); 380 } 381 382 if(anyNamespace.equals("##local") && cm.getTargetNamespace() == null) { 385 populateItemsForAny(cm,any,context,items); 386 } 387 388 if(!anyNamespace.startsWith("##") && cm.getTargetNamespace() != null && 391 anyNamespace.indexOf(cm.getTargetNamespace()) != -1) { 392 populateItemsForAny(cm,any,context,items); 393 } 394 395 if(anyNamespace.equals("##any")) { 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 <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 |