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 12873e4 JUNEAU-197
12873e4 is described below
commit 12873e4cdb789dcfbfb605849b8065c759aa2334
Author: JamesBognar <[email protected]>
AuthorDate: Sun Mar 8 13:36:57 2020 -0400
JUNEAU-197
@BeanConfig(bpi) does not override @Bean(bpi)
---
.../juneau/internal/ReadOnlyArrayListTest.java | 142 +++++++
.../apache/juneau/reflection/ClassInfoTest.java | 28 +-
.../main/java/org/apache/juneau/BeanContext.java | 8 +-
.../main/java/org/apache/juneau/ContextCache.java | 2 +-
.../apache/juneau/internal/ReadOnlyArrayList.java | 217 +++++++++++
.../java/org/apache/juneau/reflect/ClassInfo.java | 406 ++++++++++++---------
.../java/org/apache/juneau/reflect/Mutaters.java | 2 +-
.../org/apache/juneau/transform/DefaultSwaps.java | 2 +-
8 files changed, 613 insertions(+), 194 deletions(-)
diff --git
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/internal/ReadOnlyArrayListTest.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/internal/ReadOnlyArrayListTest.java
new file mode 100644
index 0000000..cdb4e8d
--- /dev/null
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/internal/ReadOnlyArrayListTest.java
@@ -0,0 +1,142 @@
+//
***************************************************************************************************************************
+// * 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.internal;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.junit.*;
+
+@SuppressWarnings("unchecked")
+public class ReadOnlyArrayListTest {
+
+ private static <T> ReadOnlyArrayList<T> create(T...t) {
+ return new ReadOnlyArrayList<>(t);
+ }
+
+ private static <T> ReadOnlyArrayList<T> createReversed(T...t) {
+ return new ReadOnlyArrayList<>(t, true);
+ }
+
+ @Test
+ public void testBasic() {
+ List<String> l = create("a","b","c");
+ assertEquals("a", l.get(0));
+ assertEquals("b", l.get(1));
+ assertEquals("c", l.get(2));
+ }
+
+ @Test
+ public void testBasicReversed() {
+ List<String> l = createReversed("a","b","c");
+ assertEquals("c", l.get(0));
+ assertEquals("b", l.get(1));
+ assertEquals("a", l.get(2));
+ }
+
+ @Test
+ public void testIterator() {
+ List<String> l = create("a","b","c");
+ Iterator<String> i = l.iterator();
+ assertTrue(i.hasNext());
+ assertEquals("a", i.next());
+ assertTrue(i.hasNext());
+ assertEquals("b", i.next());
+ assertTrue(i.hasNext());
+ assertEquals("c", i.next());
+ assertFalse(i.hasNext());
+
+ l = create();
+ assertFalse(l.iterator().hasNext());
+ }
+
+ @Test
+ public void testIteratorReversed() {
+ List<String> l = createReversed("a","b","c");
+ Iterator<String> i = l.iterator();
+ assertTrue(i.hasNext());
+ assertEquals("c", i.next());
+ assertTrue(i.hasNext());
+ assertEquals("b", i.next());
+ assertTrue(i.hasNext());
+ assertEquals("a", i.next());
+ assertFalse(i.hasNext());
+
+ l = createReversed();
+ assertFalse(l.iterator().hasNext());
+ }
+
+ @Test
+ public void testSize() {
+ assertEquals(1, create("a").size());
+ }
+
+ @Test
+ public void testIsEmpty() {
+ assertFalse(create("a").isEmpty());
+ assertTrue(create().isEmpty());
+ }
+
+ @Test
+ public void testContains() {
+ assertTrue(create("a").contains("a"));
+ assertFalse(create("a").contains("b"));
+ assertFalse(create("a").contains(null));
+ assertTrue(create("a", null).contains(null));
+ }
+
+ @Test
+ public void testToArray() {
+ String[] s = new String[]{"a"};
+ List<String> l = new ReadOnlyArrayList<>(s);
+ String[] s2 = (String[])l.toArray();
+ assertEquals("a", s2[0]);
+ s2[0] = "b";
+ assertEquals("a", s[0]);
+ }
+
+ @Test
+ public void testToArray2() {
+ String[] s = new String[]{"a"};
+ List<String> l = new ReadOnlyArrayList<>(s);
+ String[] s2 = l.toArray(new String[l.size()]);
+ assertEquals("a", s2[0]);
+ s2[0] = "b";
+ assertEquals("a", s[0]);
+ }
+
+ @Test
+ public void testContainsAll() {
+ assertTrue(create("a").containsAll(Arrays.asList("a")));
+ assertFalse(create("a").containsAll(Arrays.asList("a","b")));
+ assertFalse(create("a").containsAll(Arrays.asList("b")));
+
assertFalse(create("a").containsAll(Arrays.asList((String)null)));
+ assertTrue(create("a",
null).containsAll(Arrays.asList((String)null)));
+ }
+
+ @Test
+ public void testIndexOf() {
+ List<String> l = create("a","b","a","c");
+ assertEquals(0, l.indexOf("a"));
+ assertEquals(2, l.lastIndexOf("a"));
+ assertEquals(1, l.indexOf("b"));
+ assertEquals(1, l.lastIndexOf("b"));
+ assertEquals(3, l.indexOf("c"));
+ assertEquals(3, l.lastIndexOf("c"));
+ assertEquals(-1, l.indexOf("d"));
+ assertEquals(-1, l.lastIndexOf("d"));
+ assertEquals(-1, l.indexOf(null));
+ assertEquals(-1, l.lastIndexOf(null));
+ }
+}
diff --git
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
index ed52125..1f60dca 100644
---
a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
+++
b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/reflection/ClassInfoTest.java
@@ -215,23 +215,23 @@ public class ClassInfoTest {
@Test
public void getInterfaces() {
- check("", bi4.getInterfaces());
- check("BI1,BI2", bc1.getInterfaces());
- check("BI3,BI1,BI2", bc2.getInterfaces());
- check("BI3,BI1,BI2", bc3.getInterfaces());
+ check("", bi4.getInterfacesChildFirst());
+ check("BI1,BI2", bc1.getInterfacesChildFirst());
+ check("BI3,BI1,BI2", bc2.getInterfacesChildFirst());
+ check("BI3,BI1,BI2", bc3.getInterfacesChildFirst());
}
@Test
public void getInterfaces_tiwce() {
- check("BI3,BI1,BI2", bc2.getInterfaces());
- check("BI3,BI1,BI2", bc2.getInterfaces());
+ check("BI3,BI1,BI2", bc2.getInterfacesChildFirst());
+ check("BI3,BI1,BI2", bc2.getInterfacesChildFirst());
}
@Test
public void getParents() {
- check("BC3,BC2,BC1", bc3.getParents());
- check("", object.getParents());
- check("BI1", bi1.getParents());
+ check("BC3,BC2,BC1", bc3.getParentsChildFirst());
+ check("", object.getParentsChildFirst());
+ check("BI1", bi1.getParentsChildFirst());
}
@Test
@@ -243,15 +243,15 @@ public class ClassInfoTest {
@Test
public void getAllParents() {
- check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParents());
- check("", object.getAllParents());
- check("BI1", bi1.getAllParents());
+ check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParentsChildFirst());
+ check("", object.getAllParentsChildFirst());
+ check("BI1", bi1.getAllParentsChildFirst());
}
@Test
public void getAllParents_twice() {
- check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParents());
- check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParents());
+ check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParentsChildFirst());
+ check("BC3,BC2,BC1,BI3,BI1,BI2", bc3.getAllParentsChildFirst());
}
@Test
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 309841e..0fb6e53 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -3638,7 +3638,7 @@ public class BeanContext extends Context implements
MetaProvider {
if (bpi.isEmpty())
return emptySet();
ClassInfo ci = ClassInfo.of(c);
- for (ClassInfo c2 : ci.getAllParents()) {
+ for (ClassInfo c2 : ci.getAllParentsChildFirst()) {
for (String n : c2.getNames()) {
Set<String> s = bpi.get(n);
if (s != null)
@@ -3671,7 +3671,7 @@ public class BeanContext extends Context implements
MetaProvider {
if (bpx.isEmpty())
return emptySet();
ClassInfo ci = ClassInfo.of(c);
- for (ClassInfo c2 : ci.getAllParents()) {
+ for (ClassInfo c2 : ci.getAllParentsChildFirst()) {
for (String n : c2.getNames()) {
Set<String> s = bpx.get(n);
if (s != null)
@@ -3704,7 +3704,7 @@ public class BeanContext extends Context implements
MetaProvider {
if (bpro.isEmpty())
return emptySet();
ClassInfo ci = ClassInfo.of(c);
- for (ClassInfo c2 : ci.getAllParents()) {
+ for (ClassInfo c2 : ci.getAllParentsChildFirst()) {
for (String n : c2.getNames()) {
Set<String> s = bpro.get(n);
if (s != null)
@@ -3737,7 +3737,7 @@ public class BeanContext extends Context implements
MetaProvider {
if (bpwo.isEmpty())
return emptySet();
ClassInfo ci = ClassInfo.of(c);
- for (ClassInfo c2 : ci.getAllParents()) {
+ for (ClassInfo c2 : ci.getAllParentsChildFirst()) {
for (String n : c2.getNames()) {
Set<String> s = bpwo.get(n);
if (s != null)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
index 18856aa..0ca4716 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
@@ -146,7 +146,7 @@ public class ContextCache {
String[] prefixes = prefixCache.get(c);
if (prefixes == null) {
Set<String> ps = new HashSet<>();
- for (ClassInfo c2 : ClassInfo.of(c).getAllParents()) {
+ for (ClassInfo c2 :
ClassInfo.of(c).getAllParentsChildFirst()) {
ConfigurableContext cc =
c2.getLastAnnotation(ConfigurableContext.class);
if (cc != null) {
if (cc.nocache()) {
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReadOnlyArrayList.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReadOnlyArrayList.java
new file mode 100644
index 0000000..28c165a
--- /dev/null
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ReadOnlyArrayList.java
@@ -0,0 +1,217 @@
+//
***************************************************************************************************************************
+// * 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.internal;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Simple read-only wrapper around an object array.
+ *
+ * <p>
+ * Allows for forward or reverse access to elements of an array without being
able to modify the array and without
+ * involving copying the array.
+ *
+ * @param <T> Array element type.
+ */
+public class ReadOnlyArrayList<T> implements List<T> {
+
+ final T[] array;
+ final int length;
+ private final boolean reversed;
+
+ /**
+ * Constructor.
+ *
+ * @param array The array being wrapped.
+ */
+ public ReadOnlyArrayList(T[] array) {
+ this(array, false);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param array The array being wrapped.
+ * @param reversed <jk>true</jk> if elements of array should be
addressed in reverse.
+ */
+ @SuppressWarnings("unchecked")
+ public ReadOnlyArrayList(T[] array, boolean reversed) {
+ this.array = array == null ? (T[])new Object[0] : array;
+ this.length = this.array.length;
+ this.reversed = reversed;
+ }
+
+ @Override
+ public int size() {
+ return array.length;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return array.length == 0;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return indexOf(o) != -1;
+ }
+
+ @Override
+ public Iterator<T> iterator() {
+ if (reversed) {
+ return new Iterator<T>() {
+ int i = length-1;
+
+ @Override
+ public boolean hasNext() {
+ return i > -1;
+ }
+
+ @Override
+ public T next() {
+ return array[i--];
+ }
+ };
+ }
+ return new Iterator<T>() {
+ int i = 0;
+
+ @Override
+ public boolean hasNext() {
+ return i < length;
+ }
+
+ @Override
+ public T next() {
+ return array[i++];
+ }
+ };
+ }
+
+ @Override
+ public Object[] toArray() {
+ Object[] o2 =
(Object[])Array.newInstance(array.getClass().getComponentType(), array.length);
+ for (int i = 0; i < array.length; i++)
+ o2[i] = reversed ? array[length-i-1] : array[i];
+ return o2;
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "hiding" })
+ public <T> T[] toArray(T[] a) {
+ for (int i = 0; i < array.length; i++)
+ a[i] = reversed ? (T)array[length-i-1] : (T)array[i];
+ return a;
+ }
+
+ @Override
+ public boolean add(T e) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ for (Object o : c)
+ if (! contains(o))
+ return false;
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends T> c) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends T> c) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public T get(int index) {
+ return reversed ? array[length-index-1] : array[index];
+ }
+
+ @Override
+ public T set(int index, T element) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public void add(int index, T element) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public T remove(int index) {
+ throw new UnsupportedOperationException("Cannot modify
read-only list.");
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ for (int i = 0; i < length; i++) {
+ int j = reversed ? length-i-1 : i;
+ T t = array[j];
+ if ((o == t) || (o != null && o.equals(t)))
+ return j;
+ }
+ return -1;
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ for (int i = length-1; i >= 0; i--) {
+ int j = reversed ? length-i-1 : i;
+ T t = array[j];
+ if ((o == t) || (o != null && o.equals(t)))
+ return j;
+ }
+ return -1;
+ }
+
+ @Override
+ public ListIterator<T> listIterator() {
+ throw new UnsupportedOperationException("Unsupported method on
ReadOnlyArrayList class.");
+ }
+
+ @Override
+ public ListIterator<T> listIterator(int index) {
+ throw new UnsupportedOperationException("Unsupported method on
ReadOnlyArrayList class.");
+ }
+
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
+ throw new UnsupportedOperationException("Unsupported method on
ReadOnlyArrayList class.");
+ }
+}
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index f0df106..c3fcc9c 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -60,10 +60,10 @@ public final class ClassInfo {
final Class<?> c;
private ClassInfo proxyFor;
private final boolean isParameterizedType;
- private List<ClassInfo> interfaces, declaredInterfaces, parents,
allParents;
- private List<MethodInfo> publicMethods, declaredMethods, allMethods,
allMethodsParentFirst;
- private List<ConstructorInfo> publicConstructors, declaredConstructors;
- private List<FieldInfo> publicFields, declaredFields, allFields,
allFieldsParentFirst;
+ private ClassInfo[] interfaces, declaredInterfaces, parents, allParents;
+ private MethodInfo[] publicMethods, declaredMethods, allMethods,
allMethodsParentFirst;
+ private ConstructorInfo[] publicConstructors, declaredConstructors;
+ private FieldInfo[] publicFields, declaredFields, allFields,
allFieldsParentFirst;
private int dim = -1;
private ClassInfo componentType;
@@ -249,14 +249,7 @@ public final class ClassInfo {
* <br>Results are in the same order as {@link
Class#getInterfaces()}.
*/
public List<ClassInfo> getDeclaredInterfaces() {
- if (declaredInterfaces == null) {
- Class<?>[] ii = c == null ? new Class[0] :
c.getInterfaces();
- List<ClassInfo> l = new ArrayList<>(ii.length);
- for (Class<?> i : ii)
- l.add(of(i));
- declaredInterfaces = unmodifiableList(l);
- }
- return declaredInterfaces;
+ return new ReadOnlyArrayList<>(getDeclaredInterfacesInternal());
}
/**
@@ -266,18 +259,8 @@ public final class ClassInfo {
* An unmodifiable list of interfaces defined on this class and
superclasses.
* <br>Results are in child-to-parent order.
*/
- public List<ClassInfo> getInterfaces() {
- if (interfaces == null) {
- Set<ClassInfo> s = new LinkedHashSet<>();
- for (ClassInfo ci : getParents())
- for (ClassInfo ci2 :
ci.getDeclaredInterfaces()) {
- s.add(ci2);
- for (ClassInfo ci3 :
ci2.getInterfaces())
- s.add(ci3);
- }
- interfaces = unmodifiableList(new ArrayList<>(s));
- }
- return interfaces;
+ public List<ClassInfo> getInterfacesChildFirst() {
+ return new ReadOnlyArrayList<>(getInterfacesInternal());
}
/**
@@ -287,8 +270,8 @@ public final class ClassInfo {
* An unmodifiable list of interfaces defined on this class and
superclasses.
* <br>Results are in parent-to-child order.
*/
- public Iterable<ClassInfo> getInterfacesParentFirst() {
- return iterable(getInterfaces(), true);
+ public List<ClassInfo> getInterfacesParentFirst() {
+ return new ReadOnlyArrayList<>(getInterfacesInternal(), true);
}
/**
@@ -300,17 +283,8 @@ public final class ClassInfo {
* @return An unmodifiable list including this class and all parent
classes.
* <br>Results are in child-to-parent order.
*/
- public List<ClassInfo> getParents() {
- if (parents == null) {
- List<ClassInfo> l = new ArrayList<>();
- Class<?> pc = c;
- while (pc != null && pc != Object.class) {
- l.add(of(pc));
- pc = pc.getSuperclass();
- }
- parents = Collections.unmodifiableList(l);
- }
- return parents;
+ public List<ClassInfo> getParentsChildFirst() {
+ return new ReadOnlyArrayList<>(getParentsInternal());
}
/**
@@ -322,8 +296,8 @@ public final class ClassInfo {
* @return An unmodifiable list including this class and all parent
classes.
* <br>Results are in parent-to-child order.
*/
- public Iterable<ClassInfo> getParentsParentFirst() {
- return iterable(getParents(), true);
+ public List<ClassInfo> getParentsParentFirst() {
+ return new ReadOnlyArrayList<>(getParentsInternal(), true);
}
/**
@@ -332,14 +306,8 @@ public final class ClassInfo {
* @return An unmodifiable list including this class and all parent
classes.
* <br>Results are ordered child-to-parent order with classes
listed before interfaces.
*/
- public List<ClassInfo> getAllParents() {
- if (allParents == null) {
- List<ClassInfo> l = new ArrayList<>();
- l.addAll(getParents());
- l.addAll(getInterfaces());
- allParents = Collections.unmodifiableList(l);
- }
- return allParents;
+ public List<ClassInfo> getAllParentsChildFirst() {
+ return new ReadOnlyArrayList<>(getAllParentsInternal());
}
/**
@@ -348,8 +316,59 @@ public final class ClassInfo {
* @return An unmodifiable list including this class and all parent
classes.
* <br>Results are ordered parent-to-child order with interfaces
listed before classes.
*/
- public Iterable<ClassInfo> getAllParentsParentFirst() {
- return iterable(getAllParents(), true);
+ public List<ClassInfo> getAllParentsParentFirst() {
+ return new ReadOnlyArrayList<>(getAllParentsInternal(), true);
+ }
+
+ private ClassInfo[] getInterfacesInternal() {
+ if (interfaces == null) {
+ Set<ClassInfo> s = new LinkedHashSet<>();
+ for (ClassInfo ci : getParentsChildFirst())
+ for (ClassInfo ci2 :
ci.getDeclaredInterfaces()) {
+ s.add(ci2);
+ for (ClassInfo ci3 :
ci2.getInterfacesChildFirst())
+ s.add(ci3);
+ }
+ interfaces = s.toArray(new ClassInfo[s.size()]);
+ }
+ return interfaces;
+ }
+
+ private ClassInfo[] getDeclaredInterfacesInternal() {
+ if (declaredInterfaces == null) {
+ Class<?>[] ii = c == null ? new Class[0] :
c.getInterfaces();
+ ClassInfo[] l = new ClassInfo[ii.length];
+ for (int i = 0; i < ii.length; i++)
+ l[i] = of(ii[i]);
+ declaredInterfaces = l;
+ }
+ return declaredInterfaces;
+ }
+
+ private ClassInfo[] getParentsInternal() {
+ if (parents == null) {
+ List<ClassInfo> l = new ArrayList<>();
+ Class<?> pc = c;
+ while (pc != null && pc != Object.class) {
+ l.add(of(pc));
+ pc = pc.getSuperclass();
+ }
+ parents = l.toArray(new ClassInfo[l.size()]);
+ }
+ return parents;
+ }
+
+ private ClassInfo[] getAllParentsInternal() {
+ if (allParents == null) {
+ ClassInfo[] a1 = getParentsInternal(), a2 =
getInterfacesInternal();
+ ClassInfo[] l = new ClassInfo[a1.length + a2.length];
+ for (int i = 0; i < a1.length; i++)
+ l[i] = a1[i];
+ for (int i = 0; i < a2.length; i++)
+ l[i+a1.length] = a2[i];
+ allParents = l;
+ }
+ return allParents;
}
//-----------------------------------------------------------------------------------------------------------------
@@ -367,34 +386,7 @@ public final class ClassInfo {
* <br>Results are ordered alphabetically.
*/
public List<MethodInfo> getPublicMethods() {
- if (publicMethods == null) {
- Method[] mm = c == null ? new Method[0] :
c.getMethods();
- List<MethodInfo> l = new ArrayList<>(mm.length);
- for (Method m : mm)
- if (m.getDeclaringClass() != Object.class)
- l.add(MethodInfo.of(this, m,
getProxyTarget(m)));
- l.sort(null);
- publicMethods = Collections.unmodifiableList(l);
- }
- return publicMethods;
- }
-
- private Method getProxyTarget(Method m) {
- if (proxyFor != null) {
- MethodInfo m2 = proxyFor.getMethod(m.getName(),
m.getParameterTypes());
- if (m2 != null)
- return m2.inner();
- }
- return m;
- }
-
- private Constructor<?> getProxyTarget(Constructor<?> c) {
- if (proxyFor != null) {
- ConstructorInfo c2 =
proxyFor.getConstructor(Visibility.PRIVATE, c.getParameterTypes());
- if (c2 != null)
- return c2.inner();
- }
- return c;
+ return new ReadOnlyArrayList<>(getPublicMethodsInternal());
}
/**
@@ -406,7 +398,7 @@ public final class ClassInfo {
* The public method with the specified method name and argument
types, or <jk>null</jk> if not found.
*/
public MethodInfo getPublicMethod(String name, Class<?>...args) {
- for (MethodInfo mi : getPublicMethods())
+ for (MethodInfo mi : getPublicMethodsInternal())
if (mi.hasName(name) && mi.hasParamTypes(args))
return mi;
return null;
@@ -421,7 +413,7 @@ public final class ClassInfo {
* The method with the specified method name and argument types, or
<jk>null</jk> if not found.
*/
public MethodInfo getMethod(String name, Class<?>...args) {
- for (MethodInfo mi : getAllMethods())
+ for (MethodInfo mi : getAllMethodsInternal())
if (mi.hasName(name) && mi.hasParamTypes(args))
return mi;
return null;
@@ -435,16 +427,7 @@ public final class ClassInfo {
* <br>Results are ordered alphabetically.
*/
public List<MethodInfo> getDeclaredMethods() {
- if (declaredMethods == null) {
- Method[] mm = c == null ? new Method[0] :
c.getDeclaredMethods();
- List<MethodInfo> l = new ArrayList<>(mm.length);
- for (Method m : mm)
- if (! "$jacocoInit".equals(m.getName())) //
Jacoco adds its own simulated methods.
- l.add(MethodInfo.of(this, m,
getProxyTarget(m)));
- l.sort(null);
- declaredMethods = Collections.unmodifiableList(l);
- }
- return declaredMethods;
+ return new ReadOnlyArrayList<>(getDeclaredMethodsInternal());
}
/**
@@ -455,13 +438,7 @@ public final class ClassInfo {
* <br>Results are ordered child-to-parent, and then
alphabetically per class.
*/
public List<MethodInfo> getAllMethods() {
- if (allMethods == null) {
- List<MethodInfo> l = new ArrayList<>();
- for (ClassInfo c : getAllParents())
- c.appendDeclaredMethods(l);
- allMethods = Collections.unmodifiableList(l);
- }
- return allMethods;
+ return new ReadOnlyArrayList<>(getAllMethodsInternal());
}
/**
@@ -473,11 +450,51 @@ public final class ClassInfo {
* <br>Results are ordered parent-to-child, and then
alphabetically per class.
*/
public List<MethodInfo> getAllMethodsParentFirst() {
+ return new
ReadOnlyArrayList<>(getAllMethodsParentFirstInternal());
+ }
+
+ private MethodInfo[] getPublicMethodsInternal() {
+ if (publicMethods == null) {
+ Method[] mm = c == null ? new Method[0] :
c.getMethods();
+ List<MethodInfo> l = new ArrayList<>(mm.length);
+ for (Method m : mm)
+ if (m.getDeclaringClass() != Object.class)
+ l.add(MethodInfo.of(this, m,
getProxyTarget(m)));
+ l.sort(null);
+ publicMethods = l.toArray(new MethodInfo[l.size()]);
+ }
+ return publicMethods;
+ }
+
+ private MethodInfo[] getDeclaredMethodsInternal() {
+ if (declaredMethods == null) {
+ Method[] mm = c == null ? new Method[0] :
c.getDeclaredMethods();
+ List<MethodInfo> l = new ArrayList<>(mm.length);
+ for (Method m : mm)
+ if (! "$jacocoInit".equals(m.getName())) //
Jacoco adds its own simulated methods.
+ l.add(MethodInfo.of(this, m,
getProxyTarget(m)));
+ l.sort(null);
+ declaredMethods = l.toArray(new MethodInfo[l.size()]);
+ }
+ return declaredMethods;
+ }
+
+ private MethodInfo[] getAllMethodsInternal() {
+ if (allMethods == null) {
+ List<MethodInfo> l = new ArrayList<>();
+ for (ClassInfo c : getAllParentsChildFirst())
+ c.appendDeclaredMethods(l);
+ allMethods = l.toArray(new MethodInfo[l.size()]);
+ }
+ return allMethods;
+ }
+
+ private MethodInfo[] getAllMethodsParentFirstInternal() {
if (allMethodsParentFirst == null) {
List<MethodInfo> l = new ArrayList<>();
for (ClassInfo c : getAllParentsParentFirst())
c.appendDeclaredMethods(l);
- allMethodsParentFirst = Collections.unmodifiableList(l);
+ allMethodsParentFirst = l.toArray(new
MethodInfo[l.size()]);
}
return allMethodsParentFirst;
}
@@ -487,6 +504,24 @@ public final class ClassInfo {
return l;
}
+ private Method getProxyTarget(Method m) {
+ if (proxyFor != null) {
+ MethodInfo m2 = proxyFor.getMethod(m.getName(),
m.getParameterTypes());
+ if (m2 != null)
+ return m2.inner();
+ }
+ return m;
+ }
+
+ private Constructor<?> getProxyTarget(Constructor<?> c) {
+ if (proxyFor != null) {
+ ConstructorInfo c2 =
proxyFor.getConstructor(Visibility.PRIVATE, c.getParameterTypes());
+ if (c2 != null)
+ return c2.inner();
+ }
+ return c;
+ }
+
//-----------------------------------------------------------------------------------------------------------------
// Special methods
//-----------------------------------------------------------------------------------------------------------------
@@ -594,15 +629,7 @@ public final class ClassInfo {
* @return All public constructors defined on this class.
*/
public List<ConstructorInfo> getPublicConstructors() {
- if (publicConstructors == null) {
- Constructor<?>[] cc = c == null ? new Constructor[0] :
c.getConstructors();
- List<ConstructorInfo> l = new ArrayList<>(cc.length);
- for (Constructor<?> ccc : cc)
- l.add(ConstructorInfo.of(this, ccc,
getProxyTarget(ccc)));
- l.sort(null);
- publicConstructors = Collections.unmodifiableList(l);
- }
- return publicConstructors;
+ return new ReadOnlyArrayList<>(getPublicConstructorsInternal());
}
/**
@@ -613,7 +640,7 @@ public final class ClassInfo {
* The public constructor with the specified argument types, or
<jk>null</jk> if not found.
*/
public ConstructorInfo getPublicConstructor(Class<?>...args) {
- for (ConstructorInfo ci : getPublicConstructors())
+ for (ConstructorInfo ci : getPublicConstructorsInternal())
if (ci.hasParamTypes(args))
return ci;
return null;
@@ -627,7 +654,7 @@ public final class ClassInfo {
* The declared constructor with the specified argument types, or
<jk>null</jk> if not found.
*/
public ConstructorInfo getDeclaredConstructor(Class<?>...args) {
- for (ConstructorInfo ci : getDeclaredConstructors())
+ for (ConstructorInfo ci : getDeclaredConstructorsInternal())
if (ci.hasParamTypes(args))
return ci;
return null;
@@ -653,15 +680,7 @@ public final class ClassInfo {
* @return All constructors defined on this class.
*/
public List<ConstructorInfo> getDeclaredConstructors() {
- if (declaredConstructors == null) {
- Constructor<?>[] cc = c == null ? new Constructor[0] :
c.getDeclaredConstructors();
- List<ConstructorInfo> l = new ArrayList<>(cc.length);
- for (Constructor<?> ccc : cc)
- l.add(ConstructorInfo.of(this, ccc,
getProxyTarget(ccc)));
- l.sort(null);
- declaredConstructors = Collections.unmodifiableList(l);
- }
- return declaredConstructors;
+ return new
ReadOnlyArrayList<>(getDeclaredConstructorsInternal());
}
/**
@@ -701,11 +720,35 @@ public final class ClassInfo {
return getConstructor(vis, false, argTypes);
}
+ private ConstructorInfo[] getPublicConstructorsInternal() {
+ if (publicConstructors == null) {
+ Constructor<?>[] cc = c == null ? new Constructor[0] :
c.getConstructors();
+ List<ConstructorInfo> l = new ArrayList<>(cc.length);
+ for (Constructor<?> ccc : cc)
+ l.add(ConstructorInfo.of(this, ccc,
getProxyTarget(ccc)));
+ l.sort(null);
+ publicConstructors = l.toArray(new
ConstructorInfo[l.size()]);
+ }
+ return publicConstructors;
+ }
+
+ private ConstructorInfo[] getDeclaredConstructorsInternal() {
+ if (declaredConstructors == null) {
+ Constructor<?>[] cc = c == null ? new Constructor[0] :
c.getDeclaredConstructors();
+ List<ConstructorInfo> l = new ArrayList<>(cc.length);
+ for (Constructor<?> ccc : cc)
+ l.add(ConstructorInfo.of(this, ccc,
getProxyTarget(ccc)));
+ l.sort(null);
+ declaredConstructors = l.toArray(new
ConstructorInfo[l.size()]);
+ }
+ return declaredConstructors;
+ }
+
private ConstructorInfo getConstructor(Visibility vis, boolean
fuzzyArgs, Class<?>...argTypes) {
if (fuzzyArgs) {
int bestCount = -1;
ConstructorInfo bestMatch = null;
- for (ConstructorInfo n : getDeclaredConstructors()) {
+ for (ConstructorInfo n :
getDeclaredConstructorsInternal()) {
if (vis.isVisible(n.inner())) {
int m =
ClassUtils.fuzzyArgsMatch(n.getParamTypes(), argTypes);
if (m > bestCount) {
@@ -718,7 +761,7 @@ public final class ClassInfo {
}
boolean isMemberClass = isNonStaticMemberClass();
- for (ConstructorInfo n : getDeclaredConstructors()) {
+ for (ConstructorInfo n : getDeclaredConstructorsInternal()) {
List<ClassInfo> paramTypes = n.getParamTypes();
if (isMemberClass)
paramTypes = paramTypes.subList(1,
paramTypes.size());
@@ -748,7 +791,7 @@ public final class ClassInfo {
if (isAbstract())
return null;
boolean isMemberClass = isNonStaticMemberClass();
- for (ConstructorInfo cc : getDeclaredConstructors())
+ for (ConstructorInfo cc : getDeclaredConstructorsInternal())
if (cc.hasNumParams(isMemberClass ? 1 : 0) &&
cc.isVisible(v))
return cc.makeAccessible(v);
return null;
@@ -769,15 +812,7 @@ public final class ClassInfo {
* <br>Results are in alphabetical order.
*/
public List<FieldInfo> getPublicFields() {
- if (publicFields == null) {
- Map<String,FieldInfo> m = new LinkedHashMap<>();
- for (ClassInfo c : getParents())
- c.appendDeclaredPublicFields(m);
- List<FieldInfo> l = new ArrayList<>(m.values());
- l.sort(null);
- publicFields = Collections.unmodifiableList(l);
- }
- return publicFields;
+ return new ReadOnlyArrayList<>(getPublicFieldsInternal());
}
/**
@@ -788,16 +823,7 @@ public final class ClassInfo {
* <br>Results are in alphabetical order.
*/
public List<FieldInfo> getDeclaredFields() {
- if (declaredFields == null) {
- Field[] ff = c == null ? new Field[0] :
c.getDeclaredFields();
- List<FieldInfo> l = new ArrayList<>(ff.length);
- for (Field f : ff)
- if (! "$jacocoData".equals(f.getName()))
- l.add(FieldInfo.of(this, f));
- l.sort(null);
- declaredFields = Collections.unmodifiableList(l);
- }
- return declaredFields;
+ return new ReadOnlyArrayList<>(getDeclaredFieldsInternal());
}
/**
@@ -808,13 +834,7 @@ public final class ClassInfo {
* <br>Results are ordered child-to-parent, and then alphabetical
per class.
*/
public List<FieldInfo> getAllFields() {
- if (allFields == null) {
- List<FieldInfo> l = new ArrayList<>();
- for (ClassInfo c : getAllParents())
- c.appendDeclaredFields(l);
- allFields = Collections.unmodifiableList(l);
- }
- return allFields;
+ return new ReadOnlyArrayList<>(getAllFieldsInternal());
}
/**
@@ -825,27 +845,7 @@ public final class ClassInfo {
* <br>Results are ordered parent-to-child, and then alphabetical
per class.
*/
public List<FieldInfo> getAllFieldsParentFirst() {
- if (allFieldsParentFirst == null) {
- List<FieldInfo> l = new ArrayList<>();
- for (ClassInfo c : getAllParentsParentFirst())
- c.appendDeclaredFields(l);
- allFieldsParentFirst = Collections.unmodifiableList(l);
- }
- return allFieldsParentFirst;
- }
-
- private List<FieldInfo> appendDeclaredFields(List<FieldInfo> l) {
- l.addAll(getDeclaredFields());
- return l;
- }
-
- private Map<String,FieldInfo>
appendDeclaredPublicFields(Map<String,FieldInfo> m) {
- for (FieldInfo f : getDeclaredFields()) {
- String fn = f.getName();
- if (f.isPublic() && ! (m.containsKey(fn) ||
"$jacocoData".equals(fn)))
- m.put(f.getName(), f);
- }
- return m;
+ return new
ReadOnlyArrayList<>(getAllFieldsParentFirstInternal());
}
/**
@@ -855,7 +855,7 @@ public final class ClassInfo {
* @return The public field, or <jk>null</jk> if not found.
*/
public FieldInfo getPublicField(String name) {
- for (FieldInfo f : getPublicFields())
+ for (FieldInfo f : getPublicFieldsInternal())
if (f.getName().equals(name))
return f;
return null;
@@ -868,7 +868,7 @@ public final class ClassInfo {
* @return The declared field, or <jk>null</jk> if not found.
*/
public FieldInfo getDeclaredField(String name) {
- for (FieldInfo f : getDeclaredFields())
+ for (FieldInfo f : getDeclaredFieldsInternal())
if (f.getName().equals(name))
return f;
return null;
@@ -881,7 +881,7 @@ public final class ClassInfo {
* @return The public field, or <jk>null</jk> if not found.
*/
public FieldInfo getStaticPublicField(String name) {
- for (FieldInfo f : getPublicFields())
+ for (FieldInfo f : getPublicFieldsInternal())
if (f.isStatic() && f.getName().equals(name))
return f;
return null;
@@ -894,12 +894,72 @@ public final class ClassInfo {
* @return The public field, or <jk>null</jk> if not found.
*/
public Field getStaticPublicFieldInner(String name) {
- for (FieldInfo f : getPublicFields())
+ for (FieldInfo f : getPublicFieldsInternal())
if (f.isStatic() && f.getName().equals(name))
return f.inner();
return null;
}
+ private List<FieldInfo> appendDeclaredFields(List<FieldInfo> l) {
+ for (FieldInfo f : getDeclaredFieldsInternal())
+ l.add(f);
+ return l;
+ }
+
+ private Map<String,FieldInfo>
appendDeclaredPublicFields(Map<String,FieldInfo> m) {
+ for (FieldInfo f : getDeclaredFieldsInternal()) {
+ String fn = f.getName();
+ if (f.isPublic() && ! (m.containsKey(fn) ||
"$jacocoData".equals(fn)))
+ m.put(f.getName(), f);
+ }
+ return m;
+ }
+
+ private FieldInfo[] getPublicFieldsInternal() {
+ if (publicFields == null) {
+ Map<String,FieldInfo> m = new LinkedHashMap<>();
+ for (ClassInfo c : getParentsInternal())
+ c.appendDeclaredPublicFields(m);
+ List<FieldInfo> l = new ArrayList<>(m.values());
+ l.sort(null);
+ publicFields = l.toArray(new FieldInfo[l.size()]);
+ }
+ return publicFields;
+ }
+
+ private FieldInfo[] getDeclaredFieldsInternal() {
+ if (declaredFields == null) {
+ Field[] ff = c == null ? new Field[0] :
c.getDeclaredFields();
+ List<FieldInfo> l = new ArrayList<>(ff.length);
+ for (Field f : ff)
+ if (! "$jacocoData".equals(f.getName()))
+ l.add(FieldInfo.of(this, f));
+ l.sort(null);
+ declaredFields = l.toArray(new FieldInfo[l.size()]);
+ }
+ return declaredFields;
+ }
+
+ private FieldInfo[] getAllFieldsInternal() {
+ if (allFields == null) {
+ List<FieldInfo> l = new ArrayList<>();
+ for (ClassInfo c : getAllParentsInternal())
+ c.appendDeclaredFields(l);
+ allFields = l.toArray(new FieldInfo[l.size()]);
+ }
+ return allFields;
+ }
+
+ private FieldInfo[] getAllFieldsParentFirstInternal() {
+ if (allFieldsParentFirst == null) {
+ List<FieldInfo> l = new ArrayList<>();
+ for (ClassInfo c : getAllParentsParentFirst())
+ c.appendDeclaredFields(l);
+ allFieldsParentFirst = l.toArray(new
FieldInfo[l.size()]);
+ }
+ return allFieldsParentFirst;
+ }
+
//-----------------------------------------------------------------------------------------------------------------
// Annotations
//-----------------------------------------------------------------------------------------------------------------
@@ -1185,7 +1245,7 @@ public final class ClassInfo {
if (x != null)
return x;
}
- for (ClassInfo ci : getInterfaces()) {
+ for (ClassInfo ci : getInterfacesChildFirst()) {
for (Class<? extends Annotation> ca : annotations) {
Annotation x = ci.getLastAnnotation(ca, mp);
if (x != null)
@@ -1226,7 +1286,7 @@ public final class ClassInfo {
return t2;
}
- for (ClassInfo c2 : getInterfaces()) {
+ for (ClassInfo c2 : getInterfacesChildFirst()) {
t2 = c2.getLastAnnotation(a, mp);
if (t2 != null)
return t2;
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
index c45e52b..9a50054 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/Mutaters.java
@@ -147,7 +147,7 @@ public class Mutaters {
ClassInfo ici = ClassInfo.of(ic), oci = ClassInfo.of(oc);
- for (ClassInfo pic : ici.getAllParents()) {
+ for (ClassInfo pic : ici.getAllParentsChildFirst()) {
Mutater t = m.get(pic.inner());
if (t != null)
return t;
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/DefaultSwaps.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/DefaultSwaps.java
index 7334bb7..143e806 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/DefaultSwaps.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/DefaultSwaps.java
@@ -60,7 +60,7 @@ public class DefaultSwaps {
* @return The matched swap, or <jk>null</jk> if it couldn't be found.
*/
public static PojoSwap<?,?> find(ClassInfo ci) {
- for (ClassInfo ci2 : ci.getAllParents()) {
+ for (ClassInfo ci2 : ci.getAllParentsChildFirst()) {
PojoSwap<?,?> ps = POJO_SWAPS.get(ci2.inner());
if (ps != null)
return ps;