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 2016/08/09 19:54:10 UTC

[37/51] [partial] incubator-juneau git commit: Rename project directories.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
new file mode 100644
index 0000000..d63a245
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/Schema.java
@@ -0,0 +1,1401 @@
+/***************************************************************************************************************************
+ * 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.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.*;
+import org.apache.juneau.xml.annotation.*;
+
+/**
+ * Represents a top-level schema object bean in the JSON-Schema core specification.
+ * <p>
+ * 	Refer to {@link org.apache.juneau.dto.jsonschema} for usage information.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+@Xml(name="schema")
+@SuppressWarnings("hiding")
+@Bean(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>.
+	 *
+	 * @param id The new value for the <property>id</property> property on this bean.
+	 * @return This object (for method chaining).
+	 */
+	public Schema setId(URI id) {
+		this.id = id;
+		return this;
+	}
+
+	/**
+	 * Bean property setter:  <property>id</property>.
+	 *
+	 * @param id The new value for the <property>id</property> property on this bean.
+	 * 	The parameter must be a valid URI.  It can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Schema setId(String id) {
+		return setId(id == null ? null : URI.create(id));
+	}
+
+	/**
+	 * 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(name="$schema")
+	public URI getSchemaVersionUri() {
+		return schemaVersion;
+	}
+
+	/**
+	 * Bean property setter:  <property>$schema</property>.
+	 *
+	 * @param schemaVersion The new value for the <property>schemaVersion</property> property on this bean.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty(name="$schema")
+	public Schema setSchemaVersionUri(URI schemaVersion) {
+		this.schemaVersion = schemaVersion;
+		return this;
+	}
+
+	/**
+	 * Bean property setter:  <property>schemaVersion</property>.
+	 *
+	 * @param schemaVersion The new value for the <property>schemaVersion</property> property on this bean.
+	 * 	The parameter must be a valid URI.  It can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Schema setSchemaVersionUri(String schemaVersion) {
+		return setSchemaVersionUri(schemaVersion == null ? null : URI.create(schemaVersion));
+	}
+
+	/**
+	 * 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(transform=JsonTypeOrJsonTypeArrayTransform.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>
+	 * Serialization method is a no-op.
+	 */
+	public static class JsonTypeOrJsonTypeArrayTransform extends PojoTransform<Object,Object> {
+
+		@Override /* PojoTransform */
+		public Object transform(Object o) throws SerializeException {
+			return o;
+		}
+
+		@Override /* PojoTransform */
+		public Object normalize(Object o, ClassMeta<?> hint) throws ParseException {
+			BeanContext bc = getBeanContext();
+			ClassMeta<?> cm = (o instanceof Collection ? bc.getClassMeta(JsonTypeArray.class) : bc.getClassMeta(JsonType.class));
+			return bc.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.
+	 * 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.
+	 * 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(transform=SchemaOrSchemaArrayTransform.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>
+	 * Serialization method is a no-op.
+	 */
+	public static class SchemaOrSchemaArrayTransform extends PojoTransform<Object,Object> {
+
+		@Override /* PojoTransform */
+		public Object transform(Object o) throws SerializeException {
+			return o;
+		}
+
+		@Override /* PojoTransform */
+		public Object normalize(Object o, ClassMeta<?> hint) throws ParseException {
+			BeanContext bc = getBeanContext();
+			ClassMeta<?> cm = (o instanceof Collection ? bc.getClassMeta(SchemaArray.class) : bc.getClassMeta(Schema.class));
+			return bc.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(transform=BooleanOrSchemaArrayTransform.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>
+	 * Serialization method is a no-op.
+	 */
+	public static class BooleanOrSchemaArrayTransform extends PojoTransform<Object,Object> {
+
+		@Override /* PojoTransform */
+		public Object transform(Object o) throws SerializeException {
+			return o;
+		}
+
+		@Override /* PojoTransform */
+		public Object normalize(Object o, ClassMeta<?> hint) throws ParseException {
+			BeanContext bc = getBeanContext();
+			ClassMeta<?> cm = (o instanceof Collection ? bc.getClassMeta(SchemaArray.class) : bc.getClassMeta(Boolean.class));
+			return bc.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(transform=BooleanOrSchemaTransform.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.
+	 */
+	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>
+	 * Serialization method is a no-op.
+	 */
+	public static class BooleanOrSchemaTransform extends PojoTransform<Object,Object> {
+
+		@Override /* PojoTransform */
+		public Object transform(Object o) throws SerializeException {
+			return o;
+		}
+
+		@Override /* PojoTransform */
+		public Object normalize(Object o, ClassMeta<?> hint) throws ParseException {
+			BeanContext bc = getBeanContext();
+			ClassMeta<?> cm = (o instanceof Boolean ? bc.getClassMeta(Boolean.class) : bc.getClassMeta(Schema.class));
+			return bc.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(name="$ref")
+	public URI getRef() {
+		return ref;
+	}
+
+	/**
+	 * Bean property setter:  <property>$ref</property>.
+	 *
+	 * @param ref The new value for the <property>$ref</property> property on this bean.
+	 * @return This object (for method chaining).
+	 */
+	@BeanProperty(name="$ref")
+	public Schema setRef(URI ref) {
+		this.ref = 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);
+	}
+
+
+	/**
+	 * Bean property setter:  <property>$ref</property>.
+	 *
+	 * @param ref The new value for the <property>$ref</property> property on this bean.
+	 * 	The parameter must be a valid URI.  It can be <jk>null</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public Schema setRef(String ref) {
+		return setRef(ref == null ? null : URI.create(ref));
+	}
+
+	/**
+	 * 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.
+	 * 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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
new file mode 100644
index 0000000..45c4962
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaArray.java
@@ -0,0 +1,54 @@
+/***************************************************************************************************************************
+ * 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.
+ * <p>
+ * 	Refer to {@link org.apache.juneau.dto.jsonschema} for usage information.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
new file mode 100644
index 0000000..5cc2f5f
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaMap.java
@@ -0,0 +1,123 @@
+/***************************************************************************************************************************
+ * 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.io.*;
+import java.net.*;
+import java.util.concurrent.*;
+
+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>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public abstract class SchemaMap extends ConcurrentHashMap<URI,Schema> {
+
+	private static final long serialVersionUID = 1L;
+
+	@Override /* Map */
+	public Schema get(Object uri) {
+		if (uri == null)
+			return null;
+		return get(URI.create(uri.toString()));
+	}
+
+	/**
+	 * Return the {@link Schema} object at the specified URI.
+	 * If this schema object has not been loaded yet, calls {@link #load(URI)}.
+	 *
+	 * @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.
+	 */
+	public Schema get(URI uri) {
+		Schema s = super.get(uri);
+		if (s != null)
+			return s;
+		synchronized(this) {
+			s = load(uri);
+			if (s != null) {
+				// Note:  Can't use add(Schema...) since the ID property may not be set.
+				s.setSchemaMap(this);
+				put(uri, s);
+			}
+			return s;
+		}
+	}
+
+	/**
+	 * Convenience method for prepopulating 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.
+	 * 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.
+	 * 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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
new file mode 100644
index 0000000..bef3caf
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaProperty.java
@@ -0,0 +1,48 @@
+/***************************************************************************************************************************
+ * 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.
+ * <p>
+ * 	Refer to {@link org.apache.juneau.dto.jsonschema} for usage information.
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
new file mode 100644
index 0000000..e71cd66
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaPropertySimpleArray.java
@@ -0,0 +1,45 @@
+/***************************************************************************************************************************
+ * 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>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
new file mode 100644
index 0000000..3bd65d5
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/SchemaRef.java
@@ -0,0 +1,38 @@
+/***************************************************************************************************************************
+ * 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.*;
+
+/**
+ * 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>
+ *
+ * @author James Bognar (james.bognar@salesforce.com)
+ */
+public class SchemaRef extends Schema {
+
+	/**
+	 * Constructor.
+	 *
+	 * @param uri The URI of the target reference.  Can be <jk>null</jk>.
+	 */
+	public SchemaRef(String uri) {
+		this.setRef(uri == null ? null : URI.create(uri));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Html.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Json.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Options.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Turtle.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_UrlEncoded.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_Xml.png b/juneau-core/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/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/e6bf97a8/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png b/juneau-core/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/src/main/java/org/apache/juneau/dto/jsonschema/doc-files/Example_XmlRdfAbbrev.png differ