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 2018/04/05 18:19:51 UTC

[juneau] branch master updated: New option for dyna-property.

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 58225b7  New option for dyna-property.
58225b7 is described below

commit 58225b702ae59fc11a741d6fac0e09fc4f47b3b8
Author: JamesBognar <ja...@apache.org>
AuthorDate: Thu Apr 5 14:19:48 2018 -0400

    New option for dyna-property.
---
 .../java/org/apache/juneau/DynaBeanComboTest.java  | 79 ++++++++++++++++++++++
 .../src/main/java/org/apache/juneau/BeanMeta.java  | 35 ++++++----
 .../java/org/apache/juneau/BeanPropertyMeta.java   | 11 +--
 .../org/apache/juneau/annotation/BeanProperty.java | 20 ++++++
 juneau-doc/src/main/javadoc/overview.html          |  3 +
 5 files changed, 132 insertions(+), 16 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/DynaBeanComboTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/DynaBeanComboTest.java
index 6711527..9fbd80a 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/DynaBeanComboTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/DynaBeanComboTest.java
@@ -206,6 +206,41 @@ public class DynaBeanComboTest extends ComboRoundTripTest {
 					}
 				}
 			},
+			{ 	/* 5 */
+				new ComboInput<BeanWithDynaMethodsAndExtraKeys>(
+					"BeanWithDynaMethodsAndExtraKeys",
+					BeanWithDynaMethodsAndExtraKeys.class,
+					new BeanWithDynaMethodsAndExtraKeys().init(),
+					/* Json */		"{f1:1,f2a:'a',f2b:'b',f3:3}",
+					/* JsonT */		"{f1:1,f2a:'a',f2b:'b',f3:3}",
+					/* JsonR */		"{\n\tf1: 1,\n\tf2a: 'a',\n\tf2b: 'b',\n\tf3: 3\n}",
+					/* Xml */		"<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>",
+					/* XmlT */		"<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>",
+					/* XmlR */		"<object>\n\t<f1>1</f1>\n\t<f2a>a</f2a>\n\t<f2b>b</f2b>\n\t<f3>3</f3>\n</object>\n",
+					/* XmlNs */		"<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>",
+					/* Html */		"<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>",
+					/* HtmlT */		"<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>",
+					/* HtmlR */		"<table>\n\t<tr>\n\t\t<td>f1</td>\n\t\t<td>1</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2a</td>\n\t\t<td>a</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2b</td>\n\t\t<td>b</td>\n\t</tr>\n\t<tr>\n\t\t<td>f3</td>\n\t\t<td>3</td>\n\t</tr>\n</table>\n",
+					/* Uon */		"(f1=1,f2a=a,f2b=b,f3=3)",
+					/* UonT */		"(f1=1,f2a=a,f2b=b,f3=3)",
+					/* UonR */		"(\n\tf1=1,\n\tf2a=a,\n\tf2b=b,\n\tf3=3\n)",
+					/* UrlEnc */	"f1=1&f2a=a&f2b=b&f3=3",
+					/* UrlEncT */	"f1=1&f2a=a&f2b=b&f3=3",
+					/* UrlEncR */	"f1=1\n&f2a=a\n&f2b=b\n&f3=3",
+					/* MsgPack */	"84A2663101A3663261A161A3663262A162A2663303",
+					/* MsgPackT */	"84A2663101A3663261A161A3663262A162A2663303",
+					/* RdfXml */	"<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n",
+					/* RdfXmlT */	"<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n",
+					/* RdfXmlR */	"<rdf:RDF>\n  <rdf:Description>\n    <jp:f1>1</jp:f1>\n    <jp:f2a>a</jp:f2a>\n    <jp:f2b>b</jp:f2b>\n    <jp:f3>3</jp:f3>\n  </rdf:Description>\n</rdf:RDF>\n"
+				)
+				{
+					@Override
+					public void verify(BeanWithDynaMethodsAndExtraKeys o) {
+						assertType(BeanWithDynaMethodsAndExtraKeys.class, o);
+						Assert.assertTrue(o.setterCalled);
+					}
+				}
+			},
 		});
 	}
 
@@ -278,6 +313,50 @@ public class DynaBeanComboTest extends ComboRoundTripTest {
 	}
 
 	@Bean(sort=true)
+	public static class BeanWithDynaMethodsAndExtraKeys {
+
+		private int f1, f3;
+		private Map<String,Object> f2 = new LinkedHashMap<String,Object>();
+		private boolean setterCalled = false;
+
+		public int getF1() {
+			return f1;
+		}
+		public void setF1(int f1) {
+			this.f1 = f1;
+		}
+		public int getF3() {
+			return f3;
+		}
+		public void setF3(int f3) {
+			this.f3 = f3;
+		}
+
+		@BeanProperty(name="*")
+		public Object get(String name) {
+			return f2.get(name);
+		}
+
+		@BeanProperty(name="*")
+		public void set(String name, Object o) {
+			setterCalled = true;
+			this.f2.put(name, o);
+		}
+
+		@BeanProperty(name="*")
+		public Collection<String> getExtraKeys() {
+			return f2.keySet();
+		}
+		
+		public BeanWithDynaMethodsAndExtraKeys init() {
+			this.f1 = 1;
+			this.f2 = new ObjectMap().append("f2a", "a").append("f2b", "b");
+			this.f3 = 3;
+			return this;
+		}
+	}
+
+	@Bean(sort=true)
 	public static class BeanWithDynaGetterOnly {
 
 		private int f1, f3;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index 0cacb9e..e15aedb 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -329,6 +329,14 @@ public class BeanMeta<T> {
 								bpm.setSetter(bm.method);
 						}
 					}
+					
+					// Now iterate through all the extraKeys.
+					for (BeanMethod bm : bms) {
+						if (bm.methodType == EXTRAKEYS) {
+							BeanPropertyMeta.Builder bpm = normalProps.get(bm.propertyName);
+							bpm.setExtraKeys(bm.method);
+						}
+					}
 				}
 
 				typeVarImpls = new HashMap<>();
@@ -611,19 +619,19 @@ public class BeanMeta<T> {
 					throw new BeanRuntimeException(c, "Found @BeanProperty(\"{0}\") but name was not found in @Bean(properties)", bpName);
 				
 				if (pt.length == 0) {
-					if (n.startsWith("get") && (! rt.equals(Void.TYPE))) {
-						methodType = GETTER;
-						n = n.substring(3);
-					} else if (n.startsWith("is") && (rt.equals(Boolean.TYPE) || rt.equals(Boolean.class))) {
-						methodType = GETTER;
-						n = n.substring(2);
-					} else if ("*".equals(bpName)) {
+					if ("*".equals(bpName)) {
 						if (isParentClass(Collection.class, rt)) {
 							methodType = EXTRAKEYS;
 						} else if (isParentClass(Map.class, rt)) {
 							methodType = GETTER;
 						}
 						n = bpName;
+					} else if (n.startsWith("get") && (! rt.equals(Void.TYPE))) {
+						methodType = GETTER;
+						n = n.substring(3);
+					} else if (n.startsWith("is") && (rt.equals(Boolean.TYPE) || rt.equals(Boolean.class))) {
+						methodType = GETTER;
+						n = n.substring(2);
 					} else if (bpName != null) {
 						methodType = GETTER;
 						if (bpName.isEmpty()) {
@@ -637,14 +645,17 @@ public class BeanMeta<T> {
 						}
 					}
 				} else if (pt.length == 1) {
-					if (n.startsWith("set") && (isParentClass(rt, c) || rt.equals(Void.TYPE))) {
-						methodType = SETTER;
-						n = n.substring(3);
-					} else if ("*".equals(bpName)) {
+					if ("*".equals(bpName)) {
 						if (isParentClass(Map.class, pt[0])) {
 							methodType = SETTER;
 							n = bpName;
+						} else if (pt[0] == String.class) {
+							methodType = GETTER;
+							n = bpName;
 						}
+					} else if (n.startsWith("set") && (isParentClass(rt, c) || rt.equals(Void.TYPE))) {
+						methodType = SETTER;
+						n = n.substring(3);
 					} else if (bpName != null) {
 						methodType = SETTER;
 						if (bpName.isEmpty()) {
@@ -670,7 +681,7 @@ public class BeanMeta<T> {
 				n = pn.getPropertyName(n);
 				
 				if ("*".equals(bpName) && methodType == UNKNOWN)
-					throw new BeanRuntimeException(c, "Found @BeanProperty(\"*\") but could not determine method type.", bpName);
+					throw new BeanRuntimeException(c, "Found @BeanProperty(\"*\") but could not determine method type on method ''{0}''.", m.getName());
 				
 				if (methodType != UNKNOWN) {
 					if (bpName != null && ! bpName.isEmpty()) {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 2872385..41cb2a9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -236,7 +236,7 @@ public final class BeanPropertyMeta {
 				if (isDyna) {
 					if (isParentClass(Map.class, c) && pt.length == 0) {
 						isDynaGetterMap = true;
-					} else if (pt.length == 2 && pt[0] == String.class) {
+					} else if (pt.length == 1 && pt[0] == String.class) {
 						// OK.
 					} else {
 						return false;
@@ -271,8 +271,11 @@ public final class BeanPropertyMeta {
 				}
 			}
 
-			if (isDyna)
+			if (isDyna) {
 				rawTypeMeta = rawTypeMeta.getValueType();
+				if (rawTypeMeta == null)
+					rawTypeMeta = beanContext.object();
+			}
 			if (rawTypeMeta == null)
 				return false;
 
@@ -779,7 +782,7 @@ public final class BeanPropertyMeta {
 			Map m = null;
 			if (getter != null) {
 				if (! isDynaGetterMap)
-					return getter.invoke(pName);
+					return getter.invoke(bean, pName);
 				m = (Map)getter.invoke(bean);
 			}
 			else if (field != null)
@@ -837,7 +840,7 @@ public final class BeanPropertyMeta {
 			if (extraKeys != null && getter != null && ! isDynaGetterMap) {
 				Map<String,Object> m = new LinkedHashMap<>();
 				for (String key : (Collection<String>)extraKeys.invoke(bean)) 
-					m.put(key, getter.invoke(bean));
+					m.put(key, getter.invoke(bean, key));
 				return m;
 			}
 			if (getter != null && isDynaGetterMap)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java
index 41f5448..eda2437 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/BeanProperty.java
@@ -93,6 +93,26 @@ public @interface BeanProperty {
 	 * 			...
 	 * 		}
 	 * 	}
+	 * 
+	 * 	<jc>// Option #4 - Getter, setter, and extra-keys method .
+	 * 	// Define a method that returns a Collection&lt;String&gt; with currently-set property names.</jc>
+	 * 	<jk>public class</jk> BeanWithDynaExtraKeys {
+	 * 
+	 * 		<ja>@BeanProperty</ja>(name=<js>"*"</js>)
+	 * 		<jk>public</jk> Object get(String name) {
+	 * 			...
+	 * 		}
+	 * 
+	 * 		<ja>@BeanProperty</ja>(name=<js>"*"</js>)
+	 * 		<jk>public void</jk> set(String name, Object value) {
+	 * 			...
+	 * 		}
+	 * 
+	 * 		<ja>@BeanProperty</ja>(name=<js>"*"</js>)
+	 * 		<jk>public</jk> Collection&lt;String&gt; extraKeys() {
+	 * 			...
+	 * 		}
+	 * 	}
 	 * </p>
 	 * 
 	 *<p>
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 087ee05..ea2213e 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21344,6 +21344,9 @@
 			<li>
 				Fixed <code>NullPointerException</code> when serializing beans with a dyna-property (i.e. <code><ja>@Bean</ja>(<js>"*"</js>)</code>)
 				which returns a <jk>null</jk> value.
+			<li>
+				New option for dyna-property (i.e. <code><ja>@Bean</ja>(<js>"*"</js>)</code>) using a method that returns a collection of extra keys.
+				<br>See new options #4 on {@link org.apache.juneau.annotation.BeanProperty#name()}
 		</ul>
 		
 		<h5 class='topic w800'>juneau-dto</h5>

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