Skip to content

Package: MapInstanceBuilder

MapInstanceBuilder

nameinstructionbranchcomplexitylinemethod
MapInstanceBuilder(CloneBuilderImpl, UnitOfWorkImpl)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
buildClone(Object, Field, Object, CloneConfiguration)
M: 12 C: 46
79%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 1 C: 10
91%
M: 0 C: 1
100%
buildSingletonClone(Object, Field, Map, CloneConfiguration)
M: 13 C: 40
75%
M: 5 C: 3
38%
M: 4 C: 1
20%
M: 0 C: 8
100%
M: 0 C: 1
100%
cloneMapContent(Object, Field, Map, Map, CloneConfiguration)
M: 25 C: 54
68%
M: 4 C: 6
60%
M: 3 C: 3
50%
M: 4 C: 14
78%
M: 0 C: 1
100%
cloneObject(Object, Field, Object, CloneConfiguration)
M: 13 C: 19
59%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 2 C: 4
67%
M: 0 C: 1
100%
cloneUsingDefaultConstructor(Object, Field, Class, Map, CloneConfiguration)
M: 0 C: 16
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
createDefaultMap(int)
M: 10 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
createNewInstance(Class, int)
M: 22 C: 42
66%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 9 C: 13
59%
M: 0 C: 1
100%
mergeChanges(Field, Object, Object, Object)
M: 23 C: 81
78%
M: 6 C: 14
70%
M: 6 C: 5
45%
M: 2 C: 20
91%
M: 0 C: 1
100%
populatesAttributes()
M: 0 C: 2
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.sessions;
14:
15: import cz.cvut.kbss.jopa.adapters.IndirectCollection;
16: import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
17: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
18:
19: import java.lang.reflect.Constructor;
20: import java.lang.reflect.Field;
21: import java.lang.reflect.InvocationTargetException;
22: import java.security.AccessController;
23: import java.security.PrivilegedActionException;
24: import java.util.Collection;
25: import java.util.Collections;
26: import java.util.HashMap;
27: import java.util.Map;
28: import java.util.Map.Entry;
29:
30: class MapInstanceBuilder extends AbstractInstanceBuilder {
31:
32: private static final Class<?> singletonMapClass = Collections.singletonMap(null, null)
33: .getClass();
34:
35: MapInstanceBuilder(CloneBuilderImpl builder, UnitOfWorkImpl uow) {
36: super(builder, uow);
37: }
38:
39: @Override
40: Object buildClone(Object cloneOwner, Field field, Object original, CloneConfiguration configuration) {
41: Map<?, ?> orig = (Map<?, ?>) original;
42:• if (original instanceof IndirectCollection) {
43: orig = ((IndirectCollection<Map<?, ?>>) original).unwrap();
44: }
45: final Class<?> origCls = orig.getClass();
46: Map<?, ?> clone;
47: clone = cloneUsingDefaultConstructor(cloneOwner, field, origCls, orig, configuration);
48:• if (clone == null) {
49:• if (singletonMapClass.isInstance(orig)) {
50: clone = buildSingletonClone(cloneOwner, field, orig, configuration);
51: } else {
52: throw new IllegalArgumentException("Unsupported map type " + origCls);
53: }
54: }
55: clone = (Map<?, ?>) uow.createIndirectCollection(clone, cloneOwner, field);
56: return clone;
57:
58: }
59:
60: private Map<?, ?> cloneUsingDefaultConstructor(Object cloneOwner, Field field, Class<?> origCls, Map<?, ?> original,
61: CloneConfiguration configuration) {
62: Map<?, ?> result = createNewInstance(origCls, original.size());
63:• if (result != null) {
64: cloneMapContent(cloneOwner, field, original, result, configuration);
65: }
66: return result;
67: }
68:
69: private static Map<?, ?> createNewInstance(Class<?> type, int size) {
70: Map<?, ?> result = null;
71: final Class<?>[] types = {int.class};
72: Object[] params;
73: Constructor<?> c = getDeclaredConstructorFor(type, types);
74:• if (c != null) {
75: params = new Object[1];
76: params[0] = size;
77: } else {
78: c = getDeclaredConstructorFor(type, null);
79: params = null;
80: }
81:• if (c == null) {
82: return null;
83: }
84: try {
85: result = (Map<?, ?>) c.newInstance(params);
86: } catch (InstantiationException | IllegalArgumentException | InvocationTargetException e) {
87: throw new OWLPersistenceException(e);
88: } catch (IllegalAccessException e) {
89: logConstructorAccessException(c, e);
90: try {
91: result = (Map<?, ?>) AccessController
92: .doPrivileged(new PrivilegedInstanceCreator(c));
93: } catch (PrivilegedActionException ex) {
94: logPrivilegedConstructorAccessException(c, ex);
95: // Do nothing
96: }
97: }
98: return result;
99: }
100:
101: private Map<?, ?> buildSingletonClone(Object cloneOwner, Field field, Map<?, ?> orig,
102: CloneConfiguration configuration) {
103: Entry<?, ?> e = orig.entrySet().iterator().next();
104:• Object key = CloneBuilderImpl.isImmutable(e.getKey()) ? e.getKey() :
105: cloneObject(cloneOwner, field, e.getKey(), configuration);
106:• Object value = CloneBuilderImpl.isImmutable(e.getValue()) ? e.getValue() :
107: cloneObject(cloneOwner, field, e.getValue(), configuration);
108:• if (value instanceof Collection || value instanceof Map) {
109: value = uow.createIndirectCollection(value, cloneOwner, field);
110: }
111: return Collections.singletonMap(key, value);
112: }
113:
114: private void cloneMapContent(Object cloneOwner, Field field, Map<?, ?> source,
115: Map<?, ?> target, CloneConfiguration configuration) {
116:• if (source.isEmpty()) {
117: return;
118: }
119: final Map<Object, Object> m = (Map<Object, Object>) target;
120: final Entry<?, ?> tmp = source.entrySet().iterator().next();
121: // Note: If we encounter null -> null mapping first, the whole map will be treated as immutable type map, which can be incorrect
122: final boolean keyPrimitive = CloneBuilderImpl.isImmutable(tmp.getKey());
123: final boolean valuePrimitive = CloneBuilderImpl.isImmutable(tmp.getValue());
124:• for (Entry<?, ?> e : source.entrySet()) {
125: Object key;
126: Object value;
127:• if (keyPrimitive) {
128:• if (valuePrimitive) {
129: m.putAll(source);
130: break;
131: }
132: key = e.getKey();
133: value = cloneObject(cloneOwner, field, e.getValue(), configuration);
134: } else {
135: key = cloneObject(cloneOwner, field, e.getKey(), configuration);
136:• value = valuePrimitive ? e.getValue() : cloneObject(cloneOwner, field, e.getValue(), configuration);
137: }
138: m.put(key, value);
139: }
140: }
141:
142: private Object cloneObject(Object owner, Field field, Object obj, CloneConfiguration configuration) {
143: Object clone;
144:• if (obj == null) {
145: clone = null;
146:• } else if (builder.isTypeManaged(obj.getClass())) {
147: clone = uow.registerExistingObject(obj, configuration.getDescriptor(), configuration.getPostRegister());
148: } else {
149: clone = builder.buildClone(owner, field, obj, configuration.getDescriptor());
150: }
151: return clone;
152: }
153:
154: @Override
155: void mergeChanges(Field field, Object target, Object originalValue, Object cloneValue) {
156:• assert (originalValue == null) || (originalValue instanceof Map);
157:• assert cloneValue instanceof Map;
158:
159: Map<Object, Object> orig = (Map<Object, Object>) originalValue;
160: Map<Object, Object> clone = (Map<Object, Object>) cloneValue;
161:• if (clone instanceof IndirectCollection) {
162: clone = ((IndirectCollection<Map<Object, Object>>) clone).unwrap();
163: }
164:• if (orig == null) {
165: orig = (Map<Object, Object>) createNewInstance(clone.getClass(), clone.size());
166:• if (orig == null) {
167: orig = createDefaultMap(clone.size());
168: }
169: EntityPropertiesUtils.setFieldValue(field, target, orig);
170: }
171: orig.clear();
172:• if (clone.isEmpty()) {
173: return;
174: }
175:• for (Entry<?, ?> e : clone.entrySet()) {
176: final Object key = e.getKey();
177: final Object value = e.getValue();
178:• final Object keyToPut = uow.contains(key) ? builder.getOriginal(key) : key;
179:• final Object valueToPut = uow.contains(value) ? builder.getOriginal(value) : value;
180: orig.put(keyToPut, valueToPut);
181: }
182: }
183:
184: private static Map<Object, Object> createDefaultMap(int size) {
185:• return new HashMap<>(size > 1 ? size : 16);
186: }
187:
188: @Override
189: boolean populatesAttributes() {
190: return true;
191: }
192: }