org.hisrc.jsonix.compilation.MappingCompiler Maven / Gradle / Ivy
/**
* Jsonix is a JavaScript library which allows you to convert between XML
* and JavaScript object structures.
*
* Copyright (c) 2010 - 2014, Alexey Valikov, Highsource.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hisrc.jsonix.compilation;
import java.util.Collection;
import javax.xml.namespace.QName;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.hisrc.jscm.codemodel.JSCodeModel;
import org.hisrc.jscm.codemodel.expression.JSArrayLiteral;
import org.hisrc.jscm.codemodel.expression.JSAssignmentExpression;
import org.hisrc.jscm.codemodel.expression.JSMemberExpression;
import org.hisrc.jscm.codemodel.expression.JSObjectLiteral;
import org.hisrc.jsonix.definition.Mapping;
import org.hisrc.jsonix.definition.MappingDependency;
import org.hisrc.jsonix.definition.Module;
import org.hisrc.jsonix.definition.Modules;
import org.hisrc.jsonix.definition.Output;
import org.hisrc.jsonix.naming.Naming;
import org.jvnet.jaxb2_commons.xml.bind.model.MClassInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MClassTypeInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MEnumConstantInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MEnumLeafInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MPackageInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MTypeInfo;
public class MappingCompiler {
public static final String DEFAULT_SCOPED_NAME_DELIMITER = ".";
private final JSCodeModel codeModel;
public final String mappingName;
private final String defaultElementNamespaceURI;
private final String defaultAttributeNamespaceURI;
private final Modules modules;
private Naming naming;
private Mapping mapping;
private Output output;
public MappingCompiler(JSCodeModel codeModel, Modules modules,
Module module, Output output, Mapping mapping) {
Validate.notNull(codeModel);
Validate.notNull(modules);
Validate.notNull(module);
Validate.notNull(mapping);
Validate.notNull(output);
this.codeModel = codeModel;
this.modules = modules;
this.mapping = mapping;
this.mappingName = mapping.getMappingName();
this.defaultElementNamespaceURI = mapping
.getDefaultElementNamespaceURI();
this.defaultAttributeNamespaceURI = mapping
.getDefaultAttributeNamespaceURI();
this.output = output;
this.naming = output.getNaming();
}
public Modules getModules() {
return modules;
}
public JSCodeModel getCodeModel() {
return codeModel;
}
public Naming getNaming() {
return naming;
}
public Mapping getMapping() {
return mapping;
}
public Output getOutput() {
return output;
}
public JSObjectLiteral compile() {
final JSObjectLiteral mappingBody = codeModel.object();
mappingBody.append(naming.name(), codeModel.string(this.mappingName));
if (!StringUtils.isEmpty(this.defaultElementNamespaceURI)) {
mappingBody.append(naming.defaultElementNamespaceURI(),
codeModel.string(this.defaultElementNamespaceURI));
}
if (!StringUtils.isEmpty(this.defaultAttributeNamespaceURI)) {
mappingBody.append(naming.defaultAttributeNamespaceURI(),
codeModel.string(this.defaultAttributeNamespaceURI));
}
final JSArrayLiteral dependencies = codeModel.array();
compileDependencies(dependencies);
if (!dependencies.getElements().isEmpty()) {
mappingBody.append(naming.dependencies(), dependencies);
}
final JSArrayLiteral typeInfos = codeModel.array();
mappingBody.append(naming.typeInfos(), typeInfos);
final JSArrayLiteral elementInfos = codeModel.array();
mappingBody.append(naming.elementInfos(), elementInfos);
compileClassInfos(typeInfos);
compileEnumLeafInfos(typeInfos);
compileElementInfos(elementInfos);
return mappingBody;
}
private void compileDependencies(JSArrayLiteral dependencies) {
final Collection> mappingDependencies = mapping
.getDirectDependencies();
for (final MappingDependency mappingDependency : mappingDependencies) {
final MPackageInfo dependencyPackageInfo = mappingDependency
.getPackageInfo();
final String dependencyPackageName = dependencyPackageInfo
.getPackageName();
final String dependencyMappingName = modules
.getMappingName(dependencyPackageName);
dependencies.append(getCodeModel().string(dependencyMappingName));
}
}
private void compileClassInfos(JSArrayLiteral typeInfos) {
for (MClassInfo classInfo : mapping.getClassInfos()) {
typeInfos.append(compileClassInfo(classInfo));
}
}
private void compileEnumLeafInfos(JSArrayLiteral typeInfos) {
for (MEnumLeafInfo enumLeafInfo : mapping.getEnumLeafInfos()) {
typeInfos.append(compileEnumLeafInfo(enumLeafInfo));
}
}
private JSObjectLiteral compileClassInfo(MClassInfo classInfo) {
final JSObjectLiteral classInfoMapping = this.codeModel.object();
classInfoMapping.append(naming.localName(), this.codeModel
.string(classInfo
.getContainerLocalName(DEFAULT_SCOPED_NAME_DELIMITER)));
final MClassTypeInfo baseTypeInfo = classInfo.getBaseTypeInfo();
if (baseTypeInfo != null) {
classInfoMapping.append(naming.baseTypeInfo(),
getTypeInfoDeclaration(baseTypeInfo));
}
final JSArrayLiteral ps = compilePropertyInfos(classInfo);
if (!ps.getElements().isEmpty()) {
classInfoMapping.append(naming.propertyInfos(), ps);
}
return classInfoMapping;
}
private JSObjectLiteral compileEnumLeafInfo(MEnumLeafInfo enumLeafInfo) {
final JSObjectLiteral mapping = this.codeModel.object();
mapping.append(naming.type(), this.codeModel.string(naming.enumInfo()));
mapping.append(naming.localName(), this.codeModel.string(enumLeafInfo
.getContainerLocalName(DEFAULT_SCOPED_NAME_DELIMITER)));
final MTypeInfo baseTypeInfo = enumLeafInfo.getBaseTypeInfo();
if (baseTypeInfo != null) {
final JSAssignmentExpression baseTypeInfoDeclaration = getTypeInfoDeclaration(baseTypeInfo);
if (!baseTypeInfoDeclaration
.acceptExpressionVisitor(new CheckValueStringLiteralExpressionVisitor(
"String"))) {
mapping.append(naming.baseTypeInfo(), baseTypeInfoDeclaration);
}
}
mapping.append(naming.values(), compileEnumConstrantInfos(enumLeafInfo));
return mapping;
}
private JSArrayLiteral compilePropertyInfos(MClassInfo classInfo) {
final JSArrayLiteral propertyInfoMappings = this.codeModel.array();
for (MPropertyInfo propertyInfo : classInfo.getProperties()) {
if (mapping.getPropertyInfos().contains(propertyInfo)) {
propertyInfoMappings
.append(propertyInfo
.acceptPropertyInfoVisitor(new PropertyInfoVisitor(
this)));
}
}
return propertyInfoMappings;
}
private JSArrayLiteral compileEnumConstrantInfos(
MEnumLeafInfo enumLeafInfo) {
final JSArrayLiteral mappings = this.codeModel.array();
for (MEnumConstantInfo enumConstantInfo : enumLeafInfo
.getConstants()) {
mappings.append(this.codeModel.string(enumConstantInfo
.getLexicalValue()));
}
return mappings;
}
private void compileElementInfos(JSArrayLiteral eis) {
for (MElementInfo elementInfo : mapping.getElementInfos()) {
eis.append(compileElementInfo(elementInfo));
}
}
private JSObjectLiteral compileElementInfo(MElementInfo elementInfo) {
MTypeInfo typeInfo = elementInfo.getTypeInfo();
MTypeInfo scope = elementInfo.getScope();
QName substitutionHead = elementInfo.getSubstitutionHead();
final JSObjectLiteral value = this.codeModel.object();
JSAssignmentExpression typeInfoDeclaration = getTypeInfoDeclaration(typeInfo);
QName elementName = elementInfo.getElementName();
value.append(naming.elementName(),
createElementNameExpression(elementName));
if (typeInfoDeclaration != null) {
if (!typeInfoDeclaration
.acceptExpressionVisitor(new CheckValueStringLiteralExpressionVisitor(
"String"))) {
value.append(naming.typeInfo(), typeInfoDeclaration);
}
}
if (scope != null) {
value.append(naming.scope(), getTypeInfoDeclaration(scope));
}
if (substitutionHead != null) {
value.append(naming.substitutionHead(),
createElementNameExpression(substitutionHead));
}
return value;
}
public JSMemberExpression createElementNameExpression(final QName name) {
Validate.notNull(name);
return createNameExpression(name, this.defaultElementNamespaceURI);
}
public JSMemberExpression createAttributeNameExpression(final QName name) {
Validate.notNull(name);
return createNameExpression(name, this.defaultAttributeNamespaceURI);
}
@SuppressWarnings("deprecation")
private JSMemberExpression createNameExpression(final QName name,
final String defaultNamespaceURI) {
final String draftNamespaceURI = name.getNamespaceURI();
final String namespaceURI = StringUtils.isEmpty(draftNamespaceURI) ? null
: draftNamespaceURI;
if (ObjectUtils.equals(defaultNamespaceURI, namespaceURI)) {
return this.codeModel.string(name.getLocalPart());
} else {
final JSObjectLiteral nameExpression = this.codeModel.object();
nameExpression.append(naming.localPart(),
this.codeModel.string(name.getLocalPart()));
if (!StringUtils.isEmpty(namespaceURI)) {
nameExpression.append(naming.namespaceURI(),
this.codeModel.string(namespaceURI));
}
return nameExpression;
}
}
public JSAssignmentExpression getTypeInfoDeclaration(
MTypeInfo typeInfo) {
return typeInfo
.acceptTypeInfoVisitor(new CreateTypeInfoDeclarationVisitor(
this));
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy