org.hisrc.jsonix.compilation.jsonschema.JsonSchemaPropertyInfoProducerVisitor Maven / Gradle / Ivy
package org.hisrc.jsonix.compilation.jsonschema;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.commons.lang3.Validate;
import org.hisrc.jsonix.JsonixConstants;
import org.hisrc.jsonix.jsonschema.JsonSchemaBuilder;
import org.hisrc.jsonix.jsonschema.JsonSchemaConstants;
import org.hisrc.jsonix.naming.StandardNaming;
import org.hisrc.jsonix.xml.xsom.ParticleMultiplicityCounter;
import org.hisrc.xml.xsom.XSFunctionApplier;
import org.jvnet.jaxb2_commons.xml.bind.model.MAnyAttributePropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MAnyElementPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MAttributePropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElement;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementRefPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementRefsPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementTypeInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementTypeInfos;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementTypeRef;
import org.jvnet.jaxb2_commons.xml.bind.model.MElementsPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MPropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MPropertyInfoVisitor;
import org.jvnet.jaxb2_commons.xml.bind.model.MTypeInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MValuePropertyInfo;
import org.jvnet.jaxb2_commons.xml.bind.model.MWrappable;
import org.jvnet.jaxb2_commons.xml.bind.model.origin.MElementOrigin;
import org.jvnet.jaxb2_commons.xml.bind.model.origin.MElementTypeRefOrigin;
import org.jvnet.jaxb2_commons.xml.bind.model.origin.MOriginated;
import com.sun.tools.xjc.model.Multiplicity;
public class JsonSchemaPropertyInfoProducerVisitor implements
MPropertyInfoVisitor {
private final JsonSchemaClassInfoProducer classInfoCompiler;
private final XSFunctionApplier multiplicityCounter = new XSFunctionApplier(
ParticleMultiplicityCounter.INSTANCE);
public JsonSchemaPropertyInfoProducerVisitor(
JsonSchemaClassInfoProducer classInfoCompiler) {
Validate.notNull(classInfoCompiler);
this.classInfoCompiler = classInfoCompiler;
}
public JsonSchemaClassInfoProducer getClassInfoCompiler() {
return classInfoCompiler;
}
@Override
public JsonSchemaBuilder visitElementPropertyInfo(
MElementPropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ELEMENT, schema);
addElementNameSchema(info.getElementName(), schema);
addWrappableSchema(info, schema);
final JsonSchemaBuilder itemTypeSchema = createTypeSchema(info, info
.getTypeInfo());
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, itemTypeSchema);
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitElementsPropertyInfo(
MElementsPropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ELEMENTS, schema);
addWrappableSchema(info, schema);
final JsonSchemaBuilder itemTypeSchema = createElementTypeInfosSchema(info);
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, itemTypeSchema);
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitElementRefPropertyInfo(
MElementRefPropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ELEMENT_REF, schema);
addElementNameSchema(info.getElementName(), schema);
addWrappableSchema(info, schema);
final List itemTypeSchemas = new ArrayList(
3);
if (info.isMixed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(XmlSchemaJsonSchemaConstants.STRING_TYPE_INFO_SCHEMA_REF));
}
if (info.isDomAllowed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(JsonixJsonSchemaConstants.DOM_TYPE_INFO_SCHEMA_REF));
}
if (info.isTypedObjectAllowed()) {
itemTypeSchemas.add(createElementRefSchema(info));
}
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, createPossiblyAnyOfTypeSchema(itemTypeSchemas));
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitElementRefsPropertyInfo(
MElementRefsPropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ELEMENT_REFS, schema);
addWrappableSchema(info, schema);
final List itemTypeSchemas = new ArrayList(
2 + info.getElementTypeInfos().size());
if (info.isMixed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(XmlSchemaJsonSchemaConstants.STRING_TYPE_INFO_SCHEMA_REF));
}
if (info.isDomAllowed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(JsonixJsonSchemaConstants.DOM_TYPE_INFO_SCHEMA_REF));
}
if (info.isTypedObjectAllowed()) {
itemTypeSchemas.addAll(createElementRefsSchema(info));
}
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, createPossiblyAnyOfTypeSchema(itemTypeSchemas));
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitValuePropertyInfo(
MValuePropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.VALUE, schema);
final JsonSchemaBuilder itemTypeSchema = createTypeSchema(info, info
.getTypeInfo());
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, itemTypeSchema);
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitAnyElementPropertyInfo(
MAnyElementPropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ANY_ELEMENT, schema);
final List itemTypeSchemas = new ArrayList(
3);
if (info.isMixed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(XmlSchemaJsonSchemaConstants.STRING_TYPE_INFO_SCHEMA_REF));
}
if (info.isDomAllowed()) {
itemTypeSchemas
.add(new JsonSchemaBuilder()
.addRef(JsonixJsonSchemaConstants.DOM_TYPE_INFO_SCHEMA_REF));
}
if (info.isTypedObjectAllowed()) {
final JsonSchemaBuilder anyElementSchema = new JsonSchemaBuilder()
.addType(JsonSchemaConstants.OBJECT_TYPE)
.addProperty(
JsonixConstants.NAME_PROPERTY_NAME,
new JsonSchemaBuilder()
.addRef(XmlSchemaJsonSchemaConstants.QNAME_TYPE_INFO_SCHEMA_REF))
.addProperty(JsonixConstants.VALUE_PROPERTY_NAME,
new JsonSchemaBuilder());
itemTypeSchemas.add(anyElementSchema);
}
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, createPossiblyAnyOfTypeSchema(itemTypeSchemas));
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitAttributePropertyInfo(
MAttributePropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ATTRIBUTE, schema);
addAttributeNameSchema(info.getAttributeName(), schema);
final JsonSchemaBuilder itemTypeSchema = createTypeSchema(info, info
.getTypeInfo());
final JsonSchemaBuilder typeSchema = createPossiblyCollectionTypeSchema(
info, itemTypeSchema);
schema.addAllOf(typeSchema);
return schema;
}
@Override
public JsonSchemaBuilder visitAnyAttributePropertyInfo(
MAnyAttributePropertyInfo info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addPropertyInfoSchema(info, schema);
addPropertyInfoTypeSchema(StandardNaming.ANY_ATTRIBUTE, schema);
final JsonSchemaBuilder typeSchema = new JsonSchemaBuilder().addType(
JsonSchemaConstants.OBJECT_TYPE).addAdditionalProperties(
new JsonSchemaBuilder()
.addType(JsonSchemaConstants.STRING_TYPE));
schema.addAllOf(typeSchema);
return schema;
}
private void addPropertyInfoTypeSchema(String string,
JsonSchemaBuilder schema) {
schema.add(JsonixJsonSchemaConstants.PROPERTY_TYPE_PROPERTY_NAME,
string);
}
private void addPropertyInfoSchema(MPropertyInfo propertyInfo,
JsonSchemaBuilder schema) {
schema.addTitle(propertyInfo.getPrivateName());
}
private void addWrappableSchema(MWrappable info, JsonSchemaBuilder schema) {
final QName wrapperElementName = info.getWrapperElementName();
if (wrapperElementName != null) {
addNameSchema(
schema,
JsonixJsonSchemaConstants.WRAPPER_ELEMENT_NAME_PROPERTY_NAME,
wrapperElementName);
}
}
private void addNameSchema(JsonSchemaBuilder schema, final String key,
final QName name) {
schema.add(key, createNameSchema(name));
}
private JsonSchemaBuilder createNameSchema(final QName elementName) {
return new JsonSchemaBuilder().add(
JsonixJsonSchemaConstants.LOCAL_PART_PROPERTY_NAME,
elementName.getLocalPart()).add(
JsonixJsonSchemaConstants.NAMESPACE_URI_PROPERTY_NAME,
elementName.getNamespaceURI());
}
private void addElementNameSchema(QName elementName,
JsonSchemaBuilder schema) {
addNameSchema(schema,
JsonixJsonSchemaConstants.ELEMENT_NAME_PROPERTY_NAME,
elementName);
}
private void addAttributeNameSchema(QName attributeName,
JsonSchemaBuilder schema) {
addNameSchema(schema,
JsonixJsonSchemaConstants.ATTRIBUTE_NAME_PROPERTY_NAME,
attributeName);
}
private JsonSchemaBuilder createElementTypeInfosSchema(
MElementTypeInfos, MElementTypeRefOrigin> info) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
if (!info.getElementTypeInfos().isEmpty()) {
for (MElementTypeRef elementTypeInfo : info
.getElementTypeInfos()) {
final JsonSchemaBuilder elementTypeInfoSchema = createElementTypeInfoSchema(elementTypeInfo);
schema.addAnyOf(elementTypeInfoSchema);
}
}
return schema;
}
private JsonSchemaBuilder createElementTypeInfoSchema(
MElementTypeRef elementTypeInfo) {
final JsonSchemaBuilder elementTypeInfoSchema = new JsonSchemaBuilder();
addElementNameSchema(elementTypeInfo.getElementName(),
elementTypeInfoSchema);
elementTypeInfoSchema.addAnyOf(createTypeSchema(elementTypeInfo, elementTypeInfo
.getTypeInfo()));
return elementTypeInfoSchema;
}
private List createElementRefsSchema(
MElementTypeInfos, MElementOrigin> info) {
final List> elementTypeInfos = info
.getElementTypeInfos();
final List schemas = new ArrayList(
elementTypeInfos.size());
for (MElement elementTypeInfo : elementTypeInfos) {
final JsonSchemaBuilder elementTypeInfoSchema = createElementRefSchema(elementTypeInfo);
schemas.add(elementTypeInfoSchema);
}
return schemas;
}
private , O> JsonSchemaBuilder createElementRefSchema(
M elementTypeInfo) {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
addElementNameSchema(elementTypeInfo.getElementName(), schema);
schema.addType(JsonSchemaConstants.OBJECT_TYPE);
schema.addProperty(
JsonixConstants.NAME_PROPERTY_NAME,
new JsonSchemaBuilder()
.addRef(XmlSchemaJsonSchemaConstants.QNAME_TYPE_INFO_SCHEMA_REF));
schema.addProperty(JsonixConstants.VALUE_PROPERTY_NAME,
createTypeSchema(elementTypeInfo, elementTypeInfo.getTypeInfo()));
return schema;
}
private JsonSchemaBuilder createPossiblyAnyOfTypeSchema(
final List schemas) {
if (schemas.size() == 0) {
return new JsonSchemaBuilder();
} else if (schemas.size() == 1) {
return schemas.get(0);
} else {
final JsonSchemaBuilder schema = new JsonSchemaBuilder();
schema.addAnyOf(schemas);
return schema;
}
}
private JsonSchemaBuilder createPossiblyCollectionTypeSchema(
MPropertyInfo propertyInfo,
final JsonSchemaBuilder itemTypeSchema) {
final JsonSchemaBuilder typeSchema;
if (propertyInfo.isCollection()) {
typeSchema = new JsonSchemaBuilder();
typeSchema.addType(JsonSchemaConstants.ARRAY_TYPE).addItem(
itemTypeSchema);
final Multiplicity multiplicity = multiplicityCounter
.apply(propertyInfo.getOrigin());
if (multiplicity != null) {
if (multiplicity.min != null) {
typeSchema.addMinItems(multiplicity.min);
}
if (multiplicity.max != null) {
typeSchema.addMaxItems(multiplicity.max);
}
}
} else {
typeSchema = itemTypeSchema;
}
return typeSchema;
}
private , O> JsonSchemaBuilder createTypeSchema(
M originated, MTypeInfo typeInfo) {
return getClassInfoCompiler().getMappingCompiler()
.createTypeInfoSchemaRef(originated, typeInfo);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy