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 6109582 Improvements to @Rest(messages)
6109582 is described below
commit 610958239eda54a22c7dd9bd073f7e40e2e57a82
Author: JamesBognar <[email protected]>
AuthorDate: Mon Jul 27 11:15:31 2020 -0400
Improvements to @Rest(messages)
---
.../apache/juneau/utils/Tuple2Function_Test.java | 71 +++++-------
.../java/org/apache/juneau/utils/Tuple2_Test.java | 84 +++++++-------
.../apache/juneau/utils/Tuple3Function_Test.java | 71 +++++-------
.../java/org/apache/juneau/utils/Tuple3_Test.java | 87 +++++++-------
.../apache/juneau/utils/Tuple4Function_Test.java | 71 +++++-------
.../java/org/apache/juneau/utils/Tuple4_Test.java | 90 ++++++++-------
.../apache/juneau/utils/Tuple5Function_Test.java | 71 +++++-------
.../java/org/apache/juneau/utils/Tuple5_Test.java | 53 +++++++++
.../java/org/apache/juneau/BeanPropertyMeta.java | 2 +-
.../java/org/apache/juneau/internal/HashCode.java | 15 ++-
.../main/java/org/apache/juneau/utils/Tuple2.java | 73 +++++++++---
.../org/apache/juneau/utils/Tuple2Function.java | 39 ++++---
.../main/java/org/apache/juneau/utils/Tuple3.java | 88 +++++++++++---
.../org/apache/juneau/utils/Tuple3Function.java | 40 ++++---
.../main/java/org/apache/juneau/utils/Tuple4.java | 111 ++++++++++++++++++
.../org/apache/juneau/utils/Tuple4Function.java | 41 ++++---
.../main/java/org/apache/juneau/utils/Tuple5.java | 126 +++++++++++++++++++++
.../org/apache/juneau/utils/Tuple5Function.java | 42 ++++---
juneau-doc/docs/ReleaseNotes/8.1.4.html | 2 +
.../Topics/06.juneau-rest-server/22.Messages.html | 100 +++++++++++-----
.../rest/annotation/RestResourceMessagesTest.java | 70 ------------
.../juneau/rest/annotation/Rest_Messages_Test.java | 126 +++++++++++++++++++++
...ourceMessagesTest1.properties => A1.properties} | 2 +-
...ourceMessagesTest2.properties => A2.properties} | 2 +-
...urceMessagesTest1.properties => B1x.properties} | 2 +-
...urceMessagesTest2.properties => B2x.properties} | 2 +-
.../java/org/apache/juneau/rest/RestContext.java | 66 ++++++-----
.../org/apache/juneau/rest/RestContextBuilder.java | 27 +----
.../java/org/apache/juneau/rest/RestRequest.java | 5 +-
.../juneau/rest/annotation/RestConfigApply.java | 4 +-
.../rest/annotation/RestResourceConfigApply.java | 2 +-
31 files changed, 1040 insertions(+), 545 deletions(-)
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2Function_Test.java
similarity index 69%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2Function_Test.java
index df16803..345723b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2Function_Test.java
@@ -1,40 +1,31 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple2Function_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple2Function<Integer,Integer,Integer> x = (a,b)->a+b;
+ assertInteger(x.apply(1,2)).is(3);
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2_Test.java
similarity index 57%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2_Test.java
index df16803..ff3878a 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple2_Test.java
@@ -1,40 +1,44 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple2_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple2<String,Integer> x = Tuple2.of("foo",1);
+ assertString(x.getA()).is("foo");
+ assertInteger(x.getB()).is(1);
+ }
+
+ @Test
+ public void a02_equality() throws Exception {
+ Tuple2<String,Integer> x1 = Tuple2.of("foo",1), x2 =
Tuple2.of("foo",1), x3 = Tuple2.of(null,1), x4 = Tuple2.of("foo",null);
+ assertTrue(x1.equals(x2));
+ assertEquals(x1.hashCode(), x2.hashCode());
+ assertFalse(x1.equals(x3));
+ assertNotEquals(x1.hashCode(), x3.hashCode());
+ assertFalse(x1.equals(x4));
+ assertNotEquals(x1.hashCode(), x4.hashCode());
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3Function_Test.java
similarity index 69%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3Function_Test.java
index df16803..7e06aca 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3Function_Test.java
@@ -1,40 +1,31 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple3Function_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple3Function<Integer,Integer,Integer,Integer> x =
(a,b,c)->a+b+c;
+ assertInteger(x.apply(1,2,3)).is(6);
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3_Test.java
similarity index 53%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3_Test.java
index df16803..dc8ce43 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple3_Test.java
@@ -1,40 +1,47 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple3_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple3<String,Integer,Integer> x = Tuple3.of("foo",1,2);
+ assertString(x.getA()).is("foo");
+ assertInteger(x.getB()).is(1);
+ assertInteger(x.getC()).is(2);
+ }
+
+ @Test
+ public void a02_equality() throws Exception {
+ Tuple3<String,Integer,Integer> x1 = Tuple3.of("foo",1,2), x2 =
Tuple3.of("foo",1,2), x3 = Tuple3.of(null,1,2), x4 = Tuple3.of("foo",null,2),
x5 = Tuple3.of("foo",1,null);
+ assertTrue(x1.equals(x2));
+ assertEquals(x1.hashCode(), x2.hashCode());
+ assertFalse(x1.equals(x3));
+ assertNotEquals(x1.hashCode(), x3.hashCode());
+ assertFalse(x1.equals(x4));
+ assertNotEquals(x1.hashCode(), x4.hashCode());
+ assertFalse(x1.equals(x5));
+ assertNotEquals(x1.hashCode(), x5.hashCode());
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4Function_Test.java
similarity index 69%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4Function_Test.java
index df16803..81e203d 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4Function_Test.java
@@ -1,40 +1,31 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple4Function_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple4Function<Integer,Integer,Integer,Integer,Integer> x =
(a,b,c,d)->a+b+c+d;
+ assertInteger(x.apply(1,2,3,4)).is(10);
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4_Test.java
similarity index 50%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4_Test.java
index df16803..227e1dd 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple4_Test.java
@@ -1,40 +1,50 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple4_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple4<String,Integer,Integer,Integer> x =
Tuple4.of("foo",1,2,3);
+ assertString(x.getA()).is("foo");
+ assertInteger(x.getB()).is(1);
+ assertInteger(x.getC()).is(2);
+ assertInteger(x.getD()).is(3);
+ }
+
+ @Test
+ public void a02_equality() throws Exception {
+ Tuple4<String,Integer,Integer,Integer> x1 =
Tuple4.of("foo",1,2,3), x2 = Tuple4.of("foo",1,2,3), x3 =
Tuple4.of(null,1,2,3), x4 = Tuple4.of("foo",null,2,3), x5 =
Tuple4.of("foo",1,null,3), x6 = Tuple4.of("foo",1,2,null);
+ assertTrue(x1.equals(x2));
+ assertEquals(x1.hashCode(), x2.hashCode());
+ assertFalse(x1.equals(x3));
+ assertNotEquals(x1.hashCode(), x3.hashCode());
+ assertFalse(x1.equals(x4));
+ assertNotEquals(x1.hashCode(), x4.hashCode());
+ assertFalse(x1.equals(x5));
+ assertNotEquals(x1.hashCode(), x5.hashCode());
+ assertFalse(x1.equals(x6));
+ assertNotEquals(x1.hashCode(), x6.hashCode());
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5Function_Test.java
similarity index 68%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5Function_Test.java
index df16803..e709d39 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5Function_Test.java
@@ -1,40 +1,31 @@
-//
***************************************************************************************************************************
-// * 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.rest;
-
-/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
- */
-public class MessageBundleLocation {
-
- final Class<?> baseClass;
- final String bundlePath;
-
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
- }
-}
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple5Function_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple5Function<Integer,Integer,Integer,Integer,Integer,Integer>
x = (a,b,c,d,e)->a+b+c+d+e;
+ assertInteger(x.apply(1,2,3,4,5)).is(15);
+ }
+}
diff --git
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5_Test.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5_Test.java
new file mode 100644
index 0000000..5801e86
--- /dev/null
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/utils/Tuple5_Test.java
@@ -0,0 +1,53 @@
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Tuple5_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests.
+
//------------------------------------------------------------------------------------------------------------------
+ @Test
+ public void a01_basic() throws Exception {
+ Tuple5<String,Integer,Integer,Integer,Integer> x =
Tuple5.of("foo",1,2,3,4);
+ assertString(x.getA()).is("foo");
+ assertInteger(x.getB()).is(1);
+ assertInteger(x.getC()).is(2);
+ assertInteger(x.getD()).is(3);
+ assertInteger(x.getE()).is(4);
+ }
+
+ @Test
+ public void a02_equality() throws Exception {
+ Tuple5<String,Integer,Integer,Integer,Integer> x1 =
Tuple5.of("foo",1,2,3,4), x2 = Tuple5.of("foo",1,2,3,4), x3 =
Tuple5.of(null,1,2,3,4), x4 = Tuple5.of("foo",null,2,3,4), x5 =
Tuple5.of("foo",1,null,3,4), x6 = Tuple5.of("foo",1,2,null,4), x7 =
Tuple5.of("foo",1,2,3,null);
+ assertTrue(x1.equals(x2));
+ assertEquals(x1.hashCode(), x2.hashCode());
+ assertFalse(x1.equals(x3));
+ assertNotEquals(x1.hashCode(), x3.hashCode());
+ assertFalse(x1.equals(x4));
+ assertNotEquals(x1.hashCode(), x4.hashCode());
+ assertFalse(x1.equals(x5));
+ assertNotEquals(x1.hashCode(), x5.hashCode());
+ assertFalse(x1.equals(x6));
+ assertNotEquals(x1.hashCode(), x6.hashCode());
+ assertFalse(x1.equals(x7));
+ assertNotEquals(x1.hashCode(), x7.hashCode());
+ }
+}
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 7a318a0..8c9dea1 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
@@ -430,7 +430,7 @@ public final class BeanPropertyMeta {
this.canWrite = b.canWrite;
this.readOnly = b.readOnly;
this.writeOnly = b.writeOnly;
- this.hashCode =
HashCode.create().add(beanMeta.hashCode()).add(name == null ? 0 :
name.hashCode()).get();
+ this.hashCode = HashCode.of(beanMeta,name);
}
/**
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HashCode.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HashCode.java
index 1e83c40..d298556 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HashCode.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/HashCode.java
@@ -35,6 +35,19 @@ public class HashCode {
}
/**
+ * Calculates a hash code over the specified objects.
+ *
+ * @param objects The objects to calculate a hashcode over.
+ * @return A numerical hashcode value.
+ */
+ public static final int of(Object...objects) {
+ HashCode x = create();
+ for (Object oo : objects)
+ x.add(oo);
+ return x.get();
+ }
+
+ /**
* Hashes the hashcode of the specified object into this object.
*
* @param o The object whose hashcode will be hashed with this object.
@@ -42,7 +55,7 @@ public class HashCode {
*/
public HashCode add(Object o) {
o = unswap(o);
- add(o == null ? 1 : o.hashCode());
+ add(o == null ? 0 : o.hashCode());
return this;
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2.java
similarity index 57%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2.java
index df16803..08e6b30 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2.java
@@ -10,31 +10,72 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import org.apache.juneau.internal.*;
/**
- * Message bundle location.
- *
- * <p>
- * Identifies a message bundle by a base class and bundle path.
+ * Represents a simple tuple of 2 objects.
*
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
*/
-public class MessageBundleLocation {
+public class Tuple2<A,B> {
- final Class<?> baseClass;
- final String bundlePath;
+ /**
+ * Creator.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param a Object 1.
+ * @param b Object 2.
+ * @return A new tuple object.
+ */
+ public static <A,B> Tuple2<A,B> of(A a, B b) {
+ return new Tuple2<>(a,b);
+ }
+
+ private final A a;
+ private final B b;
/**
* Constructor.
*
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
+ * @param a Object 1.
+ * @param b Object 2.
+ */
+ public Tuple2(A a, B b) {
+ this.a = a;
+ this.b = b;
+ }
+
+ /**
+ * Returns the first object in this tuple.
+ *
+ * @return The first object in this tuple.
*/
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ public A getA() {
+ return a;
+ }
+
+ /**
+ * Returns the second object in this tuple.
+ *
+ * @return The second object in this tuple.
+ */
+ public B getB() {
+ return b;
+ }
+
+ @Override /* Object */
+ public int hashCode() {
+ return HashCode.of(a,b);
+ }
+
+ @Override /* Object */
+ public boolean equals(Object o) {
+ return o instanceof Tuple2 && eq(this, (Tuple2<?,?>)o,
(x,y)->eq(x.a,y.a) && eq(x.b,y.b));
}
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2Function.java
similarity index 67%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2Function.java
index df16803..21a6786 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple2Function.java
@@ -10,31 +10,34 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import java.util.function.*;
/**
- * Message bundle location.
+ * Allows you to perform a function against 2 objects.
*
* <p>
- * Identifies a message bundle by a base class and bundle path.
+ * Same as {@link BiFunction}.
+ *
+ * <p class='bcode w800'>
+ * Tuple2Function<A,B,R> <jv>x</jv> = (<jv>a</jv>,<jv>b</jv>) ->
<jsm>doSomething</jsm>(<jv>a</jv>,<jv>b</jv>);
+ *
+ * R <jv>result</jv> = <jv>x</jv>.apply(<jv>xa</jv>,<jv>xb</jv>);
+ * </p>
*
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <R> Result type.
*/
-public class MessageBundleLocation {
+@FunctionalInterface
+public interface Tuple2Function<A,B,R> {
- final Class<?> baseClass;
- final String bundlePath;
+ @SuppressWarnings("javadoc")
+ R apply(A a, B b);
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ @SuppressWarnings("javadoc")
+ default <V> Tuple2Function<A,B,V> andThen(Function<? super R, ? extends
V> after) {
+ return (A a, B b) -> after.apply(apply(a, b));
}
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3.java
similarity index 51%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3.java
index df16803..110d565 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3.java
@@ -10,31 +10,87 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import org.apache.juneau.internal.*;
/**
- * Message bundle location.
+ * Represents a simple tuple of 3 objects.
*
- * <p>
- * Identifies a message bundle by a base class and bundle path.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
*/
-public class MessageBundleLocation {
+public class Tuple3<A,B,C> {
+
+ /**
+ * Creator.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
+ * @return A new tuple object.
+ */
+ public static <A,B,C> Tuple3<A,B,C> of(A a, B b, C c) {
+ return new Tuple3<>(a,b,c);
+ }
- final Class<?> baseClass;
- final String bundlePath;
+ private final A a;
+ private final B b;
+ private final C c;
/**
* Constructor.
*
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
*/
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ public Tuple3(A a, B b, C c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ /**
+ * Returns the first object in this tuple.
+ *
+ * @return The first object in this tuple.
+ */
+ public A getA() {
+ return a;
+ }
+
+ /**
+ * Returns the second object in this tuple.
+ *
+ * @return The second object in this tuple.
+ */
+ public B getB() {
+ return b;
+ }
+
+ /**
+ * Returns the third object in this tuple.
+ *
+ * @return The third object in this tuple.
+ */
+ public C getC() {
+ return c;
+ }
+
+ @Override /* Object */
+ public int hashCode() {
+ return HashCode.of(a,b,c);
+ }
+
+ @Override /* Object */
+ public boolean equals(Object o) {
+ return o instanceof Tuple3 && eq(this, (Tuple3<?,?,?>)o,
(x,y)->eq(x.a,y.a) && eq(x.b,y.b) && eq(x.c,y.c));
}
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3Function.java
similarity index 64%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3Function.java
index df16803..9ec8b59 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple3Function.java
@@ -10,31 +10,35 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import java.util.function.*;
/**
- * Message bundle location.
+ * Allows you to perform a function against 3 objects.
*
* <p>
- * Identifies a message bundle by a base class and bundle path.
+ * Similar to {@link BiFunction} except for 3 parameters.
+ *
+ * <p class='bcode w800'>
+ * Tuple3Function<A,B,C,R> <jv>x</jv> =
(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>) ->
<jsm>doSomething</jsm>(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>);
+ *
+ * R <jv>result</jv> =
<jv>x</jv>.apply(<jv>xa</jv>,<jv>xb</jv>,<jv>xc</jv>);
+ * </p>
*
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <R> Result type.
*/
-public class MessageBundleLocation {
+@FunctionalInterface
+public interface Tuple3Function<A,B,C,R> {
- final Class<?> baseClass;
- final String bundlePath;
+ @SuppressWarnings("javadoc")
+ R apply(A a, B b, C c);
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ @SuppressWarnings("javadoc")
+ default <V> Tuple3Function<A,B,C,V> andThen(Function<? super R, ?
extends V> after) {
+ return (A a, B b, C c) -> after.apply(apply(a, b, c));
}
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4.java
new file mode 100644
index 0000000..920bf2f
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4.java
@@ -0,0 +1,111 @@
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents a simple tuple of 4 objects.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ */
+public class Tuple4<A,B,C,D> {
+
+ /**
+ * Creator.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
+ * @param d Object 4.
+ * @return A new tuple object.
+ */
+ public static <A,B,C,D> Tuple4<A,B,C,D> of(A a, B b, C c, D d) {
+ return new Tuple4<>(a,b,c,d);
+ }
+
+ private final A a;
+ private final B b;
+ private final C c;
+ private final D d;
+
+ /**
+ * Constructor.
+ *
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
+ * @param d Object 4.
+ */
+ public Tuple4(A a, B b, C c, D d) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ }
+
+ /**
+ * Returns the first object in this tuple.
+ *
+ * @return The first object in this tuple.
+ */
+ public A getA() {
+ return a;
+ }
+
+ /**
+ * Returns the second object in this tuple.
+ *
+ * @return The second object in this tuple.
+ */
+ public B getB() {
+ return b;
+ }
+
+ /**
+ * Returns the third object in this tuple.
+ *
+ * @return The third object in this tuple.
+ */
+ public C getC() {
+ return c;
+ }
+
+ /**
+ * Returns the fourth object in this tuple.
+ *
+ * @return The fourth object in this tuple.
+ */
+ public D getD() {
+ return d;
+ }
+
+ @Override /* Object */
+ public int hashCode() {
+ return HashCode.of(a,b,c,d);
+ }
+
+ @Override /* Object */
+ public boolean equals(Object o) {
+ return o instanceof Tuple4 && eq(this, (Tuple4<?,?,?,?>)o,
(x,y)->eq(x.a,y.a) && eq(x.b,y.b) && eq(x.c,y.c) && eq(x.d,y.d));
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4Function.java
similarity index 62%
copy from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
copy to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4Function.java
index df16803..e641ad1 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple4Function.java
@@ -10,31 +10,36 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import java.util.function.*;
/**
- * Message bundle location.
+ * Allows you to perform a function against 4 objects.
*
* <p>
- * Identifies a message bundle by a base class and bundle path.
+ * Similar to {@link BiFunction} except for 4 parameters.
+ *
+ * <p class='bcode w800'>
+ * Tuple4Function<A,B,C,D,R> <jv>x</jv> =
(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>,<jv>d</jv>) ->
<jsm>doSomething</jsm>(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>,<jv>d</jv>);
+ *
+ * R <jv>result</jv> =
<jv>x</jv>.apply(<jv>xa</jv>,<jv>xb</jv>,<jv>xc</jv>,<jv>xd</jv>);
+ * </p>
*
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ * @param <R> Result type.
*/
-public class MessageBundleLocation {
+@FunctionalInterface
+public interface Tuple4Function<A,B,C,D,R> {
- final Class<?> baseClass;
- final String bundlePath;
+ @SuppressWarnings("javadoc")
+ R apply(A a, B b, C c, D d);
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ @SuppressWarnings("javadoc")
+ default <V> Tuple4Function<A,B,C,D,V> andThen(Function<? super R, ?
extends V> after) {
+ return (A a, B b, C c, D d) -> after.apply(apply(a, b, c, d));
}
}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5.java
new file mode 100644
index 0000000..f5528f0
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5.java
@@ -0,0 +1,126 @@
+//
***************************************************************************************************************************
+// * 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.utils;
+
+import static org.apache.juneau.internal.ObjectUtils.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Represents a simple tuple of 5 objects.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ * @param <E> Object 5 type.
+ */
+public class Tuple5<A,B,C,D,E> {
+
+ /**
+ * Creator.
+ *
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ * @param <E> Object 5 type.
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
+ * @param d Object 4.
+ * @param e Object 5.
+ * @return A new tuple object.
+ */
+ public static <A,B,C,D,E> Tuple5<A,B,C,D,E> of(A a, B b, C c, D d, E e)
{
+ return new Tuple5<>(a,b,c,d, e);
+ }
+
+ private final A a;
+ private final B b;
+ private final C c;
+ private final D d;
+ private final E e;
+
+ /**
+ * Constructor.
+ *
+ * @param a Object 1.
+ * @param b Object 2.
+ * @param c Object 3.
+ * @param d Object 4.
+ * @param e Object 5.
+ */
+ public Tuple5(A a, B b, C c, D d, E e) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ this.d = d;
+ this.e = e;
+ }
+
+ /**
+ * Returns the first object in this tuple.
+ *
+ * @return The first object in this tuple.
+ */
+ public A getA() {
+ return a;
+ }
+
+ /**
+ * Returns the second object in this tuple.
+ *
+ * @return The second object in this tuple.
+ */
+ public B getB() {
+ return b;
+ }
+
+ /**
+ * Returns the third object in this tuple.
+ *
+ * @return The third object in this tuple.
+ */
+ public C getC() {
+ return c;
+ }
+
+ /**
+ * Returns the fourth object in this tuple.
+ *
+ * @return The fourth object in this tuple.
+ */
+ public D getD() {
+ return d;
+ }
+
+ /**
+ * Returns the fifth object in this tuple.
+ *
+ * @return The fifth object in this tuple.
+ */
+ public E getE() {
+ return e;
+ }
+
+ @Override /* Object */
+ public int hashCode() {
+ return HashCode.of(a,b,c,d,e);
+ }
+
+ @Override /* Object */
+ public boolean equals(Object o) {
+ return o instanceof Tuple5 && eq(this, (Tuple5<?,?,?,?,?>)o,
(x,y)->eq(x.a,y.a) && eq(x.b,y.b) && eq(x.c,y.c) && eq(x.d,y.d) && eq(x.e,y.e));
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5Function.java
similarity index 60%
rename from
juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
rename to
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5Function.java
index df16803..7def989 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/MessageBundleLocation.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/Tuple5Function.java
@@ -10,31 +10,37 @@
// * "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.rest;
+package org.apache.juneau.utils;
+
+import java.util.function.*;
/**
- * Message bundle location.
+ * Allows you to perform a function against 5 objects.
*
* <p>
- * Identifies a message bundle by a base class and bundle path.
+ * Similar to {@link BiFunction} except for 5 parameters.
+ *
+ * <p class='bcode w800'>
+ * Tuple5Function<A,B,C,D,E,R> <jv>x</jv> =
(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>,<jv>d</jv>,<jv>e</jv>) ->
<jsm>doSomething</jsm>(<jv>a</jv>,<jv>b</jv>,<jv>c</jv>,<jv>d</jv>,<jv>e</jv>);
+ *
+ * R <jv>result</jv> =
<jv>x</jv>.apply(<jv>xa</jv>,<jv>xb</jv>,<jv>xc</jv>,<jv>xd</jv>,<jv>xe</jv>);
+ * </p>
*
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-rest-server.Messages}
- * </ul>
+ * @param <A> Object 1 type.
+ * @param <B> Object 2 type.
+ * @param <C> Object 3 type.
+ * @param <D> Object 4 type.
+ * @param <E> Object 5 type.
+ * @param <R> Result type.
*/
-public class MessageBundleLocation {
+@FunctionalInterface
+public interface Tuple5Function<A,B,C,D,E,R> {
- final Class<?> baseClass;
- final String bundlePath;
+ @SuppressWarnings("javadoc")
+ R apply(A a, B b, C c, D d, E e);
- /**
- * Constructor.
- *
- * @param baseClass The base class that the bundle path is relative to.
- * @param bundlePath The bundle path relative to the base class.
- */
- public MessageBundleLocation(Class<?> baseClass, String bundlePath) {
- this.baseClass = baseClass;
- this.bundlePath = bundlePath;
+ @SuppressWarnings("javadoc")
+ default <V> Tuple5Function<A,B,C,D,E,V> andThen(Function<? super R, ?
extends V> after) {
+ return (A a, B b, C c, D d, E e) -> after.apply(apply(a, b, c,
d, e));
}
}
diff --git a/juneau-doc/docs/ReleaseNotes/8.1.4.html
b/juneau-doc/docs/ReleaseNotes/8.1.4.html
index cc72ad5..d0ac1a9 100644
--- a/juneau-doc/docs/ReleaseNotes/8.1.4.html
+++ b/juneau-doc/docs/ReleaseNotes/8.1.4.html
@@ -446,6 +446,8 @@
String getFoo(); <jc>// @RestMethod(name=GET,path="/foo") is
implied.</jc>
}
</p>
+ <li>
+ Improved {@link oajr.annotation.RestMethod#REST_messages
REST_messages} support (mostly bug fixes).
</ul>
<h5 class='topic w800'>juneau-rest-server-springboot</h5>
diff --git a/juneau-doc/docs/Topics/06.juneau-rest-server/22.Messages.html
b/juneau-doc/docs/Topics/06.juneau-rest-server/22.Messages.html
index bd2898a..cf3c215 100644
--- a/juneau-doc/docs/Topics/06.juneau-rest-server/22.Messages.html
+++ b/juneau-doc/docs/Topics/06.juneau-rest-server/22.Messages.html
@@ -13,49 +13,97 @@
***************************************************************************************************************************/
-->
+{8.1.4-updated}
Messages
<p>
- The {@link oajr.annotation.Rest#messages @Rest(messages)} annotation is
used to associate a resource bundle with a servlet class.
+ The {@link oajr.annotation.Rest#messages @Rest(messages)} annotation
identifies the location of the resource bundle
+ for a <ja>@Rest</ja>-annotated class if it's different from the class
name.
</p>
-<p class='bpcode w800'>
- <jc>// Servlet with associated resource bundle</jc>
- <ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
- <jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet {
-
- <jc>// Returns the localized greeting from the "greeting" key
in MyMessages.properties</jc>
- <ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/"</js>)
- <jk>public</jk> String printLocalizedGreeting(RestRequest req) {
- <jk>return</jk> req.getMessage(<js>"greeting"</js>);
- }
+<p>
+ By default, the resource bundle name is assumed to match the class
name. For example, given the class
+ <c>MyClass.java</c>, the resource bundle is assumed to be
<c>MyClass.properties</c>. This property
+ allows you to override this setting to specify a different location
such as <c>MyMessages.properties</c> by
+ specifying a value of <js>"MyMessages"</js>.
</p>
-<p>
- The resource bundle can also be passed into the method by simply
specifying a parameter
- of type {@link java.util.ResourceBundle} or {@link
oaj.utils.MessageBundle}:
+<p>
+Resource bundles are searched using the following base name patterns:
</p>
-<p class='bpcode w800'>
- <ja>@RestMethod</ja>(name=<jsf>GET</jsf>)
- <jk>public</jk> String printLocalizedGreeting(MessageBundle messages) {
- <jk>return</jk> messages.getString(<js>"greeting"</js>);
- }
+<ul>
+ <li><js>"{package}.{name}"</js>
+ <li><js>"{package}.i18n.{name}"</js>
+ <li><js>"{package}.nls.{name}"</js>
+ <li><js>"{package}.messages.{name}"</js>
+</ul>
+
+<p>
+ This annotation is used to provide request-localized (based on
<c>Accept-Language</c>) messages for the following methods:
+</p>
+<ul class='javatree'>
+ <li class='jm'>{@link RestRequest#getMessage(String, Object...)}
+ <li class='jm'>{@link RestContext#getMessages()
RestContext.getMessages()}
+</ul>
+
+<p>
+ Request-localized messages are also available by passing either of the
following parameter types into your Java method:
</p>
+<ul class='javatree'>
+ <li class='jc'>{@link ResourceBundle} - Basic Java resource bundle.
+ <li class='jc'>{@link Messages} - Extended resource bundle with several
convenience methods.
+</ul>
<p>
- If a resource bundle is shared by multiple servlets, the label and
description can be prefixed by the class
- name:
+ The value can be a relative path like <js>"nls/Messages"</js>,
indicating to look for the resource bundle
+ <js>"com.foo.sample.nls.Messages"</js> if the resource class is in
<js>"com.foo.sample"</js>, or it can be an
+ absolute path like <js>"com.foo.sample.nls.Messages"</js>
</p>
+
+<h5 class='figure'>Examples:</h5>
<p class='bpcode w800'>
<cc>#--------------------------------------------------------------------------------
- # Contents of MyMessages.properties
+ # Contents of org/apache/foo/nls/MyMessages.properties
#--------------------------------------------------------------------------------</cc>
- <ck>greeting</ck> = Hello!
-</p>
+ <ck>HelloMessage</ck> = <cv>Hello {0}!</cv>
+</p>
+<p class='bpcode w800'>
+ <jc>// Contents of org/apache/foo/MyResource.java</jc>
+
+ <ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
+ <jk>public class</jk> MyResource {...}
+
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>,
path=<js>"/hello/{you}"</js>)
+ <jk>public</jk> Object helloYou(RestRequest <jv>req</jv>,
Messages <jv>messages</jv>, <ja>@Path</ja>(<js>"name"</js>) String
<jv>you</jv>) {
+ String <jv>s</jv>;
+
+ <jc>// Get it from the RestRequest object.</jc>
+ <jv>s</jv> =
<jv>req</jv>.getMessage(<js>"HelloMessage"</js>, <jv>you</jv>);
+
+ <jc>// Or get it from the method parameter.</jc>
+ <jv>s</jv> =
<jv>messages</jv>.getString(<js>"HelloMessage"</js>, <jv>you</jv>);
+
+ <jc>// Or get the message in a locale different from
the request.</jc>
+ <jv>s</jv> =
<jv>messages</jv>.forLocale(Locale.<jsf>UK</jsf>).getString(<js>"HelloMessage"</js>,
<jv>you</jv>);
+
+ <jk>return</jk> <jv>s</jv>;
+ }
+ }
+</p>
+<p>
+ When using shared resource bundles, keys can be prefixed by class names
like so and still retrieve by simple
+ key names:
+</p>
<p class='bpcode w800'>
<cc>#--------------------------------------------------------------------------------
- # Contents of shared MyMessages.properties
+ # Contents of shared org/apache/foo/nls/MyMessages.properties
#--------------------------------------------------------------------------------</cc>
- <ck>MyRestServlet.greeting</ck> = Hello!
+ <ck>MyResource.HelloMessage</ck> = <cv>Hello {0}!</cv>
+</p>
+
+<p>
+ Messages are automatically inherited from super classes. If a string
cannot be found in the bundle of the current
+ class, it will be searched for up the class hierarchy.
</p>
<ul class='seealso'>
+ <li class='jc'>{@link oaj.cp.Messages}
<li class='jf'>{@link oajr.RestContext#REST_messages}
</ul>
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
deleted file mode 100644
index 2807fcc..0000000
---
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-//
***************************************************************************************************************************
-// * 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.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.collections.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class RestResourceMessagesTest {
-
-
//====================================================================================================
- // Setup
-
//====================================================================================================
-
- static OMap convertToMap(ResourceBundle rb) {
- OMap m = new OMap();
- for (String k : new TreeSet<>(rb.keySet()))
- m.put(k, rb.getString(k));
- return m;
- }
-
-
//====================================================================================================
- // Basic tests
-
//====================================================================================================
-
- @Rest(messages="RestResourceMessagesTest1")
- public static class A {
- @RestMethod
- public OMap a01(ResourceBundle rb) {
- return convertToMap(rb);
- }
- }
- static MockRestClient a = MockRestClient.build(A.class);
-
- @Test
- public void a01() throws Exception {
- // Parent resource should just pick up values from its bundle.
-
a.get("/a01").run().assertBody().is("{key1:'value1a',key2:'value2a'}");
- }
-
-
//====================================================================================================
- // Overridden on subclass.
-
//====================================================================================================
-
- @Rest(messages="RestResourceMessagesTest2")
- public static class B extends A {}
- static MockRestClient b = MockRestClient.build(B.class);
-
- @Test
- public void b01() throws Exception {
- // Child resource should pick up values from both parent and
child,
- // ordered child before parent.
-
b.get("/a01").run().assertBody().is("{key1:'value1a',key2:'value2b',key3:'value3b'}");
- }
-}
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
new file mode 100644
index 0000000..2157af2
--- /dev/null
+++
b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
@@ -0,0 +1,126 @@
+//
***************************************************************************************************************************
+// * 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.rest.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Rest_Messages_Test {
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Basic tests
+
//------------------------------------------------------------------------------------------------------------------
+
+ @Rest
+ public static class A1 {
+ @RestMethod
+ public OMap a(ResourceBundle rb) {
+ return asMap(rb);
+ }
+ @RestMethod
+ public OMap b(Messages m) {
+ return asMap(m);
+ }
+ @RestMethod
+ public String c(Messages m, @Query("name") String name) {
+ return m.getString(name);
+ }
+ }
+ static MockRestClient a1 = MockRestClient.build(A1.class);
+
+ @Test
+ public void a01_default() throws Exception {
+
a1.get("/a").run().assertBody().is("{'A1.key2':'A1.value2a',key1:'value1a',key2:'A1.value2a'}");
+
a1.get("/b").run().assertBody().is("{'A1.key2':'A1.value2a',key1:'value1a',key2:'A1.value2a'}");
+ a1.get("/c?name=key1").run().assertBody().is("value1a");
+ a1.get("/c?name=key2").run().assertBody().is("A1.value2a");
+ a1.get("/c?name=key3").run().assertBody().is("{!key3}");
+ }
+
+ @Rest
+ public static class A2 extends A1 {}
+ static MockRestClient a2 = MockRestClient.build(A2.class);
+
+ @Test
+ public void a02_subclassed() throws Exception {
+
a2.get("/a").run().assertBody().is("{'A1.key2':'A1.value2a','A2.key3':'A2.value3b',key1:'value1a',key2:'value2b',key3:'A2.value3b'}");
+
a2.get("/b").run().assertBody().is("{'A1.key2':'A1.value2a','A2.key3':'A2.value3b',key1:'value1a',key2:'value2b',key3:'A2.value3b'}");
+ a2.get("/c?name=key1").run().assertBody().is("value1a");
+ a2.get("/c?name=key2").run().assertBody().is("value2b");
+ a2.get("/c?name=key3").run().assertBody().is("A2.value3b");
+ a2.get("/c?name=key4").run().assertBody().is("{!key4}");
+ }
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Overridden on subclass.
+
//------------------------------------------------------------------------------------------------------------------
+
+ @Rest(messages="B1x")
+ public static class B1 {
+ @RestMethod
+ public OMap a(ResourceBundle rb) {
+ return asMap(rb);
+ }
+ @RestMethod
+ public OMap b(Messages m) {
+ return asMap(m);
+ }
+ @RestMethod
+ public String c(Messages m, @Query("name") String name) {
+ return m.getString(name);
+ }
+ }
+ static MockRestClient b1 = MockRestClient.build(B1.class);
+
+ @Test
+ public void b01_customName() throws Exception {
+
b1.get("/a").run().assertBody().is("{'B1.key2':'B1.value2a',key1:'value1a',key2:'B1.value2a'}");
+
b1.get("/b").run().assertBody().is("{'B1.key2':'B1.value2a',key1:'value1a',key2:'B1.value2a'}");
+ b1.get("/c?name=key1").run().assertBody().is("value1a");
+ b1.get("/c?name=key2").run().assertBody().is("B1.value2a");
+ b1.get("/c?name=key3").run().assertBody().is("{!key3}");
+ }
+
+ @Rest(messages="B2x")
+ public static class B2 extends B1 {}
+ static MockRestClient b2 = MockRestClient.build(B2.class);
+
+ @Test
+ public void b02_subclassed_customName() throws Exception {
+
b2.get("/a").run().assertBody().stderr().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b',key3:'B2.value3b'}");
+
b2.get("/b").run().assertBody().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b',key3:'B2.value3b'}");
+ b2.get("/c?name=key1").run().assertBody().is("value1a");
+ b2.get("/c?name=key2").run().assertBody().is("value2b");
+ b2.get("/c?name=key3").run().assertBody().is("B2.value3b");
+ b2.get("/c?name=key4").run().assertBody().is("{!key4}");
+ }
+
+
//------------------------------------------------------------------------------------------------------------------
+ // Helper methods.
+
//------------------------------------------------------------------------------------------------------------------
+
+ private static OMap asMap(ResourceBundle rb) {
+ OMap m = new OMap();
+ for (String k : new TreeSet<>(rb.keySet()))
+ m.put(k, rb.getString(k));
+ return m;
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A1.properties
similarity index 97%
copy from
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
copy to
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A1.properties
index d107ee8..f8077ed 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
+++
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A1.properties
@@ -13,4 +13,4 @@
#
***************************************************************************************************************************
key1 = value1a
-key2 = value2a
\ No newline at end of file
+A1.key2 = A1.value2a
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A2.properties
similarity index 97%
copy from
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
copy to
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A2.properties
index 9a5fe73..505513c 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
+++
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/A2.properties
@@ -13,4 +13,4 @@
#
***************************************************************************************************************************
key2 = value2b
-key3 = value3b
\ No newline at end of file
+A2.key3 = A2.value3b
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B1x.properties
similarity index 97%
rename from
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
rename to
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B1x.properties
index d107ee8..a4b7aae 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest1.properties
+++
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B1x.properties
@@ -13,4 +13,4 @@
#
***************************************************************************************************************************
key1 = value1a
-key2 = value2a
\ No newline at end of file
+B1.key2 = B1.value2a
diff --git
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B2x.properties
similarity index 97%
rename from
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
rename to
juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B2x.properties
index 9a5fe73..12b31a1 100644
---
a/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/RestResourceMessagesTest2.properties
+++
b/juneau-rest/juneau-rest-server-utest/src/test/resources/org/apache/juneau/rest/annotation/B2x.properties
@@ -13,4 +13,4 @@
#
***************************************************************************************************************************
key2 = value2b
-key3 = value3b
\ No newline at end of file
+B2.key3 = B2.value3b
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index fefad04..03312dd 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -14,6 +14,7 @@ package org.apache.juneau.rest;
import static javax.servlet.http.HttpServletResponse.*;
import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.apache.juneau.internal.ObjectUtils.*;
import static org.apache.juneau.internal.IOUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.rest.util.RestUtils.*;
@@ -1554,7 +1555,7 @@ public final class RestContext extends BeanContext {
* <ul class='spaced-list'>
* <li><b>ID:</b> {@link
org.apache.juneau.rest.RestContext#REST_messages REST_messages}
* <li><b>Name:</b> <js>"RestContext.messages.lo"</js>
- * <li><b>Data type:</b> <c>List<{@link
org.apache.juneau.rest.MessageBundleLocation}></c>
+ * <li><b>Data type:</b> <c>List<{@link
org.apache.juneau.utils.Tuple2}<Class,String>></c>
* <li><b>Default:</b> <jk>null</jk>
* <li><b>Session property:</b> <jk>false</jk>
* <li><b>Annotations:</b>
@@ -1564,59 +1565,72 @@ public final class RestContext extends BeanContext {
* <li><b>Methods:</b>
* <ul>
* <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#messages(String)},
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#messages(Class,String)}
- * <li class='jm'>{@link
org.apache.juneau.rest.RestContextBuilder#messages(MessageBundleLocation...)}
* </ul>
* </ul>
*
* <h5 class='section'>Description:</h5>
* <p>
- * Identifies the location of the resource bundle for this class.
+ * Identifies the location of the resource bundle for this class if
it's different from the class name.
*
* <p>
- * This annotation is used to provide localized messages for the
following methods:
+ * By default, the resource bundle name is assumed to match the class
name. For example, given the class
+ * <c>MyClass.java</c>, the resource bundle is assumed to be
<c>MyClass.properties</c>. This property
+ * allows you to override this setting to specify a different location
such as <c>MyMessages.properties</c> by
+ * specifying a value of <js>"MyMessages"</js>.
+ *
+ * <p>
+ * Resource bundles are searched using the following base name
patterns:
+ * <ul>
+ * <li><js>"{package}.{name}"</js>
+ * <li><js>"{package}.i18n.{name}"</js>
+ * <li><js>"{package}.nls.{name}"</js>
+ * <li><js>"{package}.messages.{name}"</js>
+ * </ul>
+ *
+ * <p>
+ * This annotation is used to provide request-localized (based on
<c>Accept-Language</c>) messages for the following methods:
* <ul class='javatree'>
* <li class='jm'>{@link RestRequest#getMessage(String, Object...)}
* <li class='jm'>{@link RestContext#getMessages()
RestContext.getMessages()}
* </ul>
*
* <p>
- * Messages are also available by passing either of the following
parameter types into your Java method:
+ * Request-localized messages are also available by passing either of
the following parameter types into your Java method:
* <ul class='javatree'>
* <li class='jc'>{@link ResourceBundle} - Basic Java resource
bundle.
* <li class='jc'>{@link Messages} - Extended resource bundle with
several convenience methods.
* </ul>
*
- * <p>
- * Messages passed into Java methods already have their locale set to
that of the incoming request.
- *
- * <p>
* The value can be a relative path like <js>"nls/Messages"</js>,
indicating to look for the resource bundle
* <js>"com.foo.sample.nls.Messages"</js> if the resource class is in
<js>"com.foo.sample"</js>, or it can be an
* absolute path like <js>"com.foo.sample.nls.Messages"</js>
*
* <h5 class='section'>Examples:</h5>
* <p class='bcode w800'>
- * <jk>package</jk> org.apache.foo;
+ * <cc># Contents of org/apache/foo/nls/MyMessages.properties</cc>
+ *
+ * <ck>HelloMessage</ck> = <cv>Hello {0}!</cv>
+ * </p>
+ * <p class='bcode w800'>
+ * <jc>// Contents of org/apache/foo/MyResource.java</jc>
*
- * <jc>// Resolve messages to
org/apache/foo/nls/MyMessages.properties</jc>
* <ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
* <jk>public class</jk> MyResource {...}
*
* <ja>@RestMethod</ja>(name=<js>"GET"</js>,
path=<js>"/hello/{you}"</js>)
- * <jk>public</jk> Object helloYou(RestRequest req,
MessageBundle messages, <ja>@Path</ja>(<js>"name"</js>) String you)) {
- * String s;
+ * <jk>public</jk> Object helloYou(RestRequest
<jv>req</jv>, Messages <jv>messages</jv>, <ja>@Path</ja>(<js>"name"</js>)
String <jv>you</jv>) {
+ * String <jv>s</jv>;
*
* <jc>// Get it from the RestRequest object.</jc>
- * s = req.getMessage(<js>"HelloMessage"</js>,
you);
+ * <jv>s</jv> =
<jv>req</jv>.getMessage(<js>"HelloMessage"</js>, <jv>you</jv>);
*
* <jc>// Or get it from the method parameter.</jc>
- * s = messages.getString(<js>"HelloMessage"</js>,
you);
+ * <jv>s</jv> =
<jv>messages</jv>.getString(<js>"HelloMessage"</js>, <jv>you</jv>);
*
* <jc>// Or get the message in a locale different
from the request.</jc>
- * s = messages.getString(Locale.<jsf>UK</jsf>,
<js>"HelloMessage"</js>, you);
+ * <jv>s</jv> =
<jv>messages</jv>.forLocale(Locale.<jsf>UK</jsf>).getString(<js>"HelloMessage"</js>,
<jv>you</jv>);
*
- * <jk>return</jk> s;
+ * <jk>return</jk> <jv>s</jv>;
* }
* }
* </p>
@@ -1627,6 +1641,7 @@ public final class RestContext extends BeanContext {
* </ul>
*
* <ul class='seealso'>
+ * <li class='jc'>{@link Messages}
* <li class='link'>{@doc juneau-rest-server.Messages}
* </ul>
*/
@@ -3849,16 +3864,11 @@ public final class RestContext extends BeanContext {
s.add(sf.getPath());
staticFilesPaths = s.toArray(new String[s.size()]);
- MessageBundleLocation[] mbl =
getInstanceArrayProperty(REST_messages, MessageBundleLocation.class, new
MessageBundleLocation[0]);
- if (mbl.length == 0)
- msgs = Messages.of(rci.inner());
- else {
- Messages msgs = null;
- for (int i = mbl.length-1; i >= 0; i--)
- if (mbl[i] != null)
- msgs =
Messages.create(mbl[i].baseClass == null ? rci.inner() :
mbl[i].baseClass).name(mbl[i].bundlePath).parent(msgs).build();
- this.msgs = msgs;
- }
+ Tuple2<Class<?>,String>[] mbl =
getInstanceArrayProperty(REST_messages, Tuple2.class, new Tuple2[0]);
+ Messages msgs = null;
+ for (int i = mbl.length-1; i >= 0; i--)
+ msgs =
Messages.create(firstNonNull(mbl[i].getA(),
rci.inner())).name(mbl[i].getB()).parent(msgs).build();
+ this.msgs = msgs;
this.fullPath = (builder.parentContext == null ? "" :
(builder.parentContext.fullPath + '/')) + builder.getPath();
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index 1f443f9..d3ea603 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -46,6 +46,7 @@ import org.apache.juneau.rest.widget.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.svl.*;
import org.apache.juneau.svl.vars.*;
+import org.apache.juneau.utils.*;
/**
* Defines the initial configuration of a <c>RestServlet</c> or <c>@Rest</c>
annotated object.
@@ -1218,28 +1219,6 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
/**
* <i><l>RestContext</l> configuration property: </i> Messages.
*
- * <p>
- * Identifies the location of the resource bundle for this class.
- *
- * <ul class='seealso'>
- * <li class='jf'>{@link RestContext#REST_messages}
- * </ul>
- *
- * @param values The values to add to this setting.
- * @return This object (for method chaining).
- */
- @FluentSetter
- public RestContextBuilder messages(MessageBundleLocation...values) {
- return prependTo(REST_messages, values);
- }
-
- /**
- * <i><l>RestContext</l> configuration property: </i> Messages.
- *
- * <p>
- * Same as {@link #messages(MessageBundleLocation...)} except allows
you to pass in the base class and bundle
- * path separately.
- *
* <ul class='seealso'>
* <li class='jf'>{@link RestContext#REST_messages}
* </ul>
@@ -1252,7 +1231,7 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
*/
@FluentSetter
public RestContextBuilder messages(Class<?> baseClass, String
bundlePath) {
- return prependTo(REST_messages, new
MessageBundleLocation(baseClass, bundlePath));
+ return prependTo(REST_messages, Tuple2.of(baseClass,
bundlePath));
}
/**
@@ -1270,7 +1249,7 @@ public class RestContextBuilder extends
BeanContextBuilder implements ServletCon
*/
@FluentSetter
public RestContextBuilder messages(String bundlePath) {
- return prependTo(REST_messages, new MessageBundleLocation(null,
bundlePath));
+ return prependTo(REST_messages, Tuple2.of(null, bundlePath));
}
/**
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 8c3990d..79ae60e 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
@@ -1226,11 +1226,8 @@ public final class RestRequest extends
HttpServletRequestWrapper {
* <ja>@RestMethod</ja>(...)
* <jk>public</jk> String sayHello(RestRequest req,
<ja>@Query</ja>(<js>"user"</js>) String user) {
*
- * <jc>// Get message bundle.</jc>
- * MessageBundle mb = req.getMessageBundle();
- *
* <jc>// Return a localized message.</jc>
- * <jk>return</jk> mb.getString(<js>"hello.message"</js>,
user);
+ * <jk>return</jk>
req.getMessages().getString(<js>"hello.message"</js>, user);
* }
* </p>
*
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestConfigApply.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestConfigApply.java
index 9b592a9..74c31a8 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestConfigApply.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestConfigApply.java
@@ -32,6 +32,7 @@ import org.apache.juneau.rest.annotation.AnnotationUtils;
import org.apache.juneau.rest.annotation.Logging;
import org.apache.juneau.rest.util.*;
import org.apache.juneau.svl.*;
+import org.apache.juneau.utils.*;
/**
* Applies {@link Rest} annotations to a {@link PropertyStoreBuilder}.
@@ -181,8 +182,7 @@ public class RestConfigApply extends ConfigApply<Rest> {
}
}
- if (! a.messages().isEmpty())
- psb.prependTo(REST_messages, new
MessageBundleLocation(c.inner(), string(a.messages())));
+ psb.prependTo(REST_messages, Tuple2.of(c.inner(),
string(a.messages())));
for (String header : strings(a.staticFileResponseHeaders())) {
String[] h = RestUtils.parseHeader(header);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResourceConfigApply.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResourceConfigApply.java
index 769603a..e66908f 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResourceConfigApply.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResourceConfigApply.java
@@ -173,7 +173,7 @@ public class RestResourceConfigApply extends
ConfigApply<RestResource> {
}
if (! a.messages().isEmpty())
- psb.prependTo(REST_messages, new
MessageBundleLocation(c.inner(), string(a.messages())));
+ psb.prependTo(REST_messages, Tuple2.of(c.inner(),
string(a.messages())));
for (String header : strings(a.staticFileResponseHeaders())) {
String[] h = RestUtils.parseHeader(header);