| /* |
| * 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.openjpa.util; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.openjpa.kernel.FillStrategy; |
| import org.apache.openjpa.kernel.ResultShape; |
| import org.junit.Test; |
| |
| |
| import static org.junit.Assert.*; |
| |
| public class TestResultShape { |
| |
| @Test |
| public void testPrimitiveShapeIsImmutable() { |
| ResultShape<Object> shape = new ResultShape<>(Object.class, true); |
| assertCategory(shape, true, false, false); |
| assertEquals(FillStrategy.Assign.class, shape.getStrategy().getClass()); |
| |
| try { |
| shape.add(int.class); |
| fail(shape + " should not allow adding other shapes"); |
| } catch (UnsupportedOperationException e) { |
| } |
| try { |
| shape.nest(Object[].class, new FillStrategy.Array(Object[].class), int.class, double.class); |
| fail(shape + " should not allow nesting other shapes"); |
| } catch (UnsupportedOperationException e) { |
| } |
| } |
| |
| @Test |
| public void testArrayIsMutable() { |
| ResultShape<Object[]> shape = new ResultShape<>(Object[].class); |
| assertCategory(shape, false, true, false); |
| assertEquals(FillStrategy.Array.class, shape.getStrategy().getClass()); |
| |
| shape.add(int.class, double.class); // will add primitive shapes |
| assertCategory(shape, false, true, false); |
| |
| ResultShape<Object> primitiveShape = new ResultShape<>(Object.class, true); |
| shape.nest(primitiveShape); |
| assertCategory(shape, false, true, false); |
| |
| ResultShape<Object[]> nonPrimitiveShape = new ResultShape<>(Object[].class); |
| nonPrimitiveShape.add(int.class, double.class); |
| assertCategory(nonPrimitiveShape, false, true, false); |
| shape.nest(nonPrimitiveShape); |
| assertCategory(shape, false, true, true); |
| } |
| |
| @Test |
| public void testMethodImpliesMapStrategy() { |
| FillStrategy<Map> strategy = new FillStrategy.Map<>(method(Map.class, "put", Object.class, Object.class)); |
| ResultShape<Map> mapShape = new ResultShape<>(Map.class, strategy, true); |
| assertCategory(mapShape, true, false, false); |
| assertEquals(FillStrategy.Map.class, mapShape.getStrategy().getClass()); |
| } |
| |
| @Test |
| public void testShapeWithConstrcutorStrategy() { |
| FillStrategy<List> strategy = new FillStrategy.NewInstance<>(constructor(ArrayList.class, int.class)); |
| ResultShape<List> listShape = new ResultShape<>(List.class, strategy); |
| assertCategory(listShape, false, true, false); |
| assertEquals(FillStrategy.NewInstance.class, listShape.getStrategy().getClass()); |
| } |
| |
| @Test |
| public void testGetCompositeTypes() { |
| ResultShape<Object[]> root = new ResultShape<>(Object[].class); |
| FillStrategy<Bar> strategy1 = new FillStrategy.NewInstance<>(Bar.class); |
| ResultShape<Bar> bar1 = new ResultShape<>(Bar.class, strategy1, false); |
| bar1.add(int.class); |
| FillStrategy<Foo> strategy2 = new FillStrategy.NewInstance<>(constructor(Foo.class, short.class, Bar.class)); |
| ResultShape<Foo> fooBarConstructor = new ResultShape<>(Foo.class, strategy2); |
| fooBarConstructor.add(short.class); |
| fooBarConstructor.nest(bar1); |
| root.add(Foo.class, Object.class); |
| root.nest(fooBarConstructor); |
| ResultShape<Bar> bar2 = new ResultShape<Bar>(Bar.class, new FillStrategy.NewInstance(Bar.class), false); |
| root.nest(bar2); |
| assertEquals("Object[]{Foo, Object, Foo{short, Bar{int}}, Bar}", root.toString()); |
| assertEquals(Arrays.asList(Foo.class, Object.class, short.class, int.class, Bar.class), |
| root.getCompositeTypes()); |
| assertEquals(Arrays.asList(Foo.class, Object.class, Foo.class, Bar.class), root.getTypes()); |
| assertEquals(5, root.argLength()); |
| assertEquals(4, root.length()); |
| } |
| |
| @Test |
| public void testRecursiveNestingIsNotAllowed() { |
| ResultShape<Object[]> root = new ResultShape<>(Object[].class); |
| ResultShape<Bar> bar1 = new ResultShape<Bar>(Bar.class, new FillStrategy.NewInstance(Bar.class), false); |
| bar1.add(int.class); |
| ResultShape<Foo> fooBarConstructor = new ResultShape<Foo>(Foo.class, |
| new FillStrategy.NewInstance(constructor(Foo.class, short.class, Bar.class))); |
| fooBarConstructor.add(short.class); |
| fooBarConstructor.nest(bar1); |
| root.add(Foo.class, Object.class); |
| root.nest(fooBarConstructor); |
| ResultShape<Bar> bar2 = new ResultShape<Bar>(Bar.class, new FillStrategy.NewInstance(Bar.class), false); |
| root.nest(bar2); |
| |
| try { |
| bar1.nest(fooBarConstructor); |
| fail("Expecetd recursive nesting error in nest " + fooBarConstructor + " in " + bar1); |
| } catch (IllegalArgumentException e) { |
| |
| } |
| } |
| |
| |
| @Test |
| public void testFill() { |
| //Fill this shape: Foo{short, Bar{String, Double}}; |
| ResultShape<Foo> foo = new ResultShape<Foo>(Foo.class, new FillStrategy.NewInstance(Foo.class), false); |
| ResultShape<Bar> bar = new ResultShape<Bar>(Bar.class, new FillStrategy.NewInstance(Bar.class), false); |
| bar.add(String.class, Double.class); |
| foo.add(short.class); |
| foo.nest(bar); |
| assertEquals("Foo{short, Bar{String, Double}}", foo.toString()); |
| |
| //from this array: 200s, "bar1", 12.3d) |
| Object[] values = {(short)200, "bar1", 12.3d}; |
| Class[] types = {short.class, String.class, Double.class}; |
| String[] aliases = {"foo-short", "foo-bar-string", "foo-bar-Double"}; |
| Foo result = foo.pack(values, types, aliases); |
| assertEquals(200, result.shrt); |
| assertEquals("bar1", result.b.string); |
| assertEquals(12.3, (double) result.b.Dbl, 0.1d); |
| } |
| |
| @Test |
| public void testFill2() { |
| //Fill this shape: Object[]{Foo, Object, Foo{short, Bar{String, Double}}, Bar{double}}; |
| ResultShape<Object[]> root = new ResultShape<>(Object[].class); |
| ResultShape<Bar> bar1 = new ResultShape<>(Bar.class, new FillStrategy.NewInstance<>(Bar.class)); |
| bar1.add(String.class, Double.class); |
| ResultShape<Foo> fooBarConstr = new ResultShape<>(Foo.class, new FillStrategy.NewInstance<>(Foo.class)); |
| fooBarConstr.add(short.class); |
| fooBarConstr.nest(bar1); |
| ResultShape<Bar> bar2 = new ResultShape<>(Bar.class, new FillStrategy.NewInstance<>(Bar.class)); |
| bar2.add(double.class); |
| root.add(Foo.class, Object.class); |
| root.nest(fooBarConstr); |
| root.nest(bar2); |
| assertEquals("Object[]{Foo, Object, Foo{short, Bar{String, Double}}, Bar{double}}", root.toString()); |
| |
| //from this array: new Foo(), new Object(), 200s, "bar1", 12.3d, 45.6d) |
| Object[] values = {new Foo(), new Object(), 200, "bar1", 12.3d, 45.6d}; |
| Class[] types = {Foo.class, Object.class, short.class, String.class, Double.class, double.class}; |
| String[] aliases = {"Foo", "Object", "foo-short", "foo-bar-string", "foo-bar-Double", "bar-double"}; |
| Object[] result = root.pack(values, types, aliases); |
| |
| assertEquals(4, result.length); |
| assertEquals(Foo.class, result[0].getClass()); |
| assertEquals(Object.class, result[1].getClass()); |
| assertEquals(Foo.class, result[2].getClass()); |
| assertEquals(Bar.class, result[3].getClass()); |
| assertEquals(200, ((Foo)result[2]).shrt); |
| assertEquals("bar1", ((Foo)result[2]).b.string); |
| assertEquals(12.3, (double)((Foo)result[2]).b.Dbl, 0.1d); |
| assertEquals(45.6, ((Bar)result[3]).dbl, 0.1d); |
| } |
| |
| void assertCategory(ResultShape<?> s, boolean primitive, boolean compound, boolean nesting) { |
| if (primitive) |
| assertTrue(s + " is not primitive", s.isPrimitive()); |
| else |
| assertFalse(s + " is primitive", s.isPrimitive()); |
| if (compound) |
| assertTrue(s + " is not compound", s.isCompound()); |
| else |
| assertFalse(s + " is compound", s.isCompound()); |
| if (nesting) |
| assertTrue(s + " is not nesting", s.isNesting()); |
| else |
| assertFalse(s + " is nesting", s.isNesting()); |
| } |
| |
| void arrayEquals(Object[] a, Object[] b) { |
| assertEquals(a.length, b.length); |
| for (int i = 0; i < a.length; i++) { |
| assertEquals(i+"-th element not equal", a[i], b[i]); |
| } |
| } |
| |
| <T> Constructor<T> constructor(Class<T> t, Class<?>...args) { |
| try { |
| return t.getConstructor(args); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| <T> Method method(Class<T> t, String name, Class<?>...args) { |
| try { |
| return t.getMethod(name, args); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| public static class Foo { |
| private String string; |
| private int i; |
| private short shrt; |
| private Bar b; |
| public Foo() {} |
| public Foo(String s, int i) {this.string = s; this.i = i;} |
| public Foo(short s, Bar b){this.shrt = s; this.b = b;} |
| @Override |
| public String toString() { |
| return "Foo(string='"+string+"' i="+i+" short="+shrt+" bar="+b+"";} |
| } |
| |
| public static class Bar { |
| private String string; |
| private Double Dbl; |
| private double dbl; |
| public Bar() {} |
| public Bar(double d) {this.dbl = d;} |
| public Bar(String s, Double i) {this.string = s; this.Dbl = i;} |
| @Override |
| public String toString() {return "Bar(string='"+string+"' Dbl="+Dbl+" dbl="+dbl+"";} |
| } |
| } |