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.xml.xpath.ext.metadata;
021:
022: import java.util.ArrayList;
023: import java.util.Collection;
024: import java.util.List;
025: import org.netbeans.modules.xml.xpath.ext.schema.CheckTypeDerivationVisitor;
026: import org.netbeans.modules.xml.schema.model.ComplexType;
027: import org.netbeans.modules.xml.schema.model.Element;
028: import org.netbeans.modules.xml.schema.model.ElementReference;
029: import org.netbeans.modules.xml.schema.model.GlobalAttribute;
030: import org.netbeans.modules.xml.schema.model.GlobalElement;
031: import org.netbeans.modules.xml.schema.model.GlobalSimpleType;
032: import org.netbeans.modules.xml.schema.model.GlobalType;
033: import org.netbeans.modules.xml.schema.model.LocalAttribute;
034: import org.netbeans.modules.xml.schema.model.LocalElement;
035: import org.netbeans.modules.xml.schema.model.LocalType;
036: import org.netbeans.modules.xml.schema.model.SchemaComponent;
037: import org.netbeans.modules.xml.schema.model.SchemaModel;
038: import org.netbeans.modules.xml.schema.model.SchemaModelFactory;
039: import org.netbeans.modules.xml.schema.model.SimpleType;
040: import org.netbeans.modules.xml.schema.model.TypeContainer;
041: import org.netbeans.modules.xml.xam.dom.NamedComponentReference;
042:
043: /**
044: *
045: * @author nk160297
046: */
047: public final class XPathMetadataUtils {
048:
049: /**
050: * Takes a list of abstract arguments and convert it to the list
051: * of arguments' descriptors. The ArgumentGrop objects are filtered out.
052: *
053: * @param sourceArgList
054: * @param returnMandatoryOnly specifies if only mandatory fields are required.
055: * @return
056: */
057: public static List<ArgumentDescriptor> getArgDescriptorsList(
058: List<AbstractArgument> sourceArgList,
059: boolean returnMandatoryOnly) {
060: return populateArgList(sourceArgList, null, returnMandatoryOnly);
061: }
062:
063: /**
064: * Traverses the description of arguments and collects all
065: * argument descriptors.
066: * This method is recursive because arguments' description can have
067: * hierarchical structure.
068: *
069: * @param sourceArgList
070: * @param resutlArgList
071: * @return
072: */
073: private static List<ArgumentDescriptor> populateArgList(
074: List<AbstractArgument> sourceArgList,
075: List<ArgumentDescriptor> resutlArgList,
076: boolean returnMandatoryOnly) {
077: //
078: for (AbstractArgument argument : sourceArgList) {
079: if (returnMandatoryOnly && !argument.isMandatory()) {
080: // Skip optional arguments if only mandatory ones are requested.
081: continue;
082: }
083: //
084: if (argument instanceof ArgumentDescriptor) {
085: //
086: if (resutlArgList == null) {
087: // Lazy initialization
088: resutlArgList = new ArrayList<ArgumentDescriptor>();
089: }
090: //
091: resutlArgList.add((ArgumentDescriptor) argument);
092: } else if (argument instanceof ArgumentGroup) {
093: List<AbstractArgument> subArgList = ((ArgumentGroup) argument)
094: .getArgumentList();
095: //
096: resutlArgList = populateArgList(subArgList,
097: resutlArgList, returnMandatoryOnly);
098: }
099: }
100: //
101: return resutlArgList;
102: }
103:
104: public static GlobalType findPrimitiveType(String typeName) {
105: if (typeName == null || typeName.length() == 0) {
106: return null;
107: }
108: //
109: Collection<GlobalSimpleType> primitiveTypes = SchemaModelFactory
110: .getDefault().getPrimitiveTypesModel().getSchema()
111: .getSimpleTypes();
112: for (GlobalSimpleType type : primitiveTypes) {
113: if (typeName.equals(type.getName())) {
114: return type;
115: }
116: }
117: //
118: return null;
119: }
120:
121: /**
122: * Checks if the derived type is derived from the base type.
123: * @param base
124: * @param derived
125: * @return
126: */
127: public static boolean isTypeDerived(SchemaComponent base,
128: SchemaComponent derived) {
129: if (base instanceof GlobalType) {
130: CheckTypeDerivationVisitor ctdVisitor = new CheckTypeDerivationVisitor(
131: (GlobalType) base, derived);
132: return ctdVisitor.isDerived();
133: } else {
134: // any type can be derived only from a global type
135: return false;
136: }
137: }
138:
139: /**
140: * Tries determine the most appropriate XPath type by the schema component.
141: * @param schemaComp
142: * @return
143: */
144: public static XPathType calculateXPathType(
145: SchemaComponent schemaComp) {
146: //
147: SchemaComponent schemaType = getSchemaType(schemaComp);
148: //
149: if (schemaType == null) {
150: return null;
151: }
152: //
153: if (schemaType instanceof SimpleType) {
154: SchemaModel primitiveTypesModel = SchemaModelFactory
155: .getDefault().getPrimitiveTypesModel();
156: //
157: GlobalSimpleType stringType = primitiveTypesModel
158: .findByNameAndType("string", GlobalSimpleType.class); // NOI18N
159: if (schemaType.equals(stringType)
160: || XPathMetadataUtils.isTypeDerived(schemaType,
161: stringType)) {
162: return XPathType.STRING_TYPE;
163: }
164: //
165: GlobalSimpleType booleanType = primitiveTypesModel
166: .findByNameAndType("boolean",
167: GlobalSimpleType.class); // NOI18N
168: if (schemaType.equals(booleanType)
169: || XPathMetadataUtils.isTypeDerived(schemaType,
170: booleanType)) {
171: return XPathType.BOOLEAN_TYPE;
172: }
173: //
174: GlobalSimpleType decimalType = primitiveTypesModel
175: .findByNameAndType("decimal",
176: GlobalSimpleType.class); // NOI18N
177: if (schemaType.equals(booleanType)
178: || XPathMetadataUtils.isTypeDerived(schemaType,
179: decimalType)) {
180: return XPathType.NUMBER_TYPE;
181: }
182: //
183: GlobalSimpleType doubleType = primitiveTypesModel
184: .findByNameAndType("double", GlobalSimpleType.class); // NOI18N
185: if (schemaType.equals(booleanType)
186: || XPathMetadataUtils.isTypeDerived(schemaType,
187: doubleType)) {
188: return XPathType.NUMBER_TYPE;
189: }
190: //
191: GlobalSimpleType floatType = primitiveTypesModel
192: .findByNameAndType("float", GlobalSimpleType.class); // NOI18N
193: if (schemaType.equals(booleanType)
194: || XPathMetadataUtils.isTypeDerived(schemaType,
195: floatType)) {
196: return XPathType.NUMBER_TYPE;
197: }
198: //
199: GlobalSimpleType hexBinaryType = primitiveTypesModel
200: .findByNameAndType("hexBinary",
201: GlobalSimpleType.class); // NOI18N
202: if (schemaType.equals(booleanType)
203: || XPathMetadataUtils.isTypeDerived(schemaType,
204: hexBinaryType)) {
205: return XPathType.NUMBER_TYPE;
206: }
207: //
208: return XPathType.ANY_TYPE;
209: } else if (schemaType instanceof ComplexType) {
210: if (schemaComp instanceof Element) {
211: if (isElementRepeating((Element) schemaComp)) {
212: return XPathType.NODE_SET_TYPE;
213: } else {
214: return XPathType.NODE_TYPE;
215: }
216: }
217: }
218: //
219: return null;
220: }
221:
222: /**
223: * Determines if the specified element is repeating.
224: * @param element
225: * @return
226: */
227: public static boolean isElementRepeating(Element element) {
228: boolean isRepeating = false;
229: String maxOccoursStr = null;
230: if (element instanceof GlobalElement) {
231: return false;
232: } else if (element instanceof LocalElement) {
233: LocalElement lElement = (LocalElement) element;
234: //
235: maxOccoursStr = lElement.getMaxOccursEffective();
236: } else if (element instanceof ElementReference) {
237: ElementReference elementRef = (ElementReference) element;
238: //
239: maxOccoursStr = elementRef.getMaxOccursEffective();
240: }
241: //
242: if (maxOccoursStr != null) {
243: try {
244: int maxOccoursInt = Integer.parseInt(maxOccoursStr);
245: isRepeating = maxOccoursInt > 1;
246: } catch (NumberFormatException ex) {
247: // Do Nothing
248: isRepeating = true;
249: }
250: }
251: //
252: return isRepeating;
253: }
254:
255: /**
256: * @param schemaComp
257: * @return the schema type of a schema component.
258: */
259: public static SchemaComponent getSchemaType(
260: SchemaComponent schemaComp) {
261: if (schemaComp instanceof GlobalType
262: || schemaComp instanceof LocalType) {
263: return schemaComp;
264: } else if (schemaComp instanceof TypeContainer) {
265: NamedComponentReference<? extends GlobalType> gTypeRef = ((TypeContainer) schemaComp)
266: .getType();
267: if (gTypeRef != null) {
268: return gTypeRef.get();
269: } else {
270: return ((TypeContainer) schemaComp).getInlineType();
271: }
272: } else if (schemaComp instanceof ElementReference) {
273: NamedComponentReference<GlobalElement> gElementRef = ((ElementReference) schemaComp)
274: .getRef();
275: if (gElementRef != null) {
276: GlobalElement gElement = gElementRef.get();
277: if (gElement != null) {
278: return getSchemaType(gElement);
279: }
280: }
281: } else if (schemaComp instanceof LocalAttribute) {
282: NamedComponentReference<GlobalSimpleType> gTypeRef = ((LocalAttribute) schemaComp)
283: .getType();
284: if (gTypeRef != null) {
285: return gTypeRef.get();
286: } else {
287: return ((LocalAttribute) schemaComp).getInlineType();
288: }
289: } else if (schemaComp instanceof GlobalAttribute) {
290: NamedComponentReference<GlobalSimpleType> gTypeRef = ((GlobalAttribute) schemaComp)
291: .getType();
292: if (gTypeRef != null) {
293: return gTypeRef.get();
294: } else {
295: return ((GlobalAttribute) schemaComp).getInlineType();
296: }
297: }
298: //
299: return null;
300: }
301:
302: }
|