You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/09/02 14:10:31 UTC
[09/51] [partial] incubator-juneau git commit: Add project
hierarchies, part 1
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
new file mode 100644
index 0000000..2e65494
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
@@ -0,0 +1,1490 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.net.*;
+import java.net.URI;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Represents a top-level schema object bean in the JSON-Schema core specification.
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+@SuppressWarnings("hiding")
+@Bean(typeName="schema",
+ properties="id,$schema,$ref, title,description,type,definitions,properties,"
+ + "patternProperties,dependencies,items,multipleOf,maximum,exclusiveMaximum,"
+ + "minimum,exclusiveMinimum,maxLength,minLength,pattern,additionalItems,"
+ + "maxItems,minItems,uniqueItems,maxProperties,minProperties,required,"
+ + "additionalProperties,enum,allOf,anyOf,oneOf,not"
+)
+public class Schema {
+ private String name; // Property name. Not serialized.
+ private URI id;
+ private URI schemaVersion;
+ private String title;
+ private String description;
+ private JsonType typeJsonType; // JsonType representation of type
+ private JsonTypeArray typeJsonTypeArray; // JsonTypeArray representation of type
+ private Map<String,Schema> definitions;
+ private Map<String,Schema> properties;
+ private Map<String,Schema> patternProperties;
+ private Map<String,Schema> dependencies;
+ private Schema itemsSchema; // Schema representation of items
+ private SchemaArray itemsSchemaArray; // SchemaArray representation of items
+ private Number multipleOf;
+ private Number maximum;
+ private Boolean exclusiveMaximum;
+ private Number minimum;
+ private Boolean exclusiveMinimum;
+ private Integer maxLength;
+ private Integer minLength;
+ private String pattern;
+ private Boolean additionalItemsBoolean; // Boolean representation of additionalItems
+ private SchemaArray additionalItemsSchemaArray; // SchemaArray representation of additionalItems
+ private Integer maxItems;
+ private Integer minItems;
+ private Boolean uniqueItems;
+ private Integer maxProperties;
+ private Integer minProperties;
+ private List<String> required;
+ private Boolean additionalPropertiesBoolean; // Boolean representation of additionalProperties
+ private Schema additionalPropertiesSchema; // Schema representation of additionalProperties
+ private List<String> _enum;
+ private List<Schema> allOf;
+ private List<Schema> anyOf;
+ private List<Schema> oneOf;
+ private Schema not;
+ private URI ref;
+ private SchemaMap schemaMap;
+ private Schema master = this;
+
+ /**
+ * Default constructor.
+ */
+ public Schema() {}
+
+
+ //--------------------------------------------------------------------------------
+ // Bean properties
+ //--------------------------------------------------------------------------------
+
+ /**
+ * Bean property getter: <property>name</property>.
+ *
+ * @return The value of the <property>name</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ @BeanIgnore
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Bean property setter: <property>name</property>.
+ *
+ * @param name The new value for the <property>name</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ @BeanIgnore
+ public Schema setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>id</property>.
+ *
+ * @return The value of the <property>id</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public URI getId() {
+ return id;
+ }
+
+ /**
+ * Bean property setter: <property>id</property>.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param id The new value for the <property>id</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setId(Object id) {
+ this.id = toURI(id);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>$schema</property>.
+ *
+ * @return The value of the <property>$schema</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ @BeanProperty("$schema")
+ public URI getSchemaVersionUri() {
+ return schemaVersion;
+ }
+
+ /**
+ * Bean property setter: <property>$schema</property>.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param schemaVersion The new value for the <property>schemaVersion</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ @BeanProperty("$schema")
+ public Schema setSchemaVersionUri(Object schemaVersion) {
+ this.schemaVersion = toURI(schemaVersion);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>title</property>.
+ *
+ * @return The value of the <property>title</property> property, or <jk>null</jk> if it is not set.
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Bean property setter: <property>title</property>.
+ *
+ * @param title The new value for the <property>title</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>description</property>.
+ *
+ * @return The value of the <property>description</property> property, or <jk>null</jk> if it is not set.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Bean property setter: <property>description</property>.
+ *
+ * @param description The new value for the <property>description</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>type</property>.
+ *
+ * @return
+ * The value of the <property>type</property> property on this bean, or <jk>null</jk> if it is not set.
+ * Can be either a {@link JsonType} or {@link JsonTypeArray} depending on what value was used to set it.
+ */
+ @BeanProperty(swap=JsonTypeOrJsonTypeArraySwap.class)
+ public Object getType() {
+ if (typeJsonType != null)
+ return typeJsonType;
+ return typeJsonTypeArray;
+ }
+
+ /**
+ * Bean property getter: <property>type</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>type</property> property when it is a {@link JsonType} value.
+ *
+ * @return
+ * The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonTypeArray}.
+ */
+ @BeanIgnore
+ public JsonType getTypeAsJsonType() {
+ return typeJsonType;
+ }
+
+ /**
+ * Bean property getter: <property>type</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>type</property> property when it is a {@link JsonTypeArray} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link JsonType}.
+ */
+ @BeanIgnore
+ public JsonTypeArray getTypeAsJsonTypeArray() {
+ return typeJsonTypeArray;
+ }
+
+ /**
+ * Bean property setter: <property>type</property>.
+ *
+ * @param type
+ * The new value for the <property>type</property> property on this bean.
+ * This object must be of type {@link JsonType} or {@link JsonTypeArray}.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If invalid object type passed in.
+ */
+ public Schema setType(Object type) {
+ this.typeJsonType = null;
+ this.typeJsonTypeArray = null;
+ if (type != null) {
+ if (type instanceof JsonType)
+ this.typeJsonType = (JsonType)type;
+ else if (type instanceof JsonTypeArray)
+ this.typeJsonTypeArray = (JsonTypeArray)type;
+ else
+ throw new BeanRuntimeException(SchemaProperty.class,
+ "Invalid attribute type ''{0}'' passed in. Must be one of the following: SimpleType, SimpleTypeArray",
+ type.getClass().getName());
+ }
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>type</property>.
+ *
+ * @param types The list of items to append to the <property>type</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addTypes(JsonType...types) {
+ if (this.typeJsonTypeArray == null)
+ this.typeJsonTypeArray = new JsonTypeArray();
+ this.typeJsonTypeArray.addAll(types);
+ return this;
+ }
+
+ /**
+ * Used during parsing to convert the <property>type</property> property to the correct class type.
+ *
+ * <ul class='spaced-list'>
+ * <li>
+ * If parsing a JSON-array, converts to a {@link JsonTypeArray}.
+ * <li>
+ * If parsing a JSON-object, converts to a {@link JsonType}.
+ * </ul>
+ *
+ * <p>
+ * Serialization method is a no-op.
+ */
+ public static class JsonTypeOrJsonTypeArraySwap extends PojoSwap<Object,Object> {
+
+ @Override /* PojoSwap */
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ return o;
+ }
+
+ @Override /* PojoSwap */
+ public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException {
+ ClassMeta<?> cm = (
+ o instanceof Collection
+ ? session.getClassMeta(JsonTypeArray.class)
+ : session.getClassMeta(JsonType.class)
+ );
+ return session.convertToType(o, cm);
+ }
+ }
+
+ /**
+ * Bean property getter: <property>definitions</property>.
+ *
+ * @return
+ * The value of the <property>definitions</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Map<String,Schema> getDefinitions() {
+ return definitions;
+ }
+
+ /**
+ * Bean property setter: <property>definitions</property>.
+ *
+ * @param definitions The new value for the <property>definitions</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setDefinitions(Map<String,Schema> definitions) {
+ this.definitions = definitions;
+ if (definitions != null)
+ setMasterOn(definitions.values());
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>definitions</property>.
+ *
+ * @param name The key in the definitions map entry.
+ * @param definition The value in the definitions map entry.
+ * @return This object (for method chaining).
+ */
+ public Schema addDefinition(String name, Schema definition) {
+ if (this.definitions == null)
+ this.definitions = new LinkedHashMap<String,Schema>();
+ this.definitions.put(name, definition);
+ setMasterOn(definition);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>properties</property>.
+ *
+ * @return The value of the <property>properties</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Map<String,Schema> getProperties() {
+ return properties;
+ }
+
+ /**
+ * Returns the property with the specified name.
+ *
+ * <p>
+ * This is equivalent to calling <property>getProperty(name, <jk>false</jk>)</property>.
+ *
+ * @param name The property name.
+ * @return The property with the specified name, or <jk>null</jk> if no property is specified.
+ */
+ public Schema getProperty(String name) {
+ return getProperty(name, false);
+ }
+
+ /**
+ * Returns the property with the specified name.
+ *
+ * <p>
+ * If <property>resolve</property> is <jk>true</jk>, the property object will automatically be resolved by calling
+ * {@link #resolve()}.
+ * Therefore, <property>getProperty(name, <jk>true</jk>)</property> is equivalent to calling
+ * <property>getProperty(name).resolve()</property>, except it's safe from a potential
+ * <property>NullPointerException</property>.
+ *
+ * @param name The property name.
+ * @param resolve If <jk>true</jk>, calls {@link #resolve()} on object before returning.
+ * @return The property with the specified name, or <jk>null</jk> if no property is specified.
+ */
+ public Schema getProperty(String name, boolean resolve) {
+ if (properties == null)
+ return null;
+ Schema s = properties.get(name);
+ if (s == null)
+ return null;
+ if (resolve)
+ s = s.resolve();
+ return s;
+ }
+
+ /**
+ * Bean property setter: <property>properties</property>.
+ *
+ * @param properties The new value for the <property>properties</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setProperties(Map<String,Schema> properties) {
+ this.properties = properties;
+ if (properties != null)
+ for (Map.Entry<String,Schema> e : properties.entrySet()) {
+ Schema value = e.getValue();
+ setMasterOn(value);
+ value.setName(e.getKey());
+ }
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>properties</property>.
+ *
+ * <p>
+ * Properties must have their <property>name</property> property set on them when using this method.
+ *
+ * @param properties The list of items to append to the <property>properties</property> property on this bean.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If property is found without a set <property>name</property> property.
+ */
+ public Schema addProperties(Schema...properties) {
+ if (this.properties == null)
+ this.properties = new LinkedHashMap<String,Schema>();
+ for (Schema p : properties) {
+ if (p.getName() == null)
+ throw new BeanRuntimeException(Schema.class,
+ "Invalid property passed to Schema.addProperties(). Property name was null.");
+ setMasterOn(p);
+ this.properties.put(p.getName(), p);
+ }
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>patternProperties</property>.
+ *
+ * @return
+ * The value of the <property>patternProperties</property> property on this bean, or <jk>null</jk> if it is
+ * not set.
+ */
+ public Map<String,Schema> getPatternProperties() {
+ return patternProperties;
+ }
+
+ /**
+ * Bean property setter: <property>patternProperties</property>.
+ *
+ * @param patternProperties The new value for the <property>patternProperties</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setPatternProperties(Map<String,Schema> patternProperties) {
+ this.patternProperties = patternProperties;
+ if (patternProperties != null)
+ for (Map.Entry<String,Schema> e : patternProperties.entrySet()) {
+ Schema s = e.getValue();
+ setMasterOn(s);
+ s.setName(e.getKey());
+ }
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>patternProperties</property>.
+ *
+ * <p>
+ * Properties must have their <property>name</property> property set to the pattern string when using this method.
+ *
+ * @param properties The list of items to append to the <property>patternProperties</property> property on this bean.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If property is found without a set <property>name</property> property.
+ */
+ public Schema addPatternProperties(SchemaProperty...properties) {
+ if (this.patternProperties == null)
+ this.patternProperties = new LinkedHashMap<String,Schema>();
+ for (Schema p : properties) {
+ if (p.getName() == null)
+ throw new BeanRuntimeException(Schema.class,
+ "Invalid property passed to Schema.addProperties(). Property name was null.");
+ setMasterOn(p);
+ this.patternProperties.put(p.getName(), p);
+ }
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>dependencies</property>.
+ *
+ * @return
+ * The value of the <property>dependencies</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Map<String,Schema> getDependencies() {
+ return dependencies;
+ }
+
+ /**
+ * Bean property setter: <property>dependencies</property>.
+ *
+ * @param dependencies The new value for the <property>dependencies</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setDependencies(Map<String,Schema> dependencies) {
+ this.dependencies = dependencies;
+ if (dependencies != null)
+ setMasterOn(dependencies.values());
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>dependencies</property>.
+ *
+ * @param name The key of the entry in the dependencies map.
+ * @param dependency The value of the entry in the dependencies map.
+ * @return This object (for method chaining).
+ */
+ public Schema addDependency(String name, Schema dependency) {
+ if (this.dependencies == null)
+ this.dependencies = new LinkedHashMap<String,Schema>();
+ this.dependencies.put(name, dependency);
+ setMasterOn(dependency);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>items</property>.
+ *
+ * @return
+ * The value of the <property>items</property> property on this bean, or <jk>null</jk> if it is not set.
+ * Can be either a {@link Schema} or {@link SchemaArray} depending on what value was used to set it.
+ */
+ @BeanProperty(swap=SchemaOrSchemaArraySwap.class)
+ public Object getItems() {
+ if (itemsSchema != null)
+ return itemsSchema;
+ return itemsSchemaArray;
+ }
+
+ /**
+ * Bean property getter: <property>items</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>items</property> property when it is a {@link Schema} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link SchemaArray}.
+ */
+ @BeanIgnore
+ public Schema getItemsAsSchema() {
+ return itemsSchema;
+ }
+
+ /**
+ * Bean property getter: <property>items</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>items</property> property when it is a {@link SchemaArray} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Schema}.
+ */
+ @BeanIgnore
+ public SchemaArray getItemsAsSchemaArray() {
+ return itemsSchemaArray;
+ }
+
+ /**
+ * Used during parsing to convert the <property>items</property> property to the correct class type.
+ *
+ * <ul class='spaced-list'>
+ * <li>
+ * If parsing a JSON-array, converts to a {@link SchemaArray}.
+ * <li>
+ * If parsing a JSON-object, converts to a {@link Schema}.
+ * </ul>
+ *
+ * <p>
+ * Serialization method is a no-op.
+ */
+ public static class SchemaOrSchemaArraySwap extends PojoSwap<Object,Object> {
+
+ @Override /* PojoSwap */
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ return o;
+ }
+
+ @Override /* PojoSwap */
+ public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException {
+ ClassMeta<?> cm = (
+ o instanceof Collection
+ ? session.getClassMeta(SchemaArray.class)
+ : session.getClassMeta(Schema.class)
+ );
+ return session.convertToType(o, cm);
+ }
+ }
+
+ /**
+ * Bean property setter: <property>items</property>.
+ *
+ * @param
+ * items The new value for the <property>items</property> property on this bean.
+ * This object must be of type {@link Schema} or {@link SchemaArray}.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If invalid object type passed in.
+ */
+ public Schema setItems(Object items) {
+ this.itemsSchema = null;
+ this.itemsSchemaArray = null;
+ if (items != null) {
+ if (items instanceof Schema) {
+ this.itemsSchema = (Schema)items;
+ setMasterOn(this.itemsSchema);
+ } else if (items instanceof SchemaArray) {
+ this.itemsSchemaArray = (SchemaArray)items;
+ setMasterOn(this.itemsSchemaArray);
+ } else
+ throw new BeanRuntimeException(SchemaProperty.class,
+ "Invalid attribute type ''{0}'' passed in. Must be one of the following: Schema, SchemaArray",
+ items.getClass().getName());
+ }
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>items</property>.
+ *
+ * @param items The list of items to append to the <property>items</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addItems(Schema...items) {
+ if (this.itemsSchemaArray == null)
+ this.itemsSchemaArray = new SchemaArray();
+ this.itemsSchemaArray.addAll(items);
+ setMasterOn(items);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>multipleOf</property>.
+ *
+ * @return The value of the <property>multipleOf</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Number getMultipleOf() {
+ return multipleOf;
+ }
+
+ /**
+ * Bean property setter: <property>multipleOf</property>.
+ *
+ * @param multipleOf The new value for the <property>multipleOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMultipleOf(Number multipleOf) {
+ this.multipleOf = multipleOf;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>maximum</property>.
+ *
+ * @return The value of the <property>maximum</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Number getMaximum() {
+ return maximum;
+ }
+
+ /**
+ * Bean property setter: <property>maximum</property>.
+ *
+ * @param maximum The new value for the <property>maximum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMaximum(Number maximum) {
+ this.maximum = maximum;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>exclusiveMaximum</property>.
+ *
+ * @return
+ * The value of the <property>exclusiveMaximum</property> property on this bean, or <jk>null</jk> if it is
+ * not set.
+ */
+ public Boolean isExclusiveMaximum() {
+ return exclusiveMaximum;
+ }
+
+ /**
+ * Bean property setter: <property>exclusiveMaximum</property>.
+ *
+ * @param exclusiveMaximum The new value for the <property>exclusiveMaximum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setExclusiveMaximum(Boolean exclusiveMaximum) {
+ this.exclusiveMaximum = exclusiveMaximum;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>minimum</property>.
+ *
+ * @return The value of the <property>minimum</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Number getMinimum() {
+ return minimum;
+ }
+
+ /**
+ * Bean property setter: <property>minimum</property>.
+ *
+ * @param minimum The new value for the <property>minimum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMinimum(Number minimum) {
+ this.minimum = minimum;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>exclusiveMinimum</property>.
+ *
+ * @return
+ * The value of the <property>exclusiveMinimum</property> property on this bean, or <jk>null</jk> if it is
+ * not set.
+ */
+ public Boolean isExclusiveMinimum() {
+ return exclusiveMinimum;
+ }
+
+ /**
+ * Bean property setter: <property>exclusiveMinimum</property>.
+ *
+ * @param exclusiveMinimum The new value for the <property>exclusiveMinimum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setExclusiveMinimum(Boolean exclusiveMinimum) {
+ this.exclusiveMinimum = exclusiveMinimum;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>maxLength</property>.
+ *
+ * @return The value of the <property>maxLength</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMaxLength() {
+ return maxLength;
+ }
+
+ /**
+ * Bean property setter: <property>maxLength</property>.
+ *
+ * @param maxLength The new value for the <property>maxLength</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMaxLength(Integer maxLength) {
+ this.maxLength = maxLength;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>minLength</property>.
+ *
+ * @return The value of the <property>minLength</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMinLength() {
+ return minLength;
+ }
+
+ /**
+ * Bean property setter: <property>minLength</property>.
+ *
+ * @param minLength The new value for the <property>minLength</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMinLength(Integer minLength) {
+ this.minLength = minLength;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>pattern</property>.
+ *
+ * @return The value of the <property>pattern</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /**
+ * Bean property setter: <property>pattern</property>.
+ *
+ * @param pattern The new value for the <property>pattern</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setPattern(String pattern) {
+ this.pattern = pattern;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>additionalItems</property>.
+ *
+ * @return
+ * The value of the <property>additionalItems</property> property on this bean, or <jk>null</jk> if it is
+ * not set.
+ * Can be either a {@link Boolean} or {@link SchemaArray} depending on what value was used to set it.
+ */
+ @BeanProperty(swap=BooleanOrSchemaArraySwap.class)
+ public Object getAdditionalItems() {
+ if (additionalItemsBoolean != null)
+ return additionalItemsBoolean;
+ return additionalItemsSchemaArray;
+ }
+
+ /**
+ * Bean property getter: <property>additionalItems</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>additionalItems</property> property when it is a {@link Boolean}
+ * value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link SchemaArray}.
+ */
+ @BeanIgnore
+ public Boolean getAdditionalItemsAsBoolean() {
+ return additionalItemsBoolean;
+ }
+
+ /**
+ * Bean property getter: <property>additionalItems</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>additionalItems</property> property when it is a
+ * {@link SchemaArray} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}.
+ */
+ @BeanIgnore
+ public List<Schema> getAdditionalItemsAsSchemaArray() {
+ return additionalItemsSchemaArray;
+ }
+
+ /**
+ * Bean property setter: <property>additionalItems</property>.
+ *
+ * @param additionalItems
+ * The new value for the <property>additionalItems</property> property on this bean.
+ * This object must be of type {@link Boolean} or {@link SchemaArray}.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If invalid object type passed in.
+ */
+ public Schema setAdditionalItems(Object additionalItems) {
+ this.additionalItemsBoolean = null;
+ this.additionalItemsSchemaArray = null;
+ if (additionalItems != null) {
+ if (additionalItems instanceof Boolean)
+ this.additionalItemsBoolean = (Boolean)additionalItems;
+ else if (additionalItems instanceof SchemaArray) {
+ this.additionalItemsSchemaArray = (SchemaArray)additionalItems;
+ setMasterOn(this.additionalItemsSchemaArray);
+ } else
+ throw new BeanRuntimeException(SchemaProperty.class,
+ "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, SchemaArray",
+ additionalItems.getClass().getName());
+ }
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>additionalItems</property>.
+ *
+ * @param additionalItems
+ * The list of items to append to the <property>additionalItems</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addAdditionalItems(Schema...additionalItems) {
+ if (this.additionalItemsSchemaArray == null)
+ this.additionalItemsSchemaArray = new SchemaArray();
+ this.additionalItemsSchemaArray.addAll(additionalItems);
+ setMasterOn(additionalItems);
+ return this;
+ }
+
+ /**
+ * Used during parsing to convert the <property>additionalItems</property> property to the correct class type.
+ *
+ * <ul class='spaced-list'>
+ * <li>
+ * If parsing a JSON-array, converts to a {@link SchemaArray}.
+ * <li>
+ * If parsing a JSON-boolean, converts to a {@link Boolean}.
+ * </ul>
+ *
+ * <p>
+ * Serialization method is a no-op.
+ */
+ public static class BooleanOrSchemaArraySwap extends PojoSwap<Object,Object> {
+
+ @Override /* PojoSwap */
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ return o;
+ }
+
+ @Override /* PojoSwap */
+ public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException {
+ ClassMeta<?> cm = (
+ o instanceof Collection
+ ? session.getClassMeta(SchemaArray.class)
+ : session.getClassMeta(Boolean.class)
+ );
+ return session.convertToType(o, cm);
+ }
+ }
+
+ /**
+ * Bean property getter: <property>maxItems</property>.
+ *
+ * @return The value of the <property>maxItems</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMaxItems() {
+ return maxItems;
+ }
+
+ /**
+ * Bean property setter: <property>maxItems</property>.
+ *
+ * @param maxItems The new value for the <property>maxItems</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMaxItems(Integer maxItems) {
+ this.maxItems = maxItems;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>minItems</property>.
+ *
+ * @return The value of the <property>minItems</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMinItems() {
+ return minItems;
+ }
+
+ /**
+ * Bean property setter: <property>minItems</property>.
+ *
+ * @param minItems The new value for the <property>minItems</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMinItems(Integer minItems) {
+ this.minItems = minItems;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>uniqueItems</property>.
+ *
+ * @return
+ * The value of the <property>uniqueItems</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Boolean getUniqueItems() {
+ return uniqueItems;
+ }
+
+ /**
+ * Bean property setter: <property>uniqueItems</property>.
+ *
+ * @param uniqueItems The new value for the <property>uniqueItems</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setUniqueItems(Boolean uniqueItems) {
+ this.uniqueItems = uniqueItems;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>maxProperties</property>.
+ *
+ * @return
+ * The value of the <property>maxProperties</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMaxProperties() {
+ return maxProperties;
+ }
+
+ /**
+ * Bean property setter: <property>maxProperties</property>.
+ *
+ * @param maxProperties The new value for the <property>maxProperties</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMaxProperties(Integer maxProperties) {
+ this.maxProperties = maxProperties;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>minProperties</property>.
+ *
+ * @return
+ * The value of the <property>minProperties</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Integer getMinProperties() {
+ return minProperties;
+ }
+
+ /**
+ * Bean property setter: <property>minProperties</property>.
+ *
+ * @param minProperties The new value for the <property>minProperties</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setMinProperties(Integer minProperties) {
+ this.minProperties = minProperties;
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>required</property>.
+ *
+ * @return The value of the <property>required</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<String> getRequired() {
+ return required;
+ }
+
+ /**
+ * Bean property setter: <property>required</property>.
+ *
+ * @param required The new value for the <property>required</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setRequired(List<String> required) {
+ this.required = required;
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>required</property>.
+ *
+ * @param required The list of items to append to the <property>required</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addRequired(List<String> required) {
+ if (this.required == null)
+ this.required = new LinkedList<String>();
+ for (String r : required)
+ this.required.add(r);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>required</property>.
+ *
+ * @param required The list of items to append to the <property>required</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addRequired(String...required) {
+ if (this.required == null)
+ this.required = new LinkedList<String>();
+ for (String r : required)
+ this.required.add(r);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>required</property>.
+ *
+ * @param properties The list of items to append to the <property>required</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addRequired(SchemaProperty...properties) {
+ if (this.required == null)
+ this.required = new LinkedList<String>();
+ for (SchemaProperty p : properties)
+ this.required.add(p.getName());
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>additionalProperties</property>.
+ *
+ * @return
+ * The value of the <property>additionalProperties</property> property on this bean, or <jk>null</jk> if it
+ * is not set.
+ * Can be either a {@link Boolean} or {@link SchemaArray} depending on what value was used to set it.
+ */
+ @BeanProperty(swap=BooleanOrSchemaSwap.class)
+ public Object getAdditionalProperties() {
+ if (additionalPropertiesBoolean != null)
+ return additionalItemsBoolean;
+ return additionalPropertiesSchema;
+ }
+
+ /**
+ * Bean property getter: <property>additionalProperties</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>additionalProperties</property> property when it is a
+ * {@link Boolean} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Schema}.
+ */
+ @BeanIgnore
+ public Boolean getAdditionalPropertiesAsBoolean() {
+ return additionalPropertiesBoolean;
+ }
+
+ /**
+ * Bean property getter: <property>additionalProperties</property>.
+ *
+ * <p>
+ * Convenience method for returning the <property>additionalProperties</property> property when it is a
+ * {@link Schema} value.
+ *
+ * @return The currently set value, or <jk>null</jk> if the property is not set, or is set as a {@link Boolean}.
+ */
+ @BeanIgnore
+ public Schema getAdditionalPropertiesAsSchema() {
+ return additionalPropertiesSchema;
+ }
+
+ /**
+ * Bean property setter: <property>additionalProperties</property>.
+ *
+ * @param additionalProperties
+ * The new value for the <property>additionalProperties</property> property on this bean.
+ * This object must be of type {@link Boolean} or {@link Schema}.
+ * @return This object (for method chaining).
+ * @throws BeanRuntimeException If invalid object type passed in.
+ */
+ @BeanProperty(beanDictionary={Schema.class})
+ public Schema setAdditionalProperties(Object additionalProperties) {
+ this.additionalPropertiesBoolean = null;
+ this.additionalPropertiesSchema = null;
+ if (additionalProperties != null) {
+ if (additionalProperties instanceof Boolean)
+ this.additionalPropertiesBoolean = (Boolean)additionalProperties;
+ else if (additionalProperties instanceof Schema) {
+ this.additionalPropertiesSchema = (Schema)additionalProperties;
+ setMasterOn(this.additionalPropertiesSchema);
+ } else
+ throw new BeanRuntimeException(SchemaProperty.class,
+ "Invalid attribute type ''{0}'' passed in. Must be one of the following: Boolean, Schema",
+ additionalProperties.getClass().getName());
+ }
+ return this;
+ }
+
+ /**
+ * Used during parsing to convert the <property>additionalProperties</property> property to the correct class type.
+ *
+ * <ul class='spaced-list'>
+ * <li>
+ * If parsing a JSON-object, converts to a {@link Schema}.
+ * <li>
+ * If parsing a JSON-boolean, converts to a {@link Boolean}.
+ * </ul>
+ *
+ * <p>
+ * Serialization method is a no-op.
+ */
+ public static class BooleanOrSchemaSwap extends PojoSwap<Object,Object> {
+
+ @Override /* PojoSwap */
+ public Object swap(BeanSession session, Object o) throws SerializeException {
+ return o;
+ }
+
+ @Override /* PojoSwap */
+ public Object unswap(BeanSession session, Object o, ClassMeta<?> hint) throws ParseException {
+ ClassMeta<?> cm = (
+ o instanceof Boolean
+ ? session.getClassMeta(Boolean.class)
+ : session.getClassMeta(Schema.class)
+ );
+ return session.convertToType(o, cm);
+ }
+ }
+
+ /**
+ * Bean property getter: <property>enum</property>.
+ *
+ * @return The value of the <property>enum</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<String> getEnum() {
+ return _enum;
+ }
+
+ /**
+ * Bean property setter: <property>enum</property>.
+ *
+ * @param _enum The new value for the <property>enum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setEnum(List<String> _enum) {
+ this._enum = _enum;
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>enum</property>.
+ *
+ * @param _enum The list of items to append to the <property>enum</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addEnum(String..._enum) {
+ if (this._enum == null)
+ this._enum = new LinkedList<String>();
+ for (String e : _enum)
+ this._enum.add(e);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>allOf</property>.
+ *
+ * @return The value of the <property>allOf</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<Schema> getAllOf() {
+ return allOf;
+ }
+
+ /**
+ * Bean property setter: <property>allOf</property>.
+ *
+ * @param allOf The new value for the <property>allOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setAllOf(List<Schema> allOf) {
+ this.allOf = allOf;
+ setMasterOn(allOf);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>allOf</property>.
+ *
+ * @param allOf The list of items to append to the <property>allOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addAllOf(Schema...allOf) {
+ if (this.allOf == null)
+ this.allOf = new LinkedList<Schema>();
+ setMasterOn(allOf);
+ for (Schema s : allOf)
+ this.allOf.add(s);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>anyOf</property>.
+ *
+ * @return The value of the <property>anyOf</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<Schema> getAnyOf() {
+ return anyOf;
+ }
+
+ /**
+ * Bean property setter: <property>anyOf</property>.
+ *
+ * @param anyOf The new value of the <property>anyOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setAnyOf(List<Schema> anyOf) {
+ this.anyOf = anyOf;
+ setMasterOn(anyOf);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>anyOf</property>.
+ *
+ * @param anyOf The list of items to append to the <property>anyOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addAnyOf(Schema...anyOf) {
+ if (this.anyOf == null)
+ this.anyOf = new LinkedList<Schema>();
+ setMasterOn(anyOf);
+ for (Schema s : anyOf)
+ this.anyOf.add(s);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>oneOf</property>.
+ *
+ * @return The value of the <property>oneOf</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public List<Schema> getOneOf() {
+ return oneOf;
+ }
+
+ /**
+ * Bean property setter: <property>oneOf</property>.
+ *
+ * @param oneOf The new value for the <property>oneOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setOneOf(List<Schema> oneOf) {
+ this.oneOf = oneOf;
+ setMasterOn(oneOf);
+ return this;
+ }
+
+ /**
+ * Bean property appender: <property>oneOf</property>.
+ *
+ * @param oneOf The list of items to append to the <property>oneOf</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema addOneOf(Schema...oneOf) {
+ if (this.oneOf == null)
+ this.oneOf = new LinkedList<Schema>();
+ setMasterOn(oneOf);
+ for (Schema s : oneOf)
+ this.oneOf.add(s);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>not</property>.
+ *
+ * @return The value of the <property>not</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ public Schema getNot() {
+ return not;
+ }
+
+ /**
+ * Bean property setter: <property>not</property>.
+ *
+ * @param not The new value for the <property>not</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ public Schema setNot(Schema not) {
+ this.not = not;
+ setMasterOn(not);
+ return this;
+ }
+
+ /**
+ * Bean property getter: <property>$ref</property>.
+ *
+ * @return The value of the <property>$ref</property> property on this bean, or <jk>null</jk> if it is not set.
+ */
+ @BeanProperty("$ref")
+ public URI getRef() {
+ return ref;
+ }
+
+ /**
+ * Bean property setter: <property>$ref</property>.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param ref The new value for the <property>$ref</property> property on this bean.
+ * @return This object (for method chaining).
+ */
+ @BeanProperty("$ref")
+ public Schema setRef(Object ref) {
+ this.ref = toURI(ref);
+ return this;
+ }
+
+ private void setMasterOn(Schema s) {
+ if (s != null)
+ s.setMaster(this);
+ }
+
+ private void setMasterOn(Schema[] ss) {
+ if (ss != null)
+ for (Schema s : ss)
+ setMasterOn(s);
+ }
+
+ private void setMasterOn(Collection<Schema> ss) {
+ if (ss != null)
+ for (Schema s : ss)
+ setMasterOn(s);
+ }
+
+ private void setMasterOn(SchemaArray ss) {
+ if (ss != null)
+ for (Schema s : ss)
+ setMasterOn(s);
+ }
+
+ /**
+ * Sets the master schema for this schema and all child schema objects.
+ *
+ * <p>
+ * All child elements in a schema should point to a single "master" schema in order to locate registered SchemaMap
+ * objects for resolving external schemas.
+ *
+ * @param master The master schema to associate on this and all children. Can be <jk>null</jk>.
+ */
+ protected void setMaster(Schema master) {
+ this.master = master;
+ if (definitions != null)
+ for (Schema s : definitions.values())
+ s.setMaster(master);
+ if (properties != null)
+ for (Schema s : properties.values())
+ s.setMaster(master);
+ if (patternProperties != null)
+ for (Schema s : patternProperties.values())
+ s.setMaster(master);
+ if (dependencies != null)
+ for (Schema s : dependencies.values())
+ s.setMaster(master);
+ if (itemsSchema != null)
+ itemsSchema.setMaster(master);
+ if (itemsSchemaArray != null)
+ for (Schema s : itemsSchemaArray)
+ s.setMaster(master);
+ if (additionalItemsSchemaArray != null)
+ for (Schema s : additionalItemsSchemaArray)
+ s.setMaster(master);
+ if (additionalPropertiesSchema != null)
+ additionalPropertiesSchema.setMaster(master);
+ if (allOf != null)
+ for (Schema s : allOf)
+ s.setMaster(master);
+ if (anyOf != null)
+ for (Schema s : anyOf)
+ s.setMaster(master);
+ if (oneOf != null)
+ for (Schema s : oneOf)
+ s.setMaster(master);
+ if (not != null)
+ not.setMaster(master);
+ }
+ /**
+ * If this schema is a reference to another schema (i.e. has its <property>$ref</property> property set), this
+ * method will retrieve the referenced schema from the schema map registered with this schema.
+ *
+ * <p>
+ * If this schema is not a reference, or no schema map is registered with this schema, this method is a no-op and
+ * simply returns this object.
+ *
+ * @return The referenced schema, or <jk>null</jk>.
+ */
+ public Schema resolve() {
+ if (ref == null || master.schemaMap == null)
+ return this;
+ return master.schemaMap.get(ref);
+ }
+
+ /**
+ * Associates a schema map with this schema for resolving other schemas identified through <property>$ref</property>
+ * properties.
+ *
+ * @param schemaMap The schema map to associate with this schema. Can be <jk>null</jk>.
+ * @return This object (for method chaining).
+ */
+ public Schema setSchemaMap(SchemaMap schemaMap) {
+ this.schemaMap = schemaMap;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
new file mode 100644
index 0000000..dc48116
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
@@ -0,0 +1,64 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+import java.util.*;
+
+/**
+ * Represents a list of {@link Schema} objects.
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+public class SchemaArray extends LinkedList<Schema> {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Default constructor.
+ */
+ public SchemaArray() {}
+
+ /**
+ * Constructor with predefined types to add to this list.
+ *
+ * @param schemas The list of schemas in this array.
+ */
+ public SchemaArray(Schema...schemas) {
+ addAll(schemas);
+ }
+
+ /**
+ * Convenience method for adding one or more {@link Schema} objects to this array.
+ *
+ * @param schemas The {@link Schema} objects to add to this array.
+ * @return This object (for method chaining).
+ */
+ public SchemaArray addAll(Schema...schemas) {
+ for (Schema s : schemas)
+ add(s);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
new file mode 100644
index 0000000..46e72ff
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
@@ -0,0 +1,153 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+import static org.apache.juneau.internal.StringUtils.*;
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+
+/**
+ * A container for retrieving JSON {@link Schema} objects by URI.
+ *
+ * <p>
+ * Subclasses must implement one of the following methods to load schemas from external sources:
+ * <ul class='spaced-list'>
+ * <li>
+ * {@link #getReader(URI)} - If schemas should be loaded from readers and automatically parsed.
+ * <li>
+ * {@link #load(URI)} - If you want control over construction of {@link Schema} objects.
+ * </ul>
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+public abstract class SchemaMap extends ConcurrentHashMap<URI,Schema> {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Return the {@link Schema} object at the specified URI.
+ *
+ * <p>
+ * If this schema object has not been loaded yet, calls {@link #load(URI)}.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param uri The URI of the schema to retrieve.
+ * @return The Schema, or <jk>null</jk> if schema was not located and could not be loaded.
+ */
+ @Override /* Map */
+ public Schema get(Object uri) {
+ URI u = toURI(uri);
+ Schema s = super.get(u);
+ if (s != null)
+ return s;
+ synchronized(this) {
+ s = load(u);
+ if (s != null) {
+ // Note: Can't use add(Schema...) since the ID property may not be set.
+ s.setSchemaMap(this);
+ put(u, s);
+ }
+ return s;
+ }
+ }
+
+ /**
+ * Convenience method for pre-populating this map with the specified schemas.
+ *
+ * <p>
+ * The schemas passed in through this method MUST have their ID properties set.
+ *
+ * @param schemas The set of schemas to add to this map.
+ * @return This object (for method chaining).
+ * @throws RuntimeException If one or more schema objects did not have their ID property set.
+ */
+ public SchemaMap add(Schema...schemas) {
+ for (Schema schema : schemas) {
+ if (schema.getId() == null)
+ throw new RuntimeException("Schema with no ID passed to SchemaMap.add(Schema...)");
+ put(schema.getId(), schema);
+ schema.setSchemaMap(this);
+ }
+ return this;
+ }
+
+ /**
+ * Subclasses must implement either this method or {@link #getReader(URI)} to load the schema with the specified URI.
+ *
+ * <p>
+ * It's up to the implementer to decide where these come from.
+ *
+ * <p>
+ * The default implementation calls {@link #getReader(URI)} and parses the schema document.
+ * If {@link #getReader(URI)} returns <jk>null</jk>, this method returns <jk>null</jk> indicating this is an
+ * unreachable document.
+ *
+ * @param uri The URI to load the schema from.
+ * @return The parsed schema.
+ */
+ public Schema load(URI uri) {
+ Reader r = getReader(uri);
+ if (r == null)
+ return null;
+ try {
+ return JsonParser.DEFAULT.parse(r, Schema.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ r.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * Subclasses must implement either this method or {@link #load(URI)} to load the schema with the specified URI.
+ *
+ * <p>
+ * It's up to the implementer to decide where these come from.
+ *
+ * <p>
+ * The default implementation returns <jk>null</jk>.
+ *
+ * @param uri The URI to connect to and retrieve the contents.
+ * @return The reader from reading the specified URI.
+ */
+ public Reader getReader(URI uri) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
new file mode 100644
index 0000000..c0f1dc7
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+/**
+ * Represents a JSON property in the JSON-Schema core specification.
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+public class SchemaProperty extends Schema {
+
+ /**
+ * Default constructor.
+ */
+ public SchemaProperty() {}
+
+ /**
+ * Convenience constructor.
+ *
+ * @param name The name of this property.
+ */
+ public SchemaProperty(String name) {
+ setName(name);
+ }
+
+ /**
+ * Convenience constructor.
+ *
+ * @param name The name of this property.
+ * @param type The JSON type of this property.
+ */
+ public SchemaProperty(String name, JsonType type) {
+ setName(name);
+ setType(type);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
new file mode 100644
index 0000000..ced1eaf
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
@@ -0,0 +1,59 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+/**
+ * Convenience class for representing a property that's an array of simple types.
+ *
+ * <p>
+ * An instance of this object is equivalent to calling...
+ *
+ * <p class='bcode'>
+ * SchemaProperty p = <jk>new</jk> SchemaProperty(name)
+ * .setType(JsonType.<jsf>ARRAY</jsf>)
+ * .setItems(
+ * <jk>new</jk> Schema().setType(elementType)
+ * );
+ * </p>
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+public class SchemaPropertySimpleArray extends SchemaProperty {
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the schema property.
+ * @param elementType The JSON type of the elements in the array.
+ */
+ public SchemaPropertySimpleArray(String name, JsonType elementType) {
+ setName(name);
+ setType(JsonType.ARRAY);
+ setItems(
+ new Schema().setType(elementType)
+ );
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
new file mode 100644
index 0000000..080cb52
--- /dev/null
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
@@ -0,0 +1,61 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
+// * to you 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.apache.juneau.dto.jsonschema;
+
+import java.net.*;
+
+import org.apache.juneau.*;
+
+/**
+ * Convenience class for representing a schema reference such as <js>"{'$ref':'/url/to/ref'}"</js>.
+ *
+ * <p>
+ * An instance of this object is equivalent to calling...
+ *
+ * <p class='bcode'>
+ * Schema s = <jk>new</jk> Schema().setRef(uri);
+ * </p>
+ *
+ * <h6 class='topic'>Additional Information</h6>
+ * <ul class='doctree'>
+ * <li class='link'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs'>Juneau Data Transfer Objects
+ * (org.apache.juneau.dto)</a>
+ * <ul>
+ * <li class='sublink'>
+ * <a class='doclink' href='../../../../../overview-summary.html#DTOs.JsonSchema'>JSON-Schema</a>
+ * </ul>
+ * </li>
+ * <li class='jp'>
+ * <a class='doclink' href='package-summary.html#TOC'>org.apache.juneau.dto.jsonschema</a>
+ * </li>
+ * </ul>
+ */
+public class SchemaRef extends Schema {
+
+ /**
+ * Constructor.
+ *
+ * <p>
+ * The value can be of any of the following types: {@link URI}, {@link URL}, {@link String}.
+ * Strings must be valid URIs.
+ *
+ * <p>
+ * URIs defined by {@link UriResolver} can be used for values.
+ *
+ * @param uri The URI of the target reference. Can be <jk>null</jk>.
+ */
+ public SchemaRef(Object uri) {
+ this.setRef(uri);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png
new file mode 100644
index 0000000..3848b4f
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png
new file mode 100644
index 0000000..6c8ddd1
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png
new file mode 100644
index 0000000..5250d3b
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png
new file mode 100644
index 0000000..478de82
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png
new file mode 100644
index 0000000..86576e7
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png
new file mode 100644
index 0000000..0195c5a
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png differ
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/75b0d8ee/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png
new file mode 100644
index 0000000..129f9df
Binary files /dev/null and b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png differ