/** * Copyright © 2006-2016 Web Cohesion (info@webcohesion.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.webcohesion.enunciate.modules.jaxb.util; import com.webcohesion.enunciate.modules.jaxb.EnunciateJaxbContext; import com.webcohesion.enunciate.modules.jaxb.model.*; import com.webcohesion.enunciate.modules.jaxb.model.Element; import com.webcohesion.enunciate.modules.jaxb.model.types.MapXmlType; import com.webcohesion.enunciate.modules.jaxb.model.types.XmlClassType; import com.webcohesion.enunciate.modules.jaxb.model.types.XmlType; import freemarker.ext.beans.BeansWrapper; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; import javax.lang.model.element.*; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.xml.namespace.QName; import java.util.HashSet; import java.util.List; import java.util.Set; /** * Gets all the referenced namespaces for a specific root element. * * @author Ryan Heaton */ public class ReferencedNamespacesMethod implements TemplateMethodModelEx { private final EnunciateJaxbContext context; public ReferencedNamespacesMethod(EnunciateJaxbContext context) { this.context = context; } public Object exec(List list) throws TemplateModelException { if (list.size() < 1) { throw new TemplateModelException("The referencedNamespaces method must have an element as a parameter."); } TemplateModel from = (TemplateModel) list.get(0); Object unwrapped = BeansWrapper.getDefaultInstance().unwrap(from); if (!(unwrapped instanceof ElementDeclaration)) { throw new TemplateModelException("The referencedNamespaces method must have an element as a parameter."); } ElementDeclaration elementDeclaration = (ElementDeclaration) unwrapped; Set<String> referencedNamespaces = new HashSet<String>(); referencedNamespaces.add(elementDeclaration.getNamespace()); if (elementDeclaration instanceof RootElementDeclaration) { TypeDefinition typeDef = ((RootElementDeclaration) elementDeclaration).getTypeDefinition(); addReferencedNamespaces(typeDef, referencedNamespaces); } else if (elementDeclaration instanceof LocalElementDeclaration) { TypeElement typeElement = null; TypeMirror elementType = ((LocalElementDeclaration)elementDeclaration).getElementType(); if (elementType instanceof DeclaredType) { javax.lang.model.element.Element element = ((DeclaredType) elementType).asElement(); if (element instanceof TypeElement) { typeElement = (TypeElement) element; } } TypeDefinition typeDefinition = this.context.findTypeDefinition(typeElement); if (typeDefinition != null) { addReferencedNamespaces(typeDefinition, referencedNamespaces); } } referencedNamespaces.remove(null); referencedNamespaces.remove(""); referencedNamespaces.remove("http://www.w3.org/2001/XMLSchema"); return referencedNamespaces; } /** * Adds the referenced namespaces of the given type definition to the given set. * * @param typeDefinition The type definition. * @param referencedNamespaces The set of referenced namespaces. */ private void addReferencedNamespaces(TypeDefinition typeDefinition, Set<String> referencedNamespaces) { for (Attribute attribute : typeDefinition.getAttributes()) { QName ref = attribute.getRef(); if (ref != null) { referencedNamespaces.add(ref.getNamespaceURI()); } else { addReferencedNamespaces(attribute.getBaseType(), referencedNamespaces); } } for (Element element : typeDefinition.getElements()) { for (Element choice : element.getChoices()) { QName ref = choice.getRef(); if (ref != null) { referencedNamespaces.add(ref.getNamespaceURI()); } else { addReferencedNamespaces(choice.getBaseType(), referencedNamespaces); } } } Value value = typeDefinition.getValue(); if (value != null) { addReferencedNamespaces(value.getBaseType(), referencedNamespaces); } if (typeDefinition instanceof QNameEnumTypeDefinition) { for (EnumValue enumValue : ((QNameEnumTypeDefinition) typeDefinition).getEnumValues()) { if (enumValue.getValue() != null) { referencedNamespaces.add(((QName)enumValue.getValue()).getNamespaceURI()); } } } addReferencedNamespaces(typeDefinition.getBaseType(), referencedNamespaces); } /** * Adds the referenced namespaces of the given xml type to the given set. * * @param xmlType The xml type. * @param referencedNamespaces The set of referenced namespaces. */ private void addReferencedNamespaces(XmlType xmlType, Set<String> referencedNamespaces) { if (!xmlType.isAnonymous()) { referencedNamespaces.add(xmlType.getNamespace()); } else if (xmlType instanceof MapXmlType) { referencedNamespaces.add(((MapXmlType) xmlType).getKeyType().getNamespace()); referencedNamespaces.add(((MapXmlType) xmlType).getValueType().getNamespace()); } else if (xmlType instanceof XmlClassType) { addReferencedNamespaces(((XmlClassType) xmlType).getTypeDefinition(), referencedNamespaces); } } }