juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [juneau] branch master updated: Improvements to Swagger support.
Date Sun, 25 Mar 2018 15:14:45 GMT
This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 19777c5  Improvements to Swagger support.
19777c5 is described below

commit 19777c5a4ad55e1a4cb3d615b258f9a41e88b387
Author: JamesBognar <jamesbognar@apache.org>
AuthorDate: Sun Mar 25 11:14:30 2018 -0400

    Improvements to Swagger support.
---
 .../java/org/apache/juneau/PropertyStoreTest.java  |   7 +-
 .../src/main/java/org/apache/juneau/ClassMeta.java |   9 +
 .../src/main/java/org/apache/juneau/ObjectMap.java |  47 ++
 .../org/apache/juneau/httppart/HttpPartType.java   |   5 +-
 .../java/org/apache/juneau/json/JsonParser.java    |  14 +-
 .../apache/juneau/examples/rest/RootResources.java |   2 +-
 .../examples/{ => rest}/petstore/ApiResponse.java  |   2 +-
 .../examples/{ => rest}/petstore/Category.java     |   2 +-
 .../juneau/examples/{ => rest}/petstore/Order.java |   2 +-
 .../examples/{ => rest}/petstore/OrderStatus.java  |   2 +-
 .../juneau/examples/{ => rest}/petstore/Pet.java   |   2 +-
 .../examples/{ => rest}/petstore/PetStatus.java    |   2 +-
 .../{ => rest}/petstore/PetStoreResource.java      |   2 +-
 .../juneau/examples/{ => rest}/petstore/Tag.java   |   2 +-
 .../juneau/examples/{ => rest}/petstore/User.java  |   2 +-
 .../examples/rest}/petstore/PetStoreResource.json  |   0
 .../org/apache/juneau/rest/BasicRestConfig.java    |   1 +
 .../apache/juneau/rest/BasicRestInfoProvider.java  | 501 +++++++++++++--------
 .../org/apache/juneau/rest/RestJavaMethod.java     |   2 +-
 .../org/apache/juneau/rest/RestParamDefaults.java  |   4 +-
 .../java/org/apache/juneau/rest/RestParamType.java |   2 +-
 .../java/org/apache/juneau/rest/RestRequest.java   |   9 +
 22 files changed, 423 insertions(+), 198 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
index 254d17e..c8e6c7d 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
@@ -1584,13 +1584,13 @@ public class PropertyStoreTest {
 			b.removeFrom("A.foo.ss", "[xxx]");
 			fail("Exception expected.");
 		} catch (ConfigException e) {
-			assertTrue(e.getMessage().startsWith("Cannot remove value '[xxx]' (String) from property 'foo.ss' (Set<String>).  Invalid input for JsonParser parser."));
+			assertTrue(e.getMessage().startsWith("Cannot remove value '[xxx]' (String) from property 'foo.ss' (Set<String>).  Invalid input for Simple parser."));
 		}
 		try {
 			b.removeFrom("A.foo.ls", "[xxx]");
 			fail("Exception expected.");
 		} catch (ConfigException e) {
-			assertTrue(e.getMessage().startsWith("Cannot remove value '[xxx]' (String) from property 'foo.ls' (List<String>).  Invalid input for JsonParser parser."));
+			assertTrue(e.getMessage().startsWith("Cannot remove value '[xxx]' (String) from property 'foo.ls' (List<String>).  Invalid input for Simple parser."));
 		}
 	}
 
@@ -1601,7 +1601,8 @@ public class PropertyStoreTest {
 			b.addTo("A.foo.sms", "{xxx}");
 			fail("Exception expected.");
 		} catch (ConfigException e) {
-			assertTrue(e.getMessage().startsWith("Cannot add '{xxx}' (String) to property 'foo.sms' (Map<String,String>) .  Invalid input for JsonParser parser."));
+			System.err.println(e.getMessage());
+			assertTrue(e.getMessage().startsWith("Cannot add '{xxx}' (String) to property 'foo.sms' (Map<String,String>) .  Invalid input for Simple parser."));
 		}
 		try {
 			b.addTo("A.foo.sms", "xxx");
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index aaf0fbe..097021a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -1782,6 +1782,15 @@ public final class ClassMeta<T> implements Type {
 		return getReadableClassName(this.innerClass);
 	}
 
+	/**
+	 * Shortcut for calling {@link Class#getSimpleName()} on the inner class of this metadata.
+	 * 
+	 * @return The simple name of the inner class.
+	 */
+	public String getSimpleName() {
+		return innerClass.getSimpleName();
+	}
+	
 	private static class LocaleAsString {
 		private static Method forLanguageTagMethod;
 		static {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
index a41239c..5b7ca6d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
@@ -948,6 +948,23 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	}
 
 	/**
+	 * Same as {@link #getObjectMap(String)} but creates a new empty {@link ObjectMap} if it doesn't already exist.
+	 * 
+	 * @param key The key.
+	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link ObjectMap}.
+	 * @return The converted value, or an empty value if the map contains no mapping for this key.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public ObjectMap getObjectMap(String key, boolean createIfNotExists) {
+		ObjectMap m = getWithDefault(key, null, ObjectMap.class);
+		if (m == null && createIfNotExists) {
+			m = new ObjectMap();
+			put(key, m);
+		}
+		return m;
+	}
+
+	/**
 	 * Returns the specified entry value converted to a {@link ObjectList}.
 	 * 
 	 * <p>
@@ -977,6 +994,23 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	}
 
 	/**
+	 * Same as {@link #getObjectList(String)} but creates a new empty {@link ObjectList} if it doesn't already exist.
+	 * 
+	 * @param key The key.
+	 * @param createIfNotExists If mapping doesn't already exist, create one with an empty {@link ObjectList}.
+	 * @return The converted value, or an empty value if the map contains no mapping for this key.
+	 * @throws InvalidDataConversionException If value cannot be converted.
+	 */
+	public ObjectList getObjectList(String key, boolean createIfNotExists) {
+		ObjectList m = getWithDefault(key, null, ObjectList.class);
+		if (m == null && createIfNotExists) {
+			m = new ObjectList();
+			put(key, m);
+		}
+		return m;
+	}
+
+	/**
 	 * Returns the first entry that exists converted to a {@link String}.
 	 * 
 	 * <p>
@@ -1242,6 +1276,19 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	}
 
 	/**
+	 * Adds a mapping if the specified key doesn't exist.
+	 * 
+	 * @param key The map key.
+	 * @param val The value to set if the current value does not exist or is <jk>null</jk> or an empty string.
+	 * @return This object (for method chaining).
+	 */
+	public ObjectMap putIfNotExists(String key, Object val) {
+		if (! containsKey(key))
+			put(key, val);
+		return this;
+	}
+
+	/**
 	 * Converts this map into an object of the specified type.
 	 * 
 	 * <p>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartType.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartType.java
index 6df019b..5ab788b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartType.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartType.java
@@ -27,5 +27,8 @@ public enum HttpPartType {
 	FORM_DATA,
 
 	/** An HTTP header */
-	HEADER
+	HEADER,
+	
+	/** A non-standard field */
+	OTHER;
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
index 5a4bdd3..1efa411 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -153,7 +153,7 @@ public class JsonParser extends ReaderParser {
 	//-------------------------------------------------------------------------------------------------------------------
 
 	/** Default parser, all default settings.*/
-	public static final JsonParser DEFAULT = new JsonParser(PropertyStore.DEFAULT);
+	public static final JsonParser DEFAULT = new JsonParser.Simple(PropertyStore.DEFAULT);
 
 	/** Default parser, all default settings.*/
 	public static final JsonParser DEFAULT_STRICT = new JsonParser.Strict(PropertyStore.DEFAULT);
@@ -176,6 +176,18 @@ public class JsonParser extends ReaderParser {
 		}
 	}
 
+	/** Default parser, simple mode. */
+	public static class Simple extends JsonParser {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param ps The property store containing all the settings for this object.
+		 */
+		public Simple(PropertyStore ps) {
+			super(ps, "application/json+simple", "text/json+simple");
+		}
+	}
 
 	//-------------------------------------------------------------------------------------------------------------------
 	// Instance
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
index 5d2df07..0c2612c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
@@ -60,7 +60,7 @@ import org.apache.juneau.rest.widget.*;
 	children={
 		HelloWorldResource.class,
 		PetStoreResource.class,
-		org.apache.juneau.examples.petstore.PetStoreResource.class,
+		org.apache.juneau.examples.rest.petstore.PetStoreResource.class,
 		SystemPropertiesResource.class,
 		MethodExampleResource.class,
 		RequestEchoResource.class,
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/ApiResponse.java
similarity index 97%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/ApiResponse.java
index a2a5401..69b2cd4 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/ApiResponse.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
similarity index 97%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
index e8a48d4..16184d0 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
similarity index 97%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
index 5699c3c..724ce07 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
similarity index 96%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
index 774ae77..f8084ab 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 public enum OrderStatus {
 	PLACED, APPROVED, DELIVERED;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
similarity index 98%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
index 21c4751..f6b2381 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import java.util.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
similarity index 96%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
index e475bf3..2d2826e 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 public enum PetStatus {
 	AVAILABLE, PENDING, SOLD;
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
similarity index 96%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
index 9bbfe9b..d10c265 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import java.util.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
similarity index 97%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
index 298b885..fdd9dfc 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
similarity index 98%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
index 05a79e0..d6978cc 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
@@ -10,7 +10,7 @@
 // * "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.examples.petstore;
+package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
 
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.json b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/PetStoreResource.json
similarity index 100%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.json
rename to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/PetStoreResource.json
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
index 0ef39f2..52ab465 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
@@ -49,6 +49,7 @@ import org.apache.juneau.xml.*;
 	},
 	parsers={
 		JsonParser.class,
+		JsonParser.Simple.class,
 		XmlParser.class,
 		HtmlParser.class,
 		UonParser.class,
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
index f46c47b..67da8eb 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
@@ -15,6 +15,7 @@ package org.apache.juneau.rest;
 import static org.apache.juneau.internal.ReflectionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.serializer.WriterSerializer.*;
+import static org.apache.juneau.serializer.OutputStreamSerializer.*;
 
 import java.lang.reflect.Method;
 import java.util.*;
@@ -23,6 +24,7 @@ import java.util.concurrent.*;
 import org.apache.juneau.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.parser.*;
@@ -50,7 +52,7 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 		siteName,
 		title,
 		description;
-	private final ConcurrentHashMap<Locale,Swagger> swaggers = new ConcurrentHashMap<>();
+	private final ConcurrentHashMap<Locale,ConcurrentHashMap<Integer,Swagger>> swaggers = new ConcurrentHashMap<>();
 
 	/**
 	 * Constructor.
@@ -99,244 +101,385 @@ public class BasicRestInfoProvider implements RestInfoProvider {
 	 * 	<br>Never <jk>null</jk>.
 	 * @throws Exception
 	 */
+	@SuppressWarnings("unchecked")
 	@Override /* RestInfoProvider */
 	public Swagger getSwagger(RestRequest req) throws Exception {
 		
 		Locale locale = req.getLocale();
 		BeanSession bs = req.getBeanSession();
 		
-		Swagger s = swaggers.get(locale);
-		if (s != null)
-			return s;
+		// Find it in the cache.
+		// Swaggers are cached by user locale and an int hash of the @RestMethods they have access to.
+		HashCode userHash = HashCode.create();
+		for (RestJavaMethod sm : context.getCallMethods().values())
+			if (sm.isRequestAllowed(req))
+				userHash.add(sm.hashCode());
+		int hashCode = userHash.get();
+		
+		if (! swaggers.containsKey(locale))
+			swaggers.putIfAbsent(locale, new ConcurrentHashMap<Integer,Swagger>());
+		
+		Swagger swagger = swaggers.get(locale).get(hashCode);
+		if (swagger != null)
+			return swagger;
 
+		// Wasn't cached...need to create one.
+		
 		VarResolverSession vr = req.getVarResolverSession();
 		JsonParser jp = JsonParser.DEFAULT;
 		MessageBundle mb = context.getMessages();
+		Class<?> c = context.getResource().getClass();
 		
-		ObjectMap om = context.getClasspathResource(ObjectMap.class, MediaType.JSON, getClass().getSimpleName() + ".json", locale);
-		if (om == null)
-			om = new ObjectMap();
+		// Load swagger JSON from classpath.
+		ObjectMap omSwagger = context.getClasspathResource(ObjectMap.class, MediaType.JSON, getClass().getSimpleName() + ".json", locale);
+		if (omSwagger == null)
+			omSwagger = new ObjectMap();
 		
-		LinkedHashMap<Class<?>,RestResource> restResourceAnnotationsParentFirst = findAnnotationsMapParentFirst(RestResource.class, context.getResource().getClass());
-
-		for (RestResource r : restResourceAnnotationsParentFirst.values()) {
+		// Combine it with @RestResource(swagger)
+		for (Map.Entry<Class<?>,RestResource> e : findAnnotationsMapParentFirst(RestResource.class, context.getResource().getClass()).entrySet()) {
+			RestResource r = e.getValue();
 			if (r.swagger().length > 0) {
 				try {
-					String json = vr.resolve(StringUtils.join(r.swagger(), '\n').trim());
-					if (! StringUtils.isObjectMap(json, true))
+					String json = vr.resolve(join(r.swagger(), '\n').trim());
+					if (! isObjectMap(json, true))
 						json = "{\n" + json + "\n}";
-					om.putAll(new ObjectMap(json));
-				} catch (ParseException e) {
-					throw new ParseException("Malformed swagger JSON encountered in @RestResource(swagger) on class "+context.getResource().getClass().getName()+".").initCause(e);
+					omSwagger.putAll(new ObjectMap(json));
+				} catch (ParseException x) {
+					throw new SwaggerException(x, e.getKey(), "Malformed swagger JSON encountered in @RestResource(swagger).");
 				}
 			}
 		}
+		
+//		System.out.println("==============================================================================================");
+//		System.out.println("omSwagger=");
+//		JsonSerializer.DEFAULT_LAX_READABLE.println(omSwagger);
+		
+		ObjectMap 
+			info = omSwagger.getObjectMap("info", true),
+			externalDocs = omSwagger.getObjectMap("externalDocs", true),
+			definitions = omSwagger.getObjectMap("definitions", true);
+		ObjectList
+			produces = omSwagger.getObjectList("produces", true),
+			consumes = omSwagger.getObjectList("consumes", true);
+		
+		String s = this.title;
+		if (s == null)
+			s = mb.findFirstString(locale, "title");
+		if (s != null) 
+			info.put("title", vr.resolve(s));
 
-		String title = this.title;
-		if (title == null)
-			title = mb.findFirstString(locale, "title");
-		if (title != null) 
-			getInfo(om).put("title", vr.resolve(title));
-
-		String description = this.description;
-		if (description == null)
-			description = mb.findFirstString(locale, "description");
-		if (description != null) 
-			getInfo(om).put("description", vr.resolve(description));
+		s = this.description;
+		if (s == null)
+			s = mb.findFirstString(locale, "description");
+		if (s != null) 
+			info.put("description", vr.resolve(s));
 		
-		String version = mb.findFirstString(locale, "version");
-		if (version != null) 
-			getInfo(om).put("version", vr.resolve(version));
+		s = mb.findFirstString(locale, "version");
+		if (s != null) 
+			info.put("version", vr.resolve(s));
 		
-		String contact = mb.findFirstString(locale, "contact");
-		if (contact != null) 
-			getInfo(om).put("contact", jp.parse(vr.resolve(contact), ObjectMap.class));
+		s = mb.findFirstString(locale, "contact");
+		if (s != null) 
+			info.put("contact", jp.parse(vr.resolve(s), ObjectMap.class));
 		
-		String license = mb.findFirstString(locale, "license");
-		if (license != null) 
-			getInfo(om).put("license", jp.parse(vr.resolve(license), ObjectMap.class));
+		s = mb.findFirstString(locale, "license");
+		if (s != null) 
+			info.put("license", jp.parse(vr.resolve(s), ObjectMap.class));
 		
-		String termsOfService = mb.findFirstString(locale, "termsOfService");
-		if (termsOfService != null) 
-			getInfo(om).put("termsOfService", vr.resolve(termsOfService));
+		s = mb.findFirstString(locale, "termsOfService");
+		if (s != null) 
+			info.put("termsOfService", vr.resolve(s));
 		
-		if (! om.containsKey("consumes")) {
-			List<MediaType> consumes = req.getContext().getConsumes();
-			if (! consumes.isEmpty())
-				om.put("consumes", consumes);
-		}
+		if (consumes.isEmpty()) 
+			consumes.addAll(req.getContext().getConsumes());
 
-		if (! om.containsKey("produces")) {
-			List<MediaType> produces = req.getContext().getProduces();
-			if (! produces.isEmpty())
-				om.put("produces", produces);
+		if (produces.isEmpty()) 
+			produces.addAll(req.getContext().getProduces());
+		
+		Map<String,ObjectMap> tagMap = new LinkedHashMap<>();
+		if (omSwagger.containsKey("tags")) {
+			for (ObjectMap om : omSwagger.getObjectList("tags").elements(ObjectMap.class)) {
+				String name = om.getString("name");
+				if (name == null)
+					throw new SwaggerException(c, "Tag definition found without name in swagger JSON.");
+				tagMap.put(name, om);
+			}
 		}
-			
-		String tags = mb.findFirstString(locale, "tags");
-		if (tags != null)
-			om.put("tags", jp.parse(vr.resolve(tags), ObjectList.class));
-
-		String externalDocs = mb.findFirstString(locale, "externalDocs");
-		if (externalDocs != null)
-			om.put("externalDocs", jp.parse(vr.resolve(externalDocs), ObjectMap.class));
 		
-		ObjectMap definitions = om.getObjectMap("definitions", new ObjectMap());
+		s = mb.findFirstString(locale, "tags");
+		if (s != null) {
+			for (ObjectMap m : jp.parse(vr.resolve(s), ObjectList.class).elements(ObjectMap.class)) {
+				String name = m.getString("name");
+				if (name == null)
+					throw new SwaggerException(c, "Tag definition found without name in resource bundle.");
+				if (tagMap.containsKey(name))
+					tagMap.get(name).putAll(m);
+				else
+					tagMap.put(name, m);
+			}
+		}
+
+		s = mb.findFirstString(locale, "externalDocs");
+		if (s != null) 
+			externalDocs.putAll(jp.parse(vr.resolve(s), ObjectMap.class));
 		
+		// Iterate through all the @RestMethod methods.
 		for (RestJavaMethod sm : context.getCallMethods().values()) {
-			if (sm.isRequestAllowed(req)) {
-				Method m = sm.method;
-				RestMethod rm = m.getAnnotation(RestMethod.class);
-				String mn = m.getName(), cn = m.getClass().getName();
-				
-				ObjectMap mom = getOperation(om, sm.getPathPattern(), sm.getHttpMethod().toLowerCase());
-				
-				if (rm.swagger().length > 0) {
-					try {
-						String json = vr.resolve(StringUtils.join(rm.swagger(), '\n').trim());
-						if (! (json.startsWith("{") && json.endsWith("}")))
-							json = "{\n" + json + "\n}";
-						mom.putAll(new ObjectMap(json));
-					} catch (ParseException e) {
-						throw new ParseException("Malformed swagger JSON encountered in @RestMethod(swagger) on method "+mn+" on class "+cn+".").initCause(e);
-					}
+			
+			// Skip it if user doesn't have access.
+			if (! sm.isRequestAllowed(req))
+				continue;
+			
+			Method m = sm.method;
+			RestMethod rm = m.getAnnotation(RestMethod.class);
+			String mn = m.getName();
+			
+			// Get the operation from the existing swagger so far.
+			ObjectMap op = getOperation(omSwagger, sm.getPathPattern(), sm.getHttpMethod().toLowerCase());
+			
+			// Add @RestMethod(swagger)
+			if (rm.swagger().length > 0) {
+				try {
+					String json = vr.resolve(join(rm.swagger(), '\n').trim());
+					if (! isObjectMap(json, true))
+						json = "{\n" + json + "\n}";
+					op.putAll(new ObjectMap(json));
+				} catch (ParseException e) {
+					throw new SwaggerException(e, m, "Malformed swagger JSON encountered in @RestMethod(swagger).");
 				}
+			}
 
-				mom.put("operationId", mn);
-				
-				String mDescription = rm.description();
-				if (mDescription.isEmpty())
-					mDescription = mb.findFirstString(locale, mn + ".description");
-				if (mDescription != null)
-					mom.put("description", vr.resolve(mDescription));
-				
-				String mTags = mb.findFirstString(locale, mn + ".tags");
-				if (mTags != null) {
-					mTags = vr.resolve(mTags);
-					if (StringUtils.isObjectList(mTags, true)) 
-						mom.put("tags", jp.parse(mTags, ArrayList.class, String.class));
-					else
-						mom.put("tags", Arrays.asList(StringUtils.split(mTags)));
-				}
-				
-				String mSummary = mb.findFirstString(locale, mn + ".summary");
-				if (mSummary != null)
-					mom.put("summary", vr.resolve(mSummary));
+			op.putIfNotExists("operationId", mn);
+			
+			s = rm.description();
+			if (s.isEmpty())
+				s = mb.findFirstString(locale, mn + ".description");
+			if (s != null)
+				op.put("description", vr.resolve(s));
 
-				String mExternalDocs = mb.findFirstString(locale, mn + ".externalDocs");
-				if (mExternalDocs != null) 
-					mom.put("externalDocs", jp.parse(vr.resolve(s), ObjectMap.class));
-				
-				Map<String,ObjectMap> paramMap = new LinkedHashMap<>();
+			Set<String> tags = new LinkedHashSet<>();
+			if (op.containsKey("tags"))
+				for (String tag : op.getObjectList("tags").elements(String.class)) 
+					tags.add(tag);
+			
+			s = mb.findFirstString(locale, mn + ".tags");
+			if (s != null) {
+				s = vr.resolve(s);
+				if (isObjectList(s, true))
+					tags.addAll((List<String>)jp.parse(s, ArrayList.class, String.class));
+				else
+					tags.addAll(Arrays.asList(StringUtils.split(s)));
+			}
+			
+			for (String tag : tags) 
+				if (! tagMap.containsKey(tag))
+					tagMap.put(tag, new ObjectMap().append("name", tag));
+			
+			op.put("tags", tags);
+			
+			s = mb.findFirstString(locale, mn + ".summary");
+			if (s != null)
+				op.put("summary", vr.resolve(s));
 
-				ObjectList parameters = mom.getObjectList("parameters");
-				if (parameters != null) {
-					for (ObjectMap param : parameters.elements(ObjectMap.class)) {
-						String key = param.getString("in") + '.' + param.getString("name");
+			s = mb.findFirstString(locale, mn + ".externalDocs");
+			if (s != null) {
+				ObjectMap eom = jp.parse(vr.resolve(s), ObjectMap.class);
+				if (op.containsKey("externalDocs"))
+					op.getObjectMap("externalDocs").putAll(eom);
+				else
+					op.put("externalDocs", eom);
+			}
+			
+			ObjectMap paramMap = new ObjectMap();
+
+			ObjectList ol = op.getObjectList("parameters");
+			if (ol != null) 
+				for (ObjectMap param : ol.elements(ObjectMap.class)) 
+					paramMap.put(param.getString("in") + '.' + param.getString("name"), param);
+		
+			s = mb.findFirstString(locale, mn + ".parameters");
+			if (s != null) {
+				ol = jp.parse(vr.resolve(s), ObjectList.class);
+				for (ObjectMap param : ol.elements(ObjectMap.class)) {
+					String key = param.getString("in") + '.' + param.getString("name");
+					if (paramMap.containsKey(key))
+						paramMap.getObjectMap(key).putAll(param);
+					else
 						paramMap.put(key, param);
-					}
 				}
+			}
 			
-				String mParameters = mb.findFirstString(locale, mn + ".parameters");
-				if (mParameters != null) {
-					ObjectList ol = jp.parse(vr.resolve(mParameters), ObjectList.class);
-					for (ObjectMap param : ol.elements(ObjectMap.class)) {
-						String key = param.getString("in") + '.' + param.getString("name");
-						if (paramMap.containsKey(key))
-							paramMap.get(key).putAll(param);
-						else
-							paramMap.put(key, param);
-					}
-				}
+			// Finally, look for parameters defined on method.
+			for (RestParam mp : context.getRestParams(m)) {
 				
-				// Finally, look for parameters defined on method.
-				for (RestParam mp : context.getRestParams(m)) {
-					RestParamType in = mp.getParamType();
-					if (in != RestParamType.OTHER) {
-						String key = in.toString() + '.' + (in == RestParamType.BODY ? null : mp.getName());
-						
-						if (! paramMap.containsKey(key))
-							paramMap.put(key, new ObjectMap());
-						ObjectMap param = paramMap.get(key);
-							
-						param.append("in", in);
-						
-						if (in != RestParamType.BODY)
-							param.append("name", mp.name);
+				RestParamType in = mp.getParamType();
+				
+				if (in == RestParamType.OTHER)
+					continue;
+				
+				String key = in.toString() + '.' + (in == RestParamType.BODY ? null : mp.getName());
+				
+				ObjectMap param = paramMap.getObjectMap(key, true);
+					
+				param.append("in", in);
+				
+				if (in != RestParamType.BODY)
+					param.append("name", mp.name);
+				
+				if (! param.containsKey("schema")) {
+					
+					ClassMeta<?> cm = bs.getClassMeta(mp.getType());
+					
+					if (cm.isMapOrBean() || cm.isCollectionOrArray()) {
+						String name = cm.getSimpleName();
 						
-						if (! param.containsKey("schema")) {
-							ClassMeta<?> cm = bs.getClassMeta(mp.getType());
-							
-							if (cm.isBean()) {
-								String name = mp.forClass().getSimpleName();
-								if (! definitions.containsKey(name)) {
-									ObjectMap definition = JsonSchemaUtils.getSchema(bs, cm);
-									
-									Object example = cm.getExample(bs);
-									if (example != null) {
-										ObjectMap examples = new ObjectMap();
-										ObjectMap sprops = new ObjectMap().append(WSERIALIZER_useWhitespace, true);
-										for (MediaType mt : req.getParsers().getSupportedMediaTypes()) {
-											if (mt != MediaType.HTML) {
-												Serializer s2 = req.getSerializers().getSerializer(mt);
-												if (s2 != null) {
-													SerializerSessionArgs args = new SerializerSessionArgs(sprops, req.getJavaMethod(), req.getLocale(), null, mt, req.getUriContext());
-													String eVal = s2.createSession(args).serializeToString(example);
-													examples.put(s2.getMediaTypes()[0].toString(), eVal);
-												}
+						if (! definitions.containsKey(name)) {
+							ObjectMap definition = JsonSchemaUtils.getSchema(bs, cm);
+							Object example = cm.getExample(bs);
+
+							if (example != null) {
+								ObjectMap examples = new ObjectMap();
+								ObjectMap sprops = new ObjectMap().append(WSERIALIZER_useWhitespace, true).append(OSSERIALIZER_binaryFormat, BinaryFormat.SPACED_HEX);
+								
+								if (in == RestParamType.BODY) {
+									for (MediaType mt : req.getParsers().getSupportedMediaTypes()) {
+										if (mt != MediaType.HTML) {
+											Serializer s2 = req.getSerializers().getSerializer(mt);
+											if (s2 != null) {
+												SerializerSessionArgs args = new SerializerSessionArgs(sprops, req.getJavaMethod(), req.getLocale(), null, mt, req.getUriContext());
+												String eVal = s2.createSession(args).serializeToString(example);
+												examples.put(s2.getMediaTypes()[0].toString(), eVal);
 											}
 										}
-										definition.put("x-examples", examples);
 									}
-									
-									definitions.put(name, definition);
+								} else {
+									examples.put("example", req.getPartSerializer().serialize(HttpPartType.valueOf(in.name()), example));
 								}
-								param.put("schema", new ObjectMap().append("$ref", "#/definitions/" + mp.forClass().getSimpleName()));
+								
+								definition.put("x-examples", examples);
 							}
+							
+							definitions.put(name, definition);
 						}
+						param.put("schema", new ObjectMap().append("$ref", "#/definitions/" + name));
 					}
 				}
-				
-				if (! paramMap.isEmpty())
-					mom.put("parameters", paramMap.values());
-				
-				String mResponses = mb.findFirstString(locale, mn + ".responses");
-				if (mResponses != null) 
-					mom.put("responses", jp.parse(vr.resolve(mResponses), ObjectMap.class));
+			}
+			
+			if (! paramMap.isEmpty())
+				op.put("parameters", paramMap.values());
 
-				if (! mom.containsKey("consumes")) {
-					List<MediaType> mConsumes = req.getParsers().getSupportedMediaTypes();
-					if (! mConsumes.equals(om.get("consumes")))
-						mom.put("consumes", mConsumes);
+			ObjectMap responses = op.getObjectMap("responses", true);
+			
+			s = mb.findFirstString(locale, mn + ".responses");
+			if (s != null) {
+				for (Map.Entry<String,Object> e : jp.parse(vr.resolve(s), ObjectMap.class).entrySet()) {
+					String httpCode = e.getKey();
+					if (responses.containsKey(httpCode))
+						responses.getObjectMap(httpCode).putAll((ObjectMap)e.getValue());
+					else
+						responses.put(httpCode, e.getValue());
 				}
-	
-				if (! mom.containsKey("produces")) {
-					List<MediaType> mProduces = req.getSerializers().getSupportedMediaTypes();
-					if (! mProduces.equals(om.get("produces")))
-						mom.put("produces", mProduces);
+			}
+			
+			if (! responses.containsKey("200"))
+				responses.put("200", new ObjectMap().append("description", "Success"));
+			
+			ObjectMap okResponse = responses.getObjectMap("200");
+			
+			ClassMeta<?> cm = bs.getClassMeta(m.getReturnType());
+			
+			if ((cm.isMapOrBean() || cm.isCollectionOrArray()) && ! okResponse.containsKey("schema") && cm.getInnerClass() != Swagger.class) {
+				String name = cm.getSimpleName();
+				
+				if (! definitions.containsKey(name)) {
+					ObjectMap definition;
+					try {
+						definition = JsonSchemaUtils.getSchema(bs, cm);
+					} catch (Exception e1) {
+						System.err.println(cm);
+						throw e1;
+					}	
+					Object example = cm.getExample(bs);
+					
+					if (example != null) {
+						ObjectMap examples = new ObjectMap();
+						ObjectMap sprops = new ObjectMap().append(WSERIALIZER_useWhitespace, true).append(OSSERIALIZER_binaryFormat, BinaryFormat.SPACED_HEX);
+						
+						for (MediaType mt : req.getSerializers().getSupportedMediaTypes()) {
+							if (mt != MediaType.HTML) {
+								Serializer s2 = req.getSerializers().getSerializer(mt);
+								if (s2 != null) {
+									SerializerSessionArgs args = new SerializerSessionArgs(sprops, req.getJavaMethod(), req.getLocale(), null, mt, req.getUriContext());
+									String eVal = s2.createSession(args).serializeToString(example);
+									examples.put(s2.getMediaTypes()[0].toString(), eVal);
+								}
+							}
+						}
+						definition.put("x-examples", examples);
+					}
+					
+					definitions.put(name, definition);
 				}
+				
+				okResponse.put("schema", new ObjectMap().append("$ref", "#/definitions/" + name));
+			}			
+			
+			if (responses.isEmpty())
+				op.remove("responses");
+			else
+				op.put("responses", new TreeMap<>(responses));
+			
+			if (! op.containsKey("consumes")) {
+				List<MediaType> mConsumes = req.getParsers().getSupportedMediaTypes();
+				if (! mConsumes.equals(consumes))
+					op.put("consumes", mConsumes);
+			}
+
+			if (! op.containsKey("produces")) {
+				List<MediaType> mProduces = req.getSerializers().getSupportedMediaTypes();
+				if (! mProduces.equals(produces))
+					op.put("produces", mProduces);
 			}
 		}
 		
-		if (! definitions.isEmpty())
-			om.put("definitions", definitions);		
+		if (definitions.isEmpty())
+			omSwagger.remove("definitions");		
+		if (tagMap.isEmpty())
+			omSwagger.remove("tags");
 		
-		String swaggerJson = om.toString(JsonSerializer.DEFAULT_LAX_READABLE);
+		String swaggerJson = omSwagger.toString(JsonSerializer.DEFAULT_LAX_READABLE);
 		try {
-			s = jp.parse(swaggerJson, Swagger.class);
+			swagger = jp.parse(swaggerJson, Swagger.class);
 		} catch (Exception e) {
-			throw new RestServletException("Error detected in swagger: \n{0}", StringUtils.addLineNumbers(swaggerJson)).initCause(e);
+			throw new RestServletException("Error detected in swagger: \n{0}", addLineNumbers(swaggerJson)).initCause(e);
 		}
-		swaggers.put(locale, s);
 		
-		return s;
+		swaggers.get(locale).put(hashCode, swagger);
+		
+//		System.out.println("==============================================================================================");
+//		System.out.println("swagger=");
+//		JsonSerializer.DEFAULT_LAX_READABLE.println(swagger);
+		
+		return swagger;
 	}
 	
-	private ObjectMap getInfo(ObjectMap om) {
-		if (! om.containsKey("info"))
-			om.put("info", new ObjectMap());
-		return om.getObjectMap("info");
+	private static class SwaggerException extends ParseException {
+		private static final long serialVersionUID = 1L;
+		
+		SwaggerException(Class<?> c, String message, Object...args) {
+			this(null, c, message, args);
+		}
+		SwaggerException(Exception e, Class<?> c, String message, Object...args) {
+			super("Swagger exception on class " + c.getName() + ".  " + message, args);
+			initCause(e);
+		}
+		SwaggerException(Exception e, Method m, String message, Object...args) {
+			super("Swagger exception on class " + m.getDeclaringClass().getName() + " method "+m.getName()+".  " + message, args);
+			initCause(e);
+		}
 	}
-
+	
 	private ObjectMap getOperation(ObjectMap om, String path, String httpMethod) {
 		if (! om.containsKey("paths"))
 			om.put("paths", new ObjectMap());
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
index 1229aa4..390e3e6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestJavaMethod.java
@@ -577,7 +577,7 @@ public class RestJavaMethod implements Comparable<RestJavaMethod>  {
 
 	@Override /* Object */
 	public int hashCode() {
-		return super.hashCode();
+		return method.hashCode();
 	}
 	
 	static String[] resolveVars(VarResolver vr, String[] in) {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index 26635e5..0fe47c3 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -598,7 +598,7 @@ class RestParamDefaults {
 		private final HttpPartParser partParser;
 
 		protected FormDataObject(Method method, FormData a, Type type, PropertyStore ps) throws ServletException {
-			super(FORMDATA, firstNonEmpty(a.name(), a.value()), type);
+			super(FORM_DATA, firstNonEmpty(a.name(), a.value()), type);
 			if (a.multipart() && ! isCollection(type))
 					throw new RestServletException("Use of multipart flag on @FormData parameter that's not an array or Collection on method ''{0}''", method);
 			this.multiPart = a.multipart();
@@ -636,7 +636,7 @@ class RestParamDefaults {
 	static final class HasFormDataObject extends RestParam {
 
 		protected HasFormDataObject(Method method, HasFormData a, Type type) throws ServletException {
-			super(FORMDATA, firstNonEmpty(a.name(), a.value()), type);
+			super(FORM_DATA, firstNonEmpty(a.name(), a.value()), type);
 			if (type != Boolean.class && type != boolean.class)
 				throw new RestServletException("Use of @HasForm annotation on parameter that is not a boolean on method ''{0}''", method);
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
index 1cb8a21..ff913c5 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamType.java
@@ -29,7 +29,7 @@ public enum RestParamType {
 	HEADER("header"),
 
 	/** Form data entry */
-	FORMDATA("formData"),
+	FORM_DATA("formData"),
 
 	/** Query parameter */
 	QUERY("query"),
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index 1fbbe03..f134546 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -34,6 +34,7 @@ import org.apache.juneau.*;
 import org.apache.juneau.config.*;
 import org.apache.juneau.dto.swagger.*;
 import org.apache.juneau.http.*;
+import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
@@ -1048,6 +1049,14 @@ public final class RestRequest extends HttpServletRequestWrapper {
 		return restJavaMethod.parsers;
 	}
 
+	/**
+	 * Returns the part serializer associated with this request.
+	 * 
+	 * @return The part serializer associated with this request.
+	 */
+	public HttpPartSerializer getPartSerializer() {
+		return restJavaMethod.partSerializer;
+	}
 
 	/**
 	 * Returns the method of this request.

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.

Mime
View raw message