private AttributeDescriptor createAttributeDescriptor( final XSDComplexTypeDefinition container, final XSDElementDeclaration elemDecl, CoordinateReferenceSystem crs) { int minOccurs = container == null ? 0 : Schemas.getMinOccurs(container, elemDecl); int maxOccurs = container == null ? Integer.MAX_VALUE : Schemas.getMaxOccurs(container, elemDecl); return createAttributeDescriptor(elemDecl, minOccurs, maxOccurs, crs); }
public void _testParseDescribeFeatureType() throws Exception { String loc = getClass().getResource("geoserver-DescribeFeatureType.xml").getFile(); XSDSchema schema = Schemas.parse(loc); assertNotNull(schema); final String targetNs = "http://cite.opengeospatial.org/gmlsf"; final String featureName = "PrimitiveGeoFeature"; QName name = new QName(targetNs, featureName); XSDElementDeclaration elementDeclaration = Schemas.getElementDeclaration(schema, name); assertNotNull(elementDeclaration); XSDComplexTypeDefinition type = (XSDComplexTypeDefinition) elementDeclaration.getType(); assertEquals("PrimitiveGeoFeatureType", type.getName()); assertEquals(targetNs, type.getTargetNamespace()); }
/** * Creates an {@link AttributeType} that matches the xsd type definition as much as possible. * * <p>The original type definition given by the {@link XSDTypeDefinition} is kept as * AttributeType's metadata stored as a "user data" property using <code>XSDTypeDefinition.class * </code> as key. * * <p>If it is a complex attribute, it will contain all the properties declared in the <code> * typeDefinition</code>, as well as all the properties declared in its super types. TODO: handle * the case where the extension mechanism is restriction. * * @param assignedName * @param typeDefinition * @return */ private AttributeType createType( final Name assignedName, final XSDTypeDefinition typeDefinition, CoordinateReferenceSystem crs, boolean anonymous) { AttributeType attType; // ///////// if (processingTypes.contains(assignedName)) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Recursion found for type " + assignedName + ". Proxying it."); } attType = createProxiedType( assignedName, typeDefinition, anonymous ? anonTypeRegistry : typeRegistry); return attType; } processingTypes.push(assignedName); // ////////// final XSDTypeDefinition baseType = typeDefinition.getBaseType(); AttributeType superType = null; if (baseType != null) { String targetNamespace = baseType.getTargetNamespace(); String name = baseType.getName(); if (name != null) { Name baseTypeName = new NameImpl(targetNamespace, name); superType = getAttributeType(baseTypeName, baseType, crs); } } else { LOGGER.warning(assignedName + " has no super type"); } if (typeDefinition instanceof XSDComplexTypeDefinition) { XSDComplexTypeDefinition complexTypeDef; complexTypeDef = (XSDComplexTypeDefinition) typeDefinition; boolean includeParents = true; List<XSDElementDeclaration> children = Schemas.getChildElementDeclarations(typeDefinition, includeParents); final Collection<PropertyDescriptor> schema = new ArrayList<PropertyDescriptor>(children.size()); XSDElementDeclaration childDecl; AttributeDescriptor descriptor; for (Iterator it = children.iterator(); it.hasNext(); ) { childDecl = (XSDElementDeclaration) it.next(); try { descriptor = createAttributeDescriptor(complexTypeDef, childDecl, crs); } catch (NoSuchElementException e) { String msg = "Failed to create descriptor for '" + childDecl.getTargetNamespace() + "#" + childDecl.getName() + " from container '" + typeDefinition.getTargetNamespace() + "#" + typeDefinition.getName() + "'"; NoSuchElementException nse = new NoSuchElementException(msg); nse.initCause(e); throw nse; } schema.add(descriptor); } if (includeAttributes) { for (XSDAttributeUse attgcontent : complexTypeDef.getAttributeUses()) { XSDAttributeDeclaration att = attgcontent.getContent(); descriptor = createAttributeDescriptor( getXmlAttributeType(), null, new NameImpl(null, "@" + att.getName()), 0, 1, false, null); schema.add(descriptor); } } // set substitution group for descriptors here for (XSDElementDeclaration elemDecl : children) { if (elemDecl.isElementDeclarationReference()) { elemDecl = elemDecl.getResolvedElementDeclaration(); } PropertyDescriptor att = null; for (PropertyDescriptor desc : schema) { if (desc.getName().getLocalPart().equals(elemDecl.getName()) && desc.getName().getNamespaceURI().equals(elemDecl.getTargetNamespace())) { att = desc; break; } } setSubstitutionGroup(complexTypeDef, elemDecl, att, crs); } attType = createComplexAttributeType(assignedName, schema, complexTypeDef, superType); } else { Class<?> binding = String.class; boolean isIdentifiable = false; boolean isAbstract = false; List<Filter> restrictions = Collections.emptyList(); InternationalString description = null; attType = typeFactory.createAttributeType( assignedName, binding, isIdentifiable, isAbstract, restrictions, superType, description); } attType.getUserData().put(XSDTypeDefinition.class, typeDefinition); processingTypes.pop(); // even if the type is anonymous, it still has to be registered somewhere because // it's needed for the proxied types to find them. That's why we have 2 registries, // typeRegistry // and anonTypeRegistry. TypeRegistry is the global one, since anonymous types are meant to // be // local and shouldn't be searchable. register(attType, anonymous); return attType; }
private void setSubstitutionGroup( XSDComplexTypeDefinition container, XSDElementDeclaration elemDecl, PropertyDescriptor descriptor, CoordinateReferenceSystem crs) { if (descriptor.getUserData().get("substitutionGroup") != null) { // this has been done before return; } List<AttributeDescriptor> substitutionGroup = new ArrayList<AttributeDescriptor>(); descriptor.getUserData().put("substitutionGroup", substitutionGroup); int minOccurs = Schemas.getMinOccurs(container, elemDecl); int maxOccurs = Schemas.getMaxOccurs(container, elemDecl); boolean nillable = elemDecl.isNillable(); Iterator substitutions = elemDecl.getSubstitutionGroup().iterator(); XSDElementDeclaration sub; while (substitutions.hasNext()) { sub = (XSDElementDeclaration) substitutions.next(); if (!(sub.getName().equals(elemDecl.getName())) || !(sub.getTargetNamespace().equals(elemDecl.getTargetNamespace()))) { Name elemName = Types.typeName(sub.getTargetNamespace(), sub.getName()); AttributeType type = getTypeOf(sub, crs); if (type != null) { substitutionGroup.add( createAttributeDescriptor(type, crs, elemName, minOccurs, maxOccurs, nillable, null)); } } } XSDTypeDefinition typeDef = elemDecl.getType(); if (typeDef instanceof XSDComplexTypeDefinition) { Name typeName = Types.typeName(typeDef.getTargetNamespace(), typeDef.getName()); AttributeType attType = typeRegistry.get(typeName); if (!processingTypes.contains(typeName)) { // ignore processingTypes to avoid endless recursion if (attType == null || attType instanceof AbstractLazyComplexTypeImpl) { // type is not yet registered or it's a lazy type from foundation types // recreate lazy type to ensure everything is loaded // it will eventually call this method so substitution groups will be set then LOGGER.finest("Creating attribute type " + typeName); createType(typeName, typeDef, crs, false); LOGGER.finest("Registering attribute type " + typeName); } else if (attType instanceof ComplexType) { // ensure substitution groups are set for children including non lazy foundation // types ComplexType complexType = (ComplexType) attType; Collection<PropertyDescriptor> children = complexType.getDescriptors(); List<XSDParticle> childParticles = Schemas.getChildElementParticles(typeDef, true); for (XSDParticle particle : childParticles) { XSDElementDeclaration element = (XSDElementDeclaration) particle.getContent(); if (element.isElementDeclarationReference()) { element = element.getResolvedElementDeclaration(); } PropertyDescriptor childDesc = null; for (PropertyDescriptor desc : children) { if (desc.getName().getLocalPart().equals(element.getName()) && desc.getName().getNamespaceURI().equals(element.getTargetNamespace())) { childDesc = desc; break; } } if (childDesc != null) { setSubstitutionGroup((XSDComplexTypeDefinition) typeDef, element, childDesc, crs); } } } } } }