2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2009-2017 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
9 * The contents of this file are subject to the terms of either the GNU
10 * General Public License Version 2 only ("GPL") or the Common
11 * Development and Distribution License("CDDL") (collectively, the
12 * "License"). You may not use this file except in compliance with the
13 * License. You can obtain a copy of the License at
14 * http://www.netbeans.org/cddl-gplv2.html
15 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16 * specific language governing permissions and limitations under the
17 * License. When distributing the software, include this License Header
18 * Notice in each file and include the License file at
19 * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20 * particular file as subject to the "Classpath" exception as provided
21 * by Oracle in the GPL Version 2 section of the License file that
22 * accompanied this code. If applicable, add the following below the
23 * License Header, with the fields enclosed by brackets [] replaced by
24 * your own identifying information:
25 * "Portions Copyrighted [year] [name of copyright owner]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Sun Microsystems, Inc. Portions Copyright 2009-2010 Sun
31 * Microsystems, Inc. All Rights Reserved.
33 * If you wish your version of this file to be governed by only the CDDL
34 * or only the GPL Version 2, indicate your decision by adding
35 * "[Contributor] elects to include this software in this distribution
36 * under the [CDDL or GPL Version 2] license." If you do not indicate a
37 * single choice of license, a recipient has the option to distribute
38 * your version of this file under either the CDDL, the GPL Version 2 or
39 * to extend the choice of license to its licensees as provided above.
40 * However, if you add GPL Version 2 code and therefore, elected the GPL
41 * Version 2 license, then the option applies only if the new code is
42 * made subject to such option by the copyright holder.
47 * Created on 31.08.2007, 15:40:45
49 * To change this template, choose Tools | Templates
50 * and open the template in the editor.
53 package org.netbeans.modules.xml.xpath.ext;
55 import java.util.ArrayList;
56 import java.util.Collection;
57 import java.util.List;
59 import javax.xml.namespace.NamespaceContext;
60 import javax.xml.namespace.QName;
61 import org.netbeans.modules.xml.schema.model.ElementReference;
62 import org.netbeans.modules.xml.schema.model.Form;
63 import org.netbeans.modules.xml.schema.model.GlobalAttribute;
64 import org.netbeans.modules.xml.schema.model.GlobalElement;
65 import org.netbeans.modules.xml.schema.model.LocalAttribute;
66 import org.netbeans.modules.xml.schema.model.LocalElement;
67 import org.netbeans.modules.xml.schema.model.Schema;
68 import org.netbeans.modules.xml.schema.model.SchemaComponent;
69 import org.netbeans.modules.xml.schema.model.SchemaModel;
70 import org.netbeans.modules.xml.xpath.ext.schema.FindAllChildrenSchemaVisitor;
71 import org.netbeans.modules.xml.xpath.ext.schema.FindChildrenSchemaVisitor;
72 import org.netbeans.modules.xml.xpath.ext.schema.resolver.SchemaCompHolder;
73 import org.netbeans.modules.xml.xpath.ext.schema.resolver.WrappingSchemaContext;
74 import org.netbeans.modules.xml.xpath.ext.schema.resolver.XPathSchemaContext;
75 import org.netbeans.modules.xml.xpath.ext.schema.resolver.XPathSchemaContext.SchemaCompPair;
76 import org.netbeans.modules.xml.xpath.ext.spi.ExternalModelResolver;
77 import org.netbeans.modules.xml.xpath.ext.spi.XPathCastResolver;
78 import org.netbeans.modules.xml.xpath.ext.spi.XPathPseudoComp;
79 import org.netbeans.modules.xml.xpath.ext.visitor.ExpressionComparatorVisitor;
86 public class XPathUtils {
88 public static boolean equal(Object o1, Object o2) {
89 if (o1 == o2) return true;
90 return (o1 == null || o2 == null) ? false : o1.equals(o2);
94 * Converts the qName to a String.
95 * Only the prefix and the local part is used.
96 * The namespace URI is ignored.
98 * This method is intended to print an entity.
100 public static String qNameObjectToString(QName qName) {
101 String prefix = qName.getPrefix();
102 if (prefix == null || prefix.length() == 0) {
103 return qName.getLocalPart();
105 return prefix + ":" + qName.getLocalPart();
111 * Converts the qName to a String.
112 * Only the prefix and the namespace URI is used.
113 * The local part is ignored.
115 * This method is intended to print a namespace which is held in a QName.
117 public static String gNameNamespaceToString(QName qName) {
118 String prefix = qName.getPrefix();
119 String nsUri = qName.getNamespaceURI();
121 if (prefix == null || prefix.length() == 0) {
122 return "{" + nsUri + "}";
124 return "{" + nsUri + "}" + prefix;
129 * Check if the namespace URI is specified for the name.
130 * If the name isn't specified, then try resolve it from the prefix.
131 * Returns the corrected name if possible. Otherwise returns old name.
136 public static QName resolvePrefix(NamespaceContext nsContext, QName name) {
137 String nsUri = name.getNamespaceURI();
138 if (nsUri == null || nsUri.length() == 0 && nsContext != null) {
140 String nsPrefix = name.getPrefix();
141 nsUri = nsContext.getNamespaceURI(nsPrefix);
144 String localPart = name.getLocalPart();
145 QName newName = new QName(nsUri, localPart);
153 public static boolean equalsIgnorNsUri(QName qName1, QName qName2) {
154 return (qName1.getLocalPart().equals(qName2.getLocalPart())) &&
155 (qName1.getPrefix().equals(qName2.getPrefix()));
158 public static boolean samePredicatesArr(
159 XPathPredicateExpression[] predArr1,
160 XPathPredicateExpression[] predArr2) {
162 if (predArr1 == predArr2) {
165 if (predArr1 == null || predArr2 == null) {
169 // Compare predicates count
170 int size1 = predArr1 == null ? 0 : predArr1.length;
171 int size2 = predArr2 == null ? 0 : predArr2.length;
172 if (size1 != size2) {
175 // Compare predicates one by one
177 // It is implied that the order is the same.
178 // So the same sets of predicates but with different order
179 // are considered different.
180 for (int index = 0; index < size1; index++) {
181 XPathPredicateExpression predicate1 = predArr1[index];
182 XPathPredicateExpression predicate2 = predArr2[index];
184 XPathExpression predExpr1 = predicate1.getPredicate();
185 XPathExpression predExpr2 = predicate2.getPredicate();
187 if (predExpr1 instanceof XPathSchemaContextHolder &&
188 predExpr2 instanceof XPathSchemaContextHolder) {
189 // If both predicate expressions are schema context holders,
190 // then compare contexts.
192 XPathSchemaContext ctxt1 =
193 ((XPathSchemaContextHolder)predExpr1).getSchemaContext();
194 XPathSchemaContext ctxt2 =
195 ((XPathSchemaContextHolder)predExpr2).getSchemaContext();
197 if (!equal(ctxt1, ctxt2)) {
201 if (!ExpressionComparatorVisitor.equals(predExpr1, predExpr2)) {
210 * Determines if a namespace prefix is required for the specified schema component.
214 public static boolean isPrefixRequired(SchemaComponent sComp) {
215 if (sComp instanceof LocalElement) {
216 Form form = ((LocalElement)sComp).getFormEffective();
217 if (form == Form.QUALIFIED) {
222 } else if (sComp instanceof GlobalElement) {
224 } else if (sComp instanceof LocalAttribute) {
225 Form form = ((LocalAttribute)sComp).getFormEffective();
226 if (form == Form.QUALIFIED) {
231 } else if (sComp instanceof GlobalElement ||
232 sComp instanceof ElementReference ||
233 sComp instanceof GlobalAttribute) {
234 // all global objects have to be with a prefix
238 assert true : "Unsupported schema component in the BPEL mapper tree!"; // NOI18N
243 * Checks if the specified Schema component has any subcomponents.
247 public static boolean hasSubcomponents(SchemaComponent sComp) {
248 FindAllChildrenSchemaVisitor checker =
249 new FindAllChildrenSchemaVisitor(true, true, true);
250 checker.lookForSubcomponents(sComp);
251 List<SchemaComponent> found = checker.getFound();
252 return found != null && !found.isEmpty();
256 * Constructs a list of SchemaCompPair objects. Each SchemaCompPair represents
257 * a child Schema component of a parent. Parents are taken from the
258 * specified parent SchemaContext. The context can contain several schema
259 * components. So children mean children of all possible parent components
260 * in current context.
262 * Childrent can be real children schema components or pseudo components.
263 * See XPathPseudoComp class.
266 * @param parentSContext
267 * @param lookForElements indicates if it necessary to add elements to
269 * @param lookForAttributes indicates if it necessary to add attributes to
271 * @param collectAny indicates if it necessary to add xsd:any or
272 * xsd:anyAttribute to the result list.
273 * @return result list
275 public static List<SchemaCompPair> findSubcomponents(
276 XPathModel xPathModel, XPathSchemaContext parentSContext,
277 boolean lookForElements, boolean lookForAttributes, boolean collectAny) {
279 assert parentSContext != null;
280 ArrayList<SchemaCompPair> result = new ArrayList<SchemaCompPair>();
282 XPathCastResolver castResolver = xPathModel == null ? null :
283 xPathModel.getXPathCastResolver();
284 Set<SchemaCompPair> parentCompPairSet = parentSContext.getSchemaCompPairs();
286 boolean processPseudoComp =
287 castResolver != null && parentCompPairSet.size() == 1;
289 for (SchemaCompPair parentCompPair : parentCompPairSet) {
290 SchemaCompHolder parentCompHolder = parentCompPair.getCompHolder();
292 FindAllChildrenSchemaVisitor visitor =
293 new FindAllChildrenSchemaVisitor(
294 lookForElements, lookForAttributes, false);
295 visitor.lookForSubcomponents(parentCompHolder.getSchemaComponent());
297 List<SchemaComponent> foundComps = visitor.getFound();
298 for (SchemaComponent foundComp : foundComps) {
299 SchemaCompPair newPair =
300 new SchemaCompPair(foundComp, parentCompHolder);
304 if (processPseudoComp) {
305 if (visitor.hasAny() || visitor.hasAnyAttribute()) {
306 List<XPathPseudoComp> pcList =
307 castResolver.getPseudoCompList(parentSContext);
308 for (XPathPseudoComp pseudoComp : pcList) {
309 if (pseudoComp.isAttribute()) {
310 if (lookForAttributes && visitor.hasAnyAttribute()) {
311 SchemaCompHolder scHolder =
312 SchemaCompHolder.Factory.construct(pseudoComp);
313 SchemaCompPair newPair =
314 new SchemaCompPair(scHolder, parentCompHolder);
318 if (lookForElements && visitor.hasAny()) {
319 SchemaCompHolder scHolder =
320 SchemaCompHolder.Factory.construct(pseudoComp);
321 SchemaCompPair newPair =
322 new SchemaCompPair(scHolder, parentCompHolder);
335 * Collects a list of SchemaCompHoder objects, which are global accessible.
338 * @param lookForElements indicates if it necessary to add elements to
340 * @param lookForAttributes indicates if it necessary to add attributes to
342 * @param collectAny indicates if it necessary to add xsd:any or
343 * xsd:anyAttribute to the result list.
344 * @return result list
346 public static List<SchemaComponent> findRootComponents(XPathModel xPathModel,
347 boolean lookForElements, boolean lookForAttributes, boolean collectAny) {
349 ArrayList<SchemaComponent> result = new ArrayList<SchemaComponent>();
351 ExternalModelResolver exModelResolver = xPathModel.getExternalModelResolver();
353 if (exModelResolver != null) {
355 // Look for all available root elements (attributes)
356 // in all available models
357 // Pseudo components can be only inside of another schema components,
358 // So they can't be global. It doesn't necessary to look them here.
359 Collection<SchemaModel> sModels = exModelResolver.getVisibleModels();
360 for (SchemaModel sModel : sModels) {
361 Schema schema = sModel.getSchema();
362 if (schema != null) {
363 FindAllChildrenSchemaVisitor visitor =
364 new FindAllChildrenSchemaVisitor(
365 lookForElements, lookForAttributes, false);
366 visitor.lookForSubcomponents(schema);
368 List<SchemaComponent> foundComps = visitor.getFound();
369 result.addAll(foundComps);
378 * Returns the list of SchemaCompHolder components, which are children
379 * of the specified parent schema component component (and context)
380 * and have specified name and namespace.
381 * Usually only one component has to be returned.
382 * Not only real schema components can be childrent but also pseudo components,
383 * which are result of casting xsd:any or xsd:anyAttribute.
386 * @param parentContext
388 * @param soughtName required name
389 * @param soughtNamespace required namespace
390 * @param isAttribute indicates if an attribute or element is required
394 public static List<SchemaCompHolder> getChildren(
395 XPathModel xPathModel, XPathSchemaContext parentContext,
396 SchemaComponent parent, String soughtName,
397 String soughtNamespace, boolean isAttribute) {
398 List<SchemaComponent> found = null;
399 boolean hasAny = false;
400 boolean hasAnyAttribute = false;
401 ArrayList<SchemaCompHolder> result = new ArrayList<SchemaCompHolder>();
403 FindChildrenSchemaVisitor visitor =
404 new FindChildrenSchemaVisitor(parentContext,
405 soughtName, soughtNamespace, isAttribute);
406 visitor.lookForSubcomponent(parent);
407 found = visitor.getFound();
408 hasAny = visitor.hasAny();
409 hasAnyAttribute = visitor.hasAnyAttribute();
411 if (found == null || found.isEmpty()) {
413 // try looking for Pseudo Components here
414 XPathCastResolver castResolver = xPathModel.getXPathCastResolver();
415 if (castResolver != null) {
416 List<XPathPseudoComp> pcList =
417 castResolver.getPseudoCompList(parentContext);
418 if (pcList != null) {
419 for (XPathPseudoComp pseudoComp : pcList) {
420 if (!hasAnyAttribute && isAttribute) {
421 // AnyAttribute isn't supported
425 if (!hasAny && !isAttribute) {
426 // Any isn't supported
430 if (isAttribute != pseudoComp.isAttribute()) {
434 if (!(soughtName.equals(pseudoComp.getName()))) {
438 if (!(soughtNamespace.equals(pseudoComp.getNamespace()))) {
439 // different namespace
443 SchemaCompHolder compHolder =
444 SchemaCompHolder.Factory.construct(pseudoComp);
445 result.add(compHolder);
450 convertToHolders(found, result);
457 * Converts the list of Schema components to the list of SC holders
461 private static void convertToHolders(List<SchemaComponent> scList,
462 ArrayList<SchemaCompHolder> target) {
463 for (SchemaComponent sc : scList) {
464 SchemaCompHolder newHolder = SchemaCompHolder.Factory.construct(sc);
465 if (newHolder != null) {
466 target.add(newHolder);
472 * Check if the input schema context is wrapping context, then takes
473 * unwrapped context recursively.
478 public static XPathSchemaContext unwrap(XPathSchemaContext sContext) {
479 if (sContext instanceof WrappingSchemaContext) {
480 sContext = ((WrappingSchemaContext)sContext).getBaseContext();
481 return unwrap(sContext);