/**
* Mule Development Kit
* Copyright 2010-2011 (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.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 org.mule.devkit.generation.spring;
import org.mule.api.annotations.Configurable;
import org.mule.api.annotations.Connector;
import org.mule.api.annotations.Module;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.Source;
import org.mule.api.annotations.Transformer;
import org.mule.api.annotations.oauth.OAuth;
import org.mule.api.annotations.oauth.OAuth2;
import org.mule.api.annotations.param.Default;
import org.mule.api.annotations.param.Optional;
import org.mule.api.callback.HttpCallback;
import org.mule.devkit.generation.AbstractModuleGenerator;
import org.mule.devkit.generation.DevKitTypeElement;
import org.mule.devkit.generation.GenerationException;
import org.mule.devkit.generation.NamingContants;
import org.mule.devkit.generation.adapter.HttpCallbackAdapterGenerator;
import org.mule.devkit.model.code.DefinedClass;
import org.mule.devkit.model.schema.Annotation;
import org.mule.devkit.model.schema.Any;
import org.mule.devkit.model.schema.Attribute;
import org.mule.devkit.model.schema.ComplexContent;
import org.mule.devkit.model.schema.ComplexType;
import org.mule.devkit.model.schema.Documentation;
import org.mule.devkit.model.schema.Element;
import org.mule.devkit.model.schema.ExplicitGroup;
import org.mule.devkit.model.schema.ExtensionType;
import org.mule.devkit.model.schema.FormChoice;
import org.mule.devkit.model.schema.GroupRef;
import org.mule.devkit.model.schema.Import;
import org.mule.devkit.model.schema.LocalComplexType;
import org.mule.devkit.model.schema.LocalSimpleType;
import org.mule.devkit.model.schema.NoFixedFacet;
import org.mule.devkit.model.schema.NumFacet;
import org.mule.devkit.model.schema.ObjectFactory;
import org.mule.devkit.model.schema.Pattern;
import org.mule.devkit.model.schema.Restriction;
import org.mule.devkit.model.schema.Schema;
import org.mule.devkit.model.schema.SchemaConstants;
import org.mule.devkit.model.schema.SchemaLocation;
import org.mule.devkit.model.schema.SimpleContent;
import org.mule.devkit.model.schema.SimpleExtensionType;
import org.mule.devkit.model.schema.SimpleType;
import org.mule.devkit.model.schema.TopLevelComplexType;
import org.mule.devkit.model.schema.TopLevelElement;
import org.mule.devkit.model.schema.TopLevelSimpleType;
import org.mule.devkit.model.schema.Union;
import org.mule.util.StringUtils;
import javax.inject.Inject;
import javax.inject.Named;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class SchemaGenerator extends AbstractModuleGenerator {
public static final String DOMAIN_ATTRIBUTE_NAME = HttpCallbackAdapterGenerator.DOMAIN_FIELD_NAME;
public static final String LOCAL_PORT_ATTRIBUTE_NAME = HttpCallbackAdapterGenerator.LOCAL_PORT_FIELD_NAME;
public static final String REMOTE_PORT_ATTRIBUTE_NAME = HttpCallbackAdapterGenerator.REMOTE_PORT_FIELD_NAME;
public static final String ASYNC_ATTRIBUTE_NAME = HttpCallbackAdapterGenerator.ASYNC_FIELD_NAME;
public static final String HTTP_CALLBACK_CONFIG_ELEMENT_NAME = "http-callback-config";
public static final String OAUTH_CALLBACK_CONFIG_ELEMENT_NAME = "oauth-callback-config";
public static final String REF_SUFFIX = "-ref";
public static final String FLOW_REF_SUFFIX = "-flow-ref";
public static final String INNER_PREFIX = "inner-";
public static final String ATTRIBUTE_NAME_CONFIG_REF = "config-ref";
public static final String ATTRIBUTE_NAME_KEY = "key";
private static final String ATTRIBUTE_NAME_REF = "ref";
private static final String ATTRIBUTE_NAME_VALUE_REF = "value-ref";
private static final String ATTRIBUTE_NAME_KEY_REF = "key-ref";
private static final String ATTRIBUTE_RETRY_MAX = "retryMax";
private static final String XSD_EXTENSION = ".xsd";
private static final String ENUM_TYPE_SUFFIX = "EnumType";
private static final String TYPE_SUFFIX = "Type";
private static final String XML_TYPE_SUFFIX = "XmlType";
private static final String UNBOUNDED = "unbounded";
private static final String LAX = "lax";
private static final String ATTRIBUTE_NAME_NAME = "name";
private static final String DOMAIN_DEFAULT_VALUE = "${fullDomain}";
private static final String PORT_DEFAULT_VALUE = "${http.port}";
private static final String ASYNC_DEFAULT_VALUE = "true";
private static final String ATTRIBUTE_RETRY_MAX_DESCRIPTION = "Specify how many times this operation can be retried automatically.";
private static final String ATTRIBUTE_NAME_REF_DESCRIPTION = "The reference object for this parameter";
private static final String ATTRIBUTE_NAME_NAME_DESCRIPTION = "Give a name to this configuration so it can be later referenced by config-ref.";
private static final String CONNECTION_POOLING_PROFILE = "connection-pooling-profile";
private static final String CONNECTION_POOLING_PROFILE_ELEMENT_DESCRIPTION = "Characteristics of the connection pool.";
private static final String POOLING_PROFILE_ELEMENT = "pooling-profile";
private static final String POOLING_PROFILE_ELEMENT_DESCRIPTION = "Characteristics of the object pool.";
private static final String OAUTH_SAVE_ACCESS_TOKEN_ELEMENT = "oauth-save-access-token";
private static final String OAUTH_RESTORE_ACCESS_TOKEN_ELEMENT = "oauth-restore-access-token";
private static final String OAUTH_SAVE_ACCESS_TOKEN_ELEMENT_DESCRIPTION = "A chain of message processors processed synchronously that can be used to save OAuth state. They will be executed once the connector acquires an OAuth access token.";
private static final String OAUTH_RESTORE_ACCESS_TOKEN_ELEMENT_DESCRIPTION = "A chain of message processors processed synchronously that can be used to restore OAuth state. They will be executed whenever access to a protected resource is requested and the connector is not authorized yet.";
private ObjectFactory objectFactory;
public SchemaGenerator() {
objectFactory = new ObjectFactory();
}
@Override
protected boolean shouldGenerate(DevKitTypeElement typeElement) {
return typeElement.hasAnnotation(Module.class) || typeElement.hasAnnotation(Connector.class);
}
@Override
protected void doGenerate(DevKitTypeElement typeElement) throws GenerationException {
String targetNamespace = getNamespace(typeElement);
Schema schema = new Schema();
schema.setTargetNamespace(targetNamespace);
schema.setElementFormDefault(FormChoice.QUALIFIED);
schema.setAttributeFormDefault(FormChoice.UNQUALIFIED);
importXmlNamespace(schema);
importSpringFrameworkNamespace(schema);
importMuleNamespace(schema);
importMuleDevKitNamespace(schema);
registerTypes(schema);
registerConfigElement(schema, targetNamespace, typeElement);
registerProcessorsAndSources(schema, targetNamespace, typeElement);
registerTransformers(schema, typeElement);
registerEnums(schema, typeElement);
String fileName = "META-INF/mule-" + typeElement.name() + XSD_EXTENSION;
String versionedLocation = getVersionedLocation(typeElement);
String currentLocation = null;
if (typeElement.schemaLocation() == null || typeElement.schemaLocation().length() == 0) {
currentLocation = schema.getTargetNamespace() + "/current/mule-" + typeElement.name() + XSD_EXTENSION;
}
// TODO: replace with a class role
String namespaceHandlerName = context.getNameUtils().generateClassName(typeElement, NamingContants.CONFIG_NAMESPACE, NamingContants.NAMESPACE_HANDLER_CLASS_NAME_SUFFIX);
String className = context.getClassForRole(context.getNameUtils().generateModuleObjectRoleKey(typeElement)).boxify().fullName();
SchemaLocation versionedSchemaLocation = new SchemaLocation(schema, schema.getTargetNamespace(), fileName, versionedLocation, namespaceHandlerName, className);
context.getSchemaModel().addSchemaLocation(versionedSchemaLocation);
if (currentLocation != null) {
SchemaLocation currentSchemaLocation = new SchemaLocation(null, schema.getTargetNamespace(), fileName, currentLocation, namespaceHandlerName, className);
context.getSchemaModel().addSchemaLocation(currentSchemaLocation);
}
}
public static String getVersionedLocation(DevKitTypeElement typeElement) {
String versionedLocation = typeElement.schemaLocation();
if (typeElement.schemaLocation() == null || typeElement.schemaLocation().length() == 0) {
versionedLocation = getNamespace(typeElement) + "/" + typeElement.schemaVersion() + "/mule-" + typeElement.name() + XSD_EXTENSION;
}
return versionedLocation;
}
public static String getNamespace(DevKitTypeElement typeElement) {
String targetNamespace = typeElement.namespace();
if (targetNamespace == null || targetNamespace.length() == 0) {
targetNamespace = SchemaConstants.BASE_NAMESPACE + typeElement.name();
}
return targetNamespace;
}
private void registerEnums(Schema schema, DevKitTypeElement typeElement) {
Set<TypeMirror> registeredEnums = new HashSet<TypeMirror>();
for (VariableElement field : typeElement.getFields()) {
if (context.getTypeMirrorUtils().isEnum(field.asType())) {
if (!registeredEnums.contains(field.asType())) {
registerEnum(schema, field.asType());
registeredEnums.add(field.asType());
}
}
}
for (ExecutableElement method : typeElement.getMethodsAnnotatedWith(Processor.class)) {
for (VariableElement variable : method.getParameters()) {
if (context.getTypeMirrorUtils().isEnum(variable.asType()) && !registeredEnums.contains(variable.asType())) {
registerEnum(schema, variable.asType());
registeredEnums.add(variable.asType());
} else if (context.getTypeMirrorUtils().isCollection(variable.asType())) {
DeclaredType variableType = (DeclaredType) variable.asType();
for (TypeMirror variableTypeParameter : variableType.getTypeArguments()) {
if (context.getTypeMirrorUtils().isEnum(variableTypeParameter) && !registeredEnums.contains(variableTypeParameter)) {
registerEnum(schema, variableTypeParameter);
registeredEnums.add(variableTypeParameter);
}
}
}
}
}
for (ExecutableElement method : typeElement.getMethodsAnnotatedWith(Source.class)) {
for (VariableElement variable : method.getParameters()) {
if (!context.getTypeMirrorUtils().isEnum(variable.asType())) {
continue;
}
if (!registeredEnums.contains(variable.asType())) {
registerEnum(schema, variable.asType());
registeredEnums.add(variable.asType());
}
}
}
}
private void registerEnum(Schema schema, TypeMirror enumType) {
javax.lang.model.element.Element enumElement = context.getTypeUtils().asElement(enumType);
TopLevelSimpleType enumSimpleType = new TopLevelSimpleType();
enumSimpleType.setName(enumElement.getSimpleName() + ENUM_TYPE_SUFFIX);
Union union = new Union();
union.getSimpleType().add(createEnumSimpleType(enumElement));
union.getSimpleType().add(createExpressionSimpleType());
enumSimpleType.setUnion(union);
schema.getSimpleTypeOrComplexTypeOrGroup().add(enumSimpleType);
}
private LocalSimpleType createEnumSimpleType(javax.lang.model.element.Element enumElement) {
LocalSimpleType enumValues = new LocalSimpleType();
Restriction restriction = new Restriction();
enumValues.setRestriction(restriction);
restriction.setBase(SchemaConstants.STRING);
for (javax.lang.model.element.Element enclosed : enumElement.getEnclosedElements()) {
if (enclosed.getKind() == ElementKind.ENUM_CONSTANT) {
NoFixedFacet noFixedFacet = objectFactory.createNoFixedFacet();
noFixedFacet.setValue(enclosed.getSimpleName().toString());
JAXBElement<NoFixedFacet> enumeration = objectFactory.createEnumeration(noFixedFacet);
enumValues.getRestriction().getFacets().add(enumeration);
}
}
return enumValues;
}
private void registerTransformers(Schema schema, DevKitTypeElement typeElement) {
for (ExecutableElement method : typeElement.getMethodsAnnotatedWith(Transformer.class)) {
Element transformerElement = registerTransformer(context.getNameUtils().uncamel(method.getSimpleName().toString()));
schema.getSimpleTypeOrComplexTypeOrGroup().add(transformerElement);
}
}
private void registerProcessorsAndSources(Schema schema, String targetNamespace, DevKitTypeElement typeElement) {
if (typeElement.hasAnnotation(OAuth.class) || typeElement.hasAnnotation(OAuth2.class)) {
// generate an MP to start the OAuth process
registerProcessorElement(schema, false, targetNamespace, "authorize", "AuthorizeType", "Starts OAuth authorization process. It must be called from a flow with an http:inbound-endpoint.");
registerProcessorType(schema, false, targetNamespace, "AuthorizeType", null);
}
for (ExecutableElement method : typeElement.getMethodsAnnotatedWith(Processor.class)) {
String name = method.getSimpleName().toString();
Processor processor = method.getAnnotation(Processor.class);
if (processor.name().length() > 0) {
name = processor.name();
}
String typeName = StringUtils.capitalize(name) + TYPE_SUFFIX;
registerProcessorElement(schema, processor.intercepting(), targetNamespace, name, typeName, context.getJavaDocUtils().getSummary(method));
registerProcessorType(schema, processor.intercepting(), targetNamespace, typeName, method);
}
for (ExecutableElement method : typeElement.getMethodsAnnotatedWith(Source.class)) {
String name = method.getSimpleName().toString();
Source source = method.getAnnotation(Source.class);
if (source.name().length() > 0) {
name = source.name();
}
String typeName = StringUtils.capitalize(name) + TYPE_SUFFIX;
registerSourceElement(schema, targetNamespace, name, typeName, method);
registerSourceType(schema, targetNamespace, typeName, method);
}
}
private void registerProcessorElement(Schema schema, boolean intercepting, String targetNamespace, String name, String typeName, String docText) {
Element element = new TopLevelElement();
element.setName(context.getNameUtils().uncamel(name));
if (intercepting) {
element.setSubstitutionGroup(SchemaConstants.MULE_ABSTRACT_INTERCEPTING_MESSAGE_PROCESSOR);
} else {
element.setSubstitutionGroup(SchemaConstants.MULE_ABSTRACT_MESSAGE_PROCESSOR);
}
element.setType(new QName(targetNamespace, typeName));
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(docText);
annotation.getAppinfoOrDocumentation().add(doc);
element.setAnnotation(annotation);
schema.getSimpleTypeOrComplexTypeOrGroup().add(element);
}
private void registerSourceElement(Schema schema, String targetNamespace, String name, String typeName, ExecutableElement executableElement) {
Element element = new TopLevelElement();
element.setName(context.getNameUtils().uncamel(name));
element.setSubstitutionGroup(SchemaConstants.MULE_ABSTRACT_INBOUND_ENDPOINT);
element.setType(new QName(targetNamespace, typeName));
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getSummary(executableElement));
annotation.getAppinfoOrDocumentation().add(doc);
element.setAnnotation(annotation);
schema.getSimpleTypeOrComplexTypeOrGroup().add(element);
}
private void registerProcessorType(Schema schema, boolean intercepting, String targetNamespace, String name, ExecutableElement element) {
if (intercepting) {
registerExtendedType(schema, SchemaConstants.MULE_ABSTRACT_INTERCEPTING_MESSAGE_PROCESSOR_TYPE, targetNamespace, name, element);
} else {
registerExtendedType(schema, SchemaConstants.MULE_ABSTRACT_MESSAGE_PROCESSOR_TYPE, targetNamespace, name, element);
}
}
private void registerSourceType(Schema schema, String targetNamespace, String name, ExecutableElement element) {
registerExtendedType(schema, SchemaConstants.MULE_ABSTRACT_INBOUND_ENDPOINT_TYPE, targetNamespace, name, element);
}
private void registerExtendedType(Schema schema, QName base, String targetNamespace, String name, ExecutableElement element) {
TopLevelComplexType complexType = new TopLevelComplexType();
complexType.setName(name);
ComplexContent complexContent = new ComplexContent();
complexType.setComplexContent(complexContent);
ExtensionType complexContentExtension = new ExtensionType();
complexContentExtension.setBase(base);
complexContent.setExtension(complexContentExtension);
Attribute configRefAttr = createAttribute(ATTRIBUTE_NAME_CONFIG_REF, true, SchemaConstants.STRING, "Specify which configuration to use for this invocation.");
complexContentExtension.getAttributeOrAttributeGroup().add(configRefAttr);
ExplicitGroup all = new ExplicitGroup();
complexContentExtension.setSequence(all);
if (element != null) {
if (element.getKind() == ElementKind.METHOD) {
int requiredChildElements = 0;
for (VariableElement variable : element.getParameters()) {
if (context.getTypeMirrorUtils().ignoreParameter(variable)) {
continue;
}
if (context.getTypeMirrorUtils().isNestedProcessor(variable.asType())) {
requiredChildElements++;
} else if (context.getTypeMirrorUtils().isXmlType(variable.asType())) {
requiredChildElements++;
} else if (context.getTypeMirrorUtils().isCollection(variable.asType())) {
requiredChildElements++;
}
}
for (VariableElement variable : element.getParameters()) {
if (context.getTypeMirrorUtils().ignoreParameter(variable)) {
continue;
}
if (context.getTypeMirrorUtils().isNestedProcessor(variable.asType())) {
if (requiredChildElements == 1) {
GroupRef groupRef = generateNestedProcessorGroup();
complexContentExtension.setGroup(groupRef);
complexContentExtension.setAll(null);
Attribute attribute = new Attribute();
attribute.setUse(SchemaConstants.USE_OPTIONAL);
attribute.setName("text");
attribute.setType(SchemaConstants.STRING);
complexContentExtension.getAttributeOrAttributeGroup().add(attribute);
} else {
generateNestedProcessorElement(all, variable);
}
} else if (context.getTypeMirrorUtils().isXmlType(variable.asType())) {
all.getParticle().add(objectFactory.createElement(generateXmlElement(variable.getSimpleName().toString(), targetNamespace)));
} else if (context.getTypeMirrorUtils().isCollection(variable.asType())) {
generateCollectionElement(schema, targetNamespace, all, variable);
} else {
complexContentExtension.getAttributeOrAttributeGroup().add(createParameterAttribute(schema, variable));
}
}
ExecutableElement connectExecutableElement = connectForMethod(element);
if (connectExecutableElement != null) {
if (element.getAnnotation(Processor.class) != null) {
Attribute retryMaxAttr = createAttribute(ATTRIBUTE_RETRY_MAX, true, SchemaConstants.STRING, ATTRIBUTE_RETRY_MAX_DESCRIPTION);
retryMaxAttr.setDefault("1");
complexContentExtension.getAttributeOrAttributeGroup().add(retryMaxAttr);
}
for (VariableElement connectVariable : connectExecutableElement.getParameters()) {
if (context.getTypeMirrorUtils().isCollection(connectVariable.asType())) {
generateCollectionElement(schema, targetNamespace, all, connectVariable, true);
} else {
complexContentExtension.getAttributeOrAttributeGroup().add(createParameterAttribute(schema, connectVariable, true));
}
}
}
}
}
if (all.getParticle().size() == 0) {
complexContentExtension.setSequence(null);
}
schema.getSimpleTypeOrComplexTypeOrGroup().add(complexType);
}
private void generateNestedProcessorElement(ExplicitGroup all, VariableElement variable) {
Optional optional = variable.getAnnotation(Optional.class);
TopLevelElement collectionElement = new TopLevelElement();
all.getParticle().add(objectFactory.createElement(collectionElement));
collectionElement.setName(context.getNameUtils().uncamel(variable.getSimpleName().toString()));
if (optional != null) {
collectionElement.setMinOccurs(BigInteger.valueOf(0L));
} else {
collectionElement.setMinOccurs(BigInteger.valueOf(1L));
}
collectionElement.setMaxOccurs("1");
LocalComplexType collectionComplexType = new LocalComplexType();
GroupRef group = generateNestedProcessorGroup();
collectionComplexType.setGroup(group);
collectionElement.setComplexType(collectionComplexType);
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getParameterSummary(variable.getSimpleName().toString(), variable.getEnclosingElement()));
annotation.getAppinfoOrDocumentation().add(doc);
collectionElement.setAnnotation(annotation);
Attribute attribute = new Attribute();
attribute.setUse(SchemaConstants.USE_OPTIONAL);
attribute.setName("text");
attribute.setType(SchemaConstants.STRING);
collectionComplexType.getAttributeOrAttributeGroup().add(attribute);
}
private GroupRef generateNestedProcessorGroup() {
GroupRef group = new GroupRef();
group.generateNestedProcessorGroup(SchemaConstants.MULE_MESSAGE_PROCESSOR_OR_OUTBOUND_ENDPOINT_TYPE);
group.setMinOccurs(BigInteger.valueOf(0L));
group.setMaxOccurs("unbounded");
return group;
}
private void generateCollectionElement(Schema schema, String targetNamespace, ExplicitGroup all, VariableElement variable) {
generateCollectionElement(schema, targetNamespace, all, variable, false);
}
private void generateCollectionElement(Schema schema, String targetNamespace, ExplicitGroup all, VariableElement variable, boolean forceOptional) {
Optional optional = variable.getAnnotation(Optional.class);
TopLevelElement collectionElement = new TopLevelElement();
all.getParticle().add(objectFactory.createElement(collectionElement));
collectionElement.setName(context.getNameUtils().uncamel(variable.getSimpleName().toString()));
if (!forceOptional) {
if (optional != null) {
collectionElement.setMinOccurs(BigInteger.valueOf(0L));
} else {
collectionElement.setMinOccurs(BigInteger.valueOf(1L));
}
} else {
collectionElement.setMinOccurs(BigInteger.valueOf(0L));
}
collectionElement.setMaxOccurs("1");
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getParameterSummary(variable.getSimpleName().toString(), variable.getEnclosingElement()));
annotation.getAppinfoOrDocumentation().add(doc);
collectionElement.setAnnotation(annotation);
String collectionName = context.getNameUtils().uncamel(context.getNameUtils().singularize(collectionElement.getName()));
LocalComplexType collectionComplexType = generateCollectionComplexType(schema, targetNamespace, collectionName, variable.asType());
collectionElement.setComplexType(collectionComplexType);
}
private LocalComplexType generateCollectionComplexType(Schema schema, String targetNamespace, String name, TypeMirror type) {
LocalComplexType collectionComplexType = new LocalComplexType();
ExplicitGroup sequence = new ExplicitGroup();
ExplicitGroup choice = new ExplicitGroup();
if (context.getTypeMirrorUtils().isMap(type)) {
collectionComplexType.setChoice(choice);
choice.getParticle().add(objectFactory.createSequence(sequence));
Any any = new Any();
any.setProcessContents(LAX);
any.setMinOccurs(new BigInteger("0"));
any.setMaxOccurs(UNBOUNDED);
ExplicitGroup anySequence = new ExplicitGroup();
anySequence.getParticle().add(any);
choice.getParticle().add(objectFactory.createSequence(anySequence));
} else if (context.getTypeMirrorUtils().isArrayOrList(type)) {
collectionComplexType.setSequence(sequence);
}
TopLevelElement collectionItemElement = new TopLevelElement();
sequence.getParticle().add(objectFactory.createElement(collectionItemElement));
if (name != null) {
collectionItemElement.setName(name);
}
collectionItemElement.setMinOccurs(BigInteger.valueOf(0L));
collectionItemElement.setMaxOccurs(UNBOUNDED);
collectionItemElement.setComplexType(generateComplexType(schema, targetNamespace, name, type));
Attribute ref = createAttribute(ATTRIBUTE_NAME_REF, true, SchemaConstants.STRING, "The reference object for this parameter");
collectionComplexType.getAttributeOrAttributeGroup().add(ref);
return collectionComplexType;
}
private LocalComplexType generateComplexType(Schema schema, String targetNamespace, String name, TypeMirror typeMirror) {
if (context.getTypeMirrorUtils().isArrayOrList(typeMirror)) {
DeclaredType variableType = (DeclaredType) typeMirror;
java.util.List<? extends TypeMirror> variableTypeParameters = variableType.getTypeArguments();
if (variableTypeParameters.size() != 0) {
TypeMirror genericType = variableTypeParameters.get(0);
if (isTypeSupported(genericType)) {
return generateComplexTypeWithRef(schema, genericType);
} else if (context.getTypeMirrorUtils().isArrayOrList(genericType) ||
context.getTypeMirrorUtils().isMap(genericType)) {
return generateCollectionComplexType(schema, targetNamespace, INNER_PREFIX + name, genericType);
} else if (context.getTypeMirrorUtils().isEnum(genericType)) {
return genereateEnumComplexType(genericType, targetNamespace);
} else {
return generateRefComplexType(ATTRIBUTE_NAME_VALUE_REF);
}
} else {
return generateRefComplexType(ATTRIBUTE_NAME_VALUE_REF);
}
} else if (context.getTypeMirrorUtils().isMap(typeMirror)) {
DeclaredType variableType = (DeclaredType) typeMirror;
java.util.List<? extends TypeMirror> variableTypeParameters = variableType.getTypeArguments();
LocalComplexType mapComplexType = new LocalComplexType();
Attribute keyAttribute = new Attribute();
if (variableTypeParameters.size() > 0 && isTypeSupported(variableTypeParameters.get(0))) {
keyAttribute.setName(ATTRIBUTE_NAME_KEY);
keyAttribute.setType(SchemaTypeConversion.convertType(variableTypeParameters.get(0).toString(), schema.getTargetNamespace()));
} else if (variableTypeParameters.size() > 0 && context.getTypeMirrorUtils().isEnum(variableTypeParameters.get(0))) {
keyAttribute.setName(ATTRIBUTE_NAME_KEY);
javax.lang.model.element.Element enumElement = context.getTypeUtils().asElement(variableTypeParameters.get(0));
keyAttribute.setType(new QName(schema.getTargetNamespace(), enumElement.getSimpleName() + ENUM_TYPE_SUFFIX));
} else {
keyAttribute.setUse(SchemaConstants.USE_REQUIRED);
keyAttribute.setName(ATTRIBUTE_NAME_KEY_REF);
keyAttribute.setType(SchemaConstants.STRING);
}
if (variableTypeParameters.size() > 1 && isTypeSupported(variableTypeParameters.get(1))) {
SimpleContent simpleContent = new SimpleContent();
mapComplexType.setSimpleContent(simpleContent);
SimpleExtensionType complexContentExtension = new SimpleExtensionType();
complexContentExtension.setBase(SchemaTypeConversion.convertType(variableTypeParameters.get(1).toString(), schema.getTargetNamespace()));
simpleContent.setExtension(complexContentExtension);
Attribute refAttribute = new Attribute();
refAttribute.setUse(SchemaConstants.USE_OPTIONAL);
refAttribute.setName(ATTRIBUTE_NAME_VALUE_REF);
refAttribute.setType(SchemaConstants.STRING);
complexContentExtension.getAttributeOrAttributeGroup().add(refAttribute);
complexContentExtension.getAttributeOrAttributeGroup().add(keyAttribute);
} else {
SimpleContent simpleContent = new SimpleContent();
mapComplexType.setSimpleContent(simpleContent);
SimpleExtensionType complexContentExtension = new SimpleExtensionType();
complexContentExtension.setBase(new QName(SchemaConstants.XSD_NAMESPACE, "string", "xs"));
simpleContent.setExtension(complexContentExtension);
Attribute refAttribute = new Attribute();
refAttribute.setUse(SchemaConstants.USE_OPTIONAL);
refAttribute.setName(ATTRIBUTE_NAME_VALUE_REF);
refAttribute.setType(SchemaConstants.STRING);
complexContentExtension.getAttributeOrAttributeGroup().add(refAttribute);
complexContentExtension.getAttributeOrAttributeGroup().add(keyAttribute);
/*
Attribute refAttribute = new Attribute();
refAttribute.setUse(SchemaConstants.USE_OPTIONAL);
refAttribute.setName(ATTRIBUTE_NAME_VALUE_REF);
refAttribute.setType(SchemaConstants.STRING);
mapComplexType.getAttributeOrAttributeGroup().add(refAttribute);
mapComplexType.getAttributeOrAttributeGroup().add(keyAttribute);
*/
}
return mapComplexType;
}
return null;
}
private LocalComplexType genereateEnumComplexType(TypeMirror genericType, String targetNamespace) {
LocalComplexType complexType = new LocalComplexType();
SimpleContent simpleContent = new SimpleContent();
complexType.setSimpleContent(simpleContent);
SimpleExtensionType simpleContentExtension = new SimpleExtensionType();
javax.lang.model.element.Element enumElement = context.getTypeUtils().asElement(genericType);
simpleContentExtension.setBase(new QName(targetNamespace, enumElement.getSimpleName() + ENUM_TYPE_SUFFIX));
simpleContent.setExtension(simpleContentExtension);
return complexType;
}
private LocalComplexType generateComplexTypeWithRef(Schema schema, TypeMirror genericType) {
LocalComplexType complexType = new LocalComplexType();
SimpleContent simpleContent = new SimpleContent();
complexType.setSimpleContent(simpleContent);
SimpleExtensionType simpleContentExtension = new SimpleExtensionType();
simpleContentExtension.setBase(SchemaTypeConversion.convertType(genericType.toString(), schema.getTargetNamespace()));
simpleContent.setExtension(simpleContentExtension);
Attribute refAttribute = new Attribute();
refAttribute.setUse(SchemaConstants.USE_OPTIONAL);
refAttribute.setName(ATTRIBUTE_NAME_VALUE_REF);
refAttribute.setType(SchemaConstants.STRING);
simpleContentExtension.getAttributeOrAttributeGroup().add(refAttribute);
return complexType;
}
private LocalComplexType generateRefComplexType(String name) {
LocalComplexType itemComplexType = new LocalComplexType();
Attribute refAttribute = new Attribute();
refAttribute.setUse(SchemaConstants.USE_REQUIRED);
refAttribute.setName(name);
refAttribute.setType(SchemaConstants.STRING);
itemComplexType.getAttributeOrAttributeGroup().add(refAttribute);
return itemComplexType;
}
private TopLevelElement generateXmlElement(String elementName, String targetNamespace) {
TopLevelElement xmlElement = new TopLevelElement();
xmlElement.setName(elementName);
xmlElement.setType(new QName(targetNamespace, XML_TYPE_SUFFIX));
return xmlElement;
}
private ComplexType createAnyXmlType() {
ComplexType xmlComplexType = new TopLevelComplexType();
xmlComplexType.setName(XML_TYPE_SUFFIX);
Any any = new Any();
any.setProcessContents(LAX);
any.setMinOccurs(new BigInteger("0"));
any.setMaxOccurs(UNBOUNDED);
ExplicitGroup all = new ExplicitGroup();
all.getParticle().add(any);
xmlComplexType.setSequence(all);
Attribute ref = createAttribute(ATTRIBUTE_NAME_REF, true, SchemaConstants.STRING, ATTRIBUTE_NAME_REF_DESCRIPTION);
xmlComplexType.getAttributeOrAttributeGroup().add(ref);
return xmlComplexType;
}
private void registerConfigElement(Schema schema, String targetNamespace, DevKitTypeElement typeElement) {
DefinedClass moduleClass = context.getClassForRole(context.getNameUtils().generateModuleObjectRoleKey(typeElement));
Map<QName, String> otherAttributes = new HashMap<QName, String>();
otherAttributes.put(SchemaConstants.MULE_DEVKIT_JAVA_CLASS_TYPE, moduleClass.fullName());
ExtensionType config = registerExtension(schema, SchemaConstants.ELEMENT_NAME_CONFIG, otherAttributes);
Attribute nameAttribute = createAttribute(ATTRIBUTE_NAME_NAME, true, SchemaConstants.STRING, ATTRIBUTE_NAME_NAME_DESCRIPTION);
config.getAttributeOrAttributeGroup().add(nameAttribute);
ExplicitGroup all = new ExplicitGroup();
config.setSequence(all);
for (VariableElement variable : typeElement.getFieldsAnnotatedWith(Configurable.class)) {
if (context.getTypeMirrorUtils().isCollection(variable.asType())) {
generateCollectionElement(schema, targetNamespace, all, variable);
} else {
config.getAttributeOrAttributeGroup().add(createAttribute(schema, variable));
}
}
for (VariableElement variable : typeElement.getFieldsAnnotatedWith(Inject.class)) {
if( variable.asType().toString().equals("org.mule.api.store.ObjectStore") ) {
config.getAttributeOrAttributeGroup().add(createObjectStoreRefAttribute(variable));
}
}
// get the executable typeElement for create connectivity
ExecutableElement connectMethod = connectMethodForClass(typeElement);
if (connectMethod != null) {
// add a configurable argument for each connectivity variable
for (VariableElement connectVariable : connectMethod.getParameters()) {
if (context.getTypeMirrorUtils().isCollection(connectVariable.asType())) {
generateCollectionElement(schema, targetNamespace, all, connectVariable, true);
} else {
config.getAttributeOrAttributeGroup().add(createParameterAttribute(schema, connectVariable, true));
}
}
TopLevelElement poolingProfile = new TopLevelElement();
poolingProfile.setName(CONNECTION_POOLING_PROFILE);
poolingProfile.setType(SchemaConstants.MULE_POOLING_PROFILE_TYPE);
poolingProfile.setMinOccurs(BigInteger.valueOf(0L));
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(CONNECTION_POOLING_PROFILE_ELEMENT_DESCRIPTION);
annotation.getAppinfoOrDocumentation().add(doc);
poolingProfile.setAnnotation(annotation);
all.getParticle().add(objectFactory.createElement(poolingProfile));
}
// add oauth callback configuration
if (typeElement.hasAnnotation(OAuth.class) || typeElement.hasAnnotation(OAuth2.class)) {
generateHttpCallbackElement(OAUTH_CALLBACK_CONFIG_ELEMENT_NAME, all);
generateOAuthSaveAccessTokenElement(all);
generateOAuthRestoreAccessTokenElement(all);
}
if (typeElement.hasProcessorMethodWithParameter(HttpCallback.class)) {
generateHttpCallbackElement(HTTP_CALLBACK_CONFIG_ELEMENT_NAME, all);
}
if (typeElement.isPoolable()) {
//<xsd:element name="abstract-pooling-profile" abstract="true" type="abstractPoolingProfileType"/>
TopLevelElement poolingProfile = new TopLevelElement();
poolingProfile.setName(POOLING_PROFILE_ELEMENT);
poolingProfile.setType(SchemaConstants.MULE_POOLING_PROFILE_TYPE);
poolingProfile.setMinOccurs(BigInteger.valueOf(0L));
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(POOLING_PROFILE_ELEMENT_DESCRIPTION);
annotation.getAppinfoOrDocumentation().add(doc);
poolingProfile.setAnnotation(annotation);
all.getParticle().add(objectFactory.createElement(poolingProfile));
}
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getSummary(typeElement.getInnerTypeElement()));
annotation.getAppinfoOrDocumentation().add(doc);
config.setAnnotation(annotation);
if (all.getParticle().size() == 0) {
config.setSequence(null);
}
}
private void generateOAuthSaveAccessTokenElement(ExplicitGroup all) {
TopLevelElement collectionElement = new TopLevelElement();
all.getParticle().add(objectFactory.createElement(collectionElement));
collectionElement.setName(OAUTH_SAVE_ACCESS_TOKEN_ELEMENT);
collectionElement.setMinOccurs(BigInteger.valueOf(0L));
collectionElement.setMaxOccurs("1");
LocalComplexType collectionComplexType = new LocalComplexType();
GroupRef group = generateNestedProcessorGroup();
collectionComplexType.setGroup(group);
collectionElement.setComplexType(collectionComplexType);
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(OAUTH_SAVE_ACCESS_TOKEN_ELEMENT_DESCRIPTION);
annotation.getAppinfoOrDocumentation().add(doc);
collectionElement.setAnnotation(annotation);
}
private void generateOAuthRestoreAccessTokenElement(ExplicitGroup all) {
TopLevelElement collectionElement = new TopLevelElement();
all.getParticle().add(objectFactory.createElement(collectionElement));
collectionElement.setName(OAUTH_RESTORE_ACCESS_TOKEN_ELEMENT);
collectionElement.setMinOccurs(BigInteger.valueOf(0L));
collectionElement.setMaxOccurs("1");
LocalComplexType collectionComplexType = new LocalComplexType();
GroupRef group = generateNestedProcessorGroup();
collectionComplexType.setGroup(group);
collectionElement.setComplexType(collectionComplexType);
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(OAUTH_RESTORE_ACCESS_TOKEN_ELEMENT_DESCRIPTION);
annotation.getAppinfoOrDocumentation().add(doc);
collectionElement.setAnnotation(annotation);
}
private void generateHttpCallbackElement(String elementName, ExplicitGroup all) {
Attribute domainAttribute = new Attribute();
domainAttribute.setUse(SchemaConstants.USE_OPTIONAL);
domainAttribute.setName(DOMAIN_ATTRIBUTE_NAME);
domainAttribute.setType(SchemaConstants.STRING);
domainAttribute.setDefault(DOMAIN_DEFAULT_VALUE);
Attribute localPortAttribute = new Attribute();
localPortAttribute.setUse(SchemaConstants.USE_OPTIONAL);
localPortAttribute.setName(LOCAL_PORT_ATTRIBUTE_NAME);
localPortAttribute.setType(SchemaConstants.STRING);
localPortAttribute.setDefault(PORT_DEFAULT_VALUE);
Attribute remotePortAttribute = new Attribute();
remotePortAttribute.setUse(SchemaConstants.USE_OPTIONAL);
remotePortAttribute.setName(REMOTE_PORT_ATTRIBUTE_NAME);
remotePortAttribute.setType(SchemaConstants.STRING);
remotePortAttribute.setDefault(PORT_DEFAULT_VALUE);
Attribute asyncAttribute = new Attribute();
asyncAttribute.setUse(SchemaConstants.USE_OPTIONAL);
asyncAttribute.setName(ASYNC_ATTRIBUTE_NAME);
asyncAttribute.setType(SchemaConstants.BOOLEAN);
asyncAttribute.setDefault(ASYNC_DEFAULT_VALUE);
Attribute connectorRefAttribute = new Attribute();
connectorRefAttribute.setUse(SchemaConstants.USE_OPTIONAL);
connectorRefAttribute.setName("connector-ref");
connectorRefAttribute.setType(SchemaConstants.STRING);
TopLevelElement httpCallbackConfig = new TopLevelElement();
httpCallbackConfig.setName(elementName);
httpCallbackConfig.setMinOccurs(BigInteger.ZERO);
httpCallbackConfig.setMaxOccurs("1");
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add("Config for http callbacks.");
annotation.getAppinfoOrDocumentation().add(doc);
httpCallbackConfig.setAnnotation(annotation);
ExtensionType extensionType = new ExtensionType();
extensionType.setBase(SchemaConstants.MULE_ABSTRACT_EXTENSION_TYPE);
extensionType.getAttributeOrAttributeGroup().add(localPortAttribute);
extensionType.getAttributeOrAttributeGroup().add(remotePortAttribute);
extensionType.getAttributeOrAttributeGroup().add(domainAttribute);
extensionType.getAttributeOrAttributeGroup().add(asyncAttribute);
extensionType.getAttributeOrAttributeGroup().add(connectorRefAttribute);
ComplexContent complextContent = new ComplexContent();
complextContent.setExtension(extensionType);
LocalComplexType localComplexType = new LocalComplexType();
localComplexType.setComplexContent(complextContent);
httpCallbackConfig.setComplexType(localComplexType);
all.getParticle().add(objectFactory.createElement(httpCallbackConfig));
}
private Attribute createObjectStoreRefAttribute(VariableElement variable) {
Attribute attribute = new Attribute();
// set whenever or not is optional
attribute.setUse(SchemaConstants.USE_OPTIONAL);
attribute.setName("objectStore-ref");
attribute.setType(SchemaConstants.STRING);
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getSummary(variable));
annotation.getAppinfoOrDocumentation().add(doc);
attribute.setAnnotation(annotation);
return attribute;
}
private Attribute createAttribute(Schema schema, VariableElement variable) {
Named named = variable.getAnnotation(Named.class);
Optional optional = variable.getAnnotation(Optional.class);
Default def = variable.getAnnotation(Default.class);
String name = variable.getSimpleName().toString();
if (named != null && named.value().length() > 0) {
name = named.value();
}
Attribute attribute = new Attribute();
// set whenever or not is optional
attribute.setUse(optional != null ? SchemaConstants.USE_OPTIONAL : SchemaConstants.USE_REQUIRED);
if (isTypeSupported(variable.asType())) {
attribute.setName(name);
attribute.setType(SchemaTypeConversion.convertType(variable.asType().toString(), schema.getTargetNamespace()));
} else if (context.getTypeMirrorUtils().isEnum(variable.asType())) {
attribute.setName(name);
javax.lang.model.element.Element enumElement = context.getTypeUtils().asElement(variable.asType());
attribute.setType(new QName(schema.getTargetNamespace(), enumElement.getSimpleName() + ENUM_TYPE_SUFFIX));
} else {
// non-supported types will get "-ref" so beans can be injected
attribute.setName(name + REF_SUFFIX);
attribute.setType(SchemaConstants.STRING);
}
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getSummary(variable));
annotation.getAppinfoOrDocumentation().add(doc);
attribute.setAnnotation(annotation);
// add default value
if (def != null && def.value().length() > 0) {
attribute.setDefault(def.value());
}
return attribute;
}
private Attribute createParameterAttribute(Schema schema, VariableElement variable) {
return createParameterAttribute(schema, variable, false);
}
private Attribute createParameterAttribute(Schema schema, VariableElement variable, boolean forceOptional) {
Named named = variable.getAnnotation(Named.class);
Optional optional = variable.getAnnotation(Optional.class);
Default def = variable.getAnnotation(Default.class);
String name = variable.getSimpleName().toString();
if (named != null && named.value().length() > 0) {
name = named.value();
}
Attribute attribute = new Attribute();
// set whenever or not is optional
if (!forceOptional) {
attribute.setUse(optional != null ? SchemaConstants.USE_OPTIONAL : SchemaConstants.USE_REQUIRED);
} else {
attribute.setUse(SchemaConstants.USE_OPTIONAL);
}
if (isTypeSupported(variable.asType())) {
attribute.setName(name);
attribute.setType(SchemaTypeConversion.convertType(variable.asType().toString(), schema.getTargetNamespace()));
} else if (context.getTypeMirrorUtils().isEnum(variable.asType())) {
attribute.setName(name);
javax.lang.model.element.Element enumElement = context.getTypeUtils().asElement(variable.asType());
attribute.setType(new QName(schema.getTargetNamespace(), enumElement.getSimpleName() + ENUM_TYPE_SUFFIX));
} else if (context.getTypeMirrorUtils().isHttpCallback(variable)) {
attribute.setName(context.getNameUtils().uncamel(name) + FLOW_REF_SUFFIX);
attribute.setType(SchemaConstants.STRING);
} else {
// non-supported types will get "-ref" so beans can be injected
attribute.setName(name + REF_SUFFIX);
attribute.setType(SchemaConstants.STRING);
}
// add doc
Annotation annotation = new Annotation();
Documentation doc = new Documentation();
doc.getContent().add(context.getJavaDocUtils().getParameterSummary(variable.getSimpleName().toString(), variable.getEnclosingElement()));
annotation.getAppinfoOrDocumentation().add(doc);
attribute.setAnnotation(annotation);
// add default value
if (def != null && def.value().length() > 0) {
attribute.setDefault(def.value());
}
return attribute;
}
private boolean isTypeSupported(TypeMirror typeMirror) {
return SchemaTypeConversion.isSupported(typeMirror.toString());
}
private void importMuleNamespace(Schema schema) {
Import muleSchemaImport = new Import();
muleSchemaImport.setNamespace(SchemaConstants.MULE_NAMESPACE);
muleSchemaImport.setSchemaLocation(SchemaConstants.MULE_SCHEMA_LOCATION);
schema.getIncludeOrImportOrRedefine().add(muleSchemaImport);
}
private void importMuleDevKitNamespace(Schema schema) {
Import muleSchemaImport = new Import();
muleSchemaImport.setNamespace(SchemaConstants.MULE_DEVKIT_NAMESPACE);
muleSchemaImport.setSchemaLocation(SchemaConstants.MULE_DEVKIT_SCHEMA_LOCATION);
schema.getIncludeOrImportOrRedefine().add(muleSchemaImport);
}
private void importSpringFrameworkNamespace(Schema schema) {
Import springFrameworkImport = new Import();
springFrameworkImport.setNamespace(SchemaConstants.SPRING_FRAMEWORK_NAMESPACE);
springFrameworkImport.setSchemaLocation(SchemaConstants.SPRING_FRAMEWORK_SCHEMA_LOCATION);
schema.getIncludeOrImportOrRedefine().add(springFrameworkImport);
}
private void importXmlNamespace(Schema schema) {
Import xmlImport = new Import();
xmlImport.setNamespace(SchemaConstants.XML_NAMESPACE);
schema.getIncludeOrImportOrRedefine().add(xmlImport);
}
private Attribute createAttribute(String name, boolean optional, QName type, String description) {
Attribute attr = new Attribute();
attr.setName(name);
attr.setUse(optional ? SchemaConstants.USE_OPTIONAL : SchemaConstants.USE_REQUIRED);
attr.setType(type);
Annotation nameAnnotation = new Annotation();
attr.setAnnotation(nameAnnotation);
Documentation nameDocumentation = new Documentation();
nameDocumentation.getContent().add(description);
nameAnnotation.getAppinfoOrDocumentation().add(nameDocumentation);
return attr;
}
private Element registerTransformer(String name) {
Element transformer = new TopLevelElement();
transformer.setName(name);
transformer.setSubstitutionGroup(SchemaConstants.MULE_ABSTRACT_TRANSFORMER);
transformer.setType(SchemaConstants.MULE_ABSTRACT_TRANSFORMER_TYPE);
return transformer;
}
private ExtensionType registerExtension(Schema schema, String name, Map<QName, String> otherAttributes) {
LocalComplexType complexType = new LocalComplexType();
Element extension = new TopLevelElement();
extension.setName(name);
extension.setSubstitutionGroup(SchemaConstants.MULE_ABSTRACT_EXTENSION);
extension.setComplexType(complexType);
extension.getOtherAttributes().putAll(otherAttributes);
ComplexContent complexContent = new ComplexContent();
complexType.setComplexContent(complexContent);
ExtensionType complexContentExtension = new ExtensionType();
complexContentExtension.setBase(SchemaConstants.MULE_ABSTRACT_EXTENSION_TYPE);
complexContent.setExtension(complexContentExtension);
schema.getSimpleTypeOrComplexTypeOrGroup().add(extension);
return complexContentExtension;
}
private void registerTypes(Schema schema) {
registerType(schema, "integerType", SchemaConstants.INTEGER);
registerType(schema, "decimalType", SchemaConstants.DECIMAL);
registerType(schema, "floatType", SchemaConstants.FLOAT);
registerType(schema, "doubleType", SchemaConstants.DOUBLE);
registerType(schema, "dateTimeType", SchemaConstants.DATETIME);
registerType(schema, "longType", SchemaConstants.LONG);
registerType(schema, "byteType", SchemaConstants.BYTE);
registerType(schema, "booleanType", SchemaConstants.BOOLEAN);
registerType(schema, "anyUriType", SchemaConstants.ANYURI);
registerType(schema, "charType", SchemaConstants.STRING, 1, 1);
registerAnyXmlType(schema);
}
private void registerAnyXmlType(Schema schema) {
ComplexType xmlComplexType = createAnyXmlType();
schema.getSimpleTypeOrComplexTypeOrGroup().add(xmlComplexType);
}
private void registerType(Schema schema, String name, QName base) {
registerType(schema, name, base, -1, -1);
}
private void registerType(Schema schema, String name, QName base, int minlen, int maxlen) {
SimpleType simpleType = new TopLevelSimpleType();
simpleType.setName(name);
Union union = new Union();
simpleType.setUnion(union);
union.getSimpleType().add(createSimpleType(base, minlen, maxlen));
union.getSimpleType().add(createExpressionAndPropertyPlaceHolderSimpleType());
schema.getSimpleTypeOrComplexTypeOrGroup().add(simpleType);
}
private LocalSimpleType createSimpleType(QName base, int minlen, int maxlen) {
LocalSimpleType simpleType = new LocalSimpleType();
Restriction restriction = new Restriction();
restriction.setBase(base);
if (minlen != -1) {
NumFacet minLenFacet = new NumFacet();
minLenFacet.setValue(Integer.toString(minlen));
JAXBElement<NumFacet> element = objectFactory.createMinLength(minLenFacet);
restriction.getFacets().add(element);
}
if (maxlen != -1) {
NumFacet maxLenFacet = new NumFacet();
maxLenFacet.setValue(Integer.toString(maxlen));
JAXBElement<NumFacet> element = objectFactory.createMaxLength(maxLenFacet);
restriction.getFacets().add(element);
}
simpleType.setRestriction(restriction);
return simpleType;
}
private LocalSimpleType createExpressionAndPropertyPlaceHolderSimpleType() {
LocalSimpleType expression = new LocalSimpleType();
Restriction restriction = new Restriction();
expression.setRestriction(restriction);
restriction.setBase(SchemaConstants.STRING);
Pattern pattern = new Pattern();
pattern.setValue("(\\#\\[[^\\]]+\\]|\\$\\{[^\\}]+\\})");
restriction.getFacets().add(pattern);
return expression;
}
private LocalSimpleType createExpressionSimpleType() {
LocalSimpleType expression = new LocalSimpleType();
Restriction restriction = new Restriction();
expression.setRestriction(restriction);
restriction.setBase(SchemaConstants.STRING);
Pattern pattern = new Pattern();
pattern.setValue("\\#\\[[^\\]]+\\]");
restriction.getFacets().add(pattern);
return expression;
}
}