Skip to content

Package: DefaultInstanceBuilder

DefaultInstanceBuilder

nameinstructionbranchcomplexitylinemethod
DefaultInstanceBuilder(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: 165 C: 17
9%
M: 14 C: 4
22%
M: 8 C: 2
20%
M: 44 C: 7
14%
M: 0 C: 1
100%
buildNewInstanceUsingDefaultConstructor(Class)
M: 22 C: 17
44%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 10 C: 7
41%
M: 0 C: 1
100%
mergeChanges(Field, Object, Object, Object)
M: 0 C: 43
100%
M: 1 C: 7
88%
M: 1 C: 4
80%
M: 0 C: 11
100%
M: 0 C: 1
100%
mergeFieldChanges(Object, Object, Class)
M: 9 C: 36
80%
M: 2 C: 4
67%
M: 2 C: 2
50%
M: 1 C: 8
89%
M: 0 C: 1
100%
static {...}
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
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.exceptions.OWLPersistenceException;
16: import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
17: import org.slf4j.Logger;
18: import org.slf4j.LoggerFactory;
19:
20: import java.lang.reflect.Constructor;
21: import java.lang.reflect.Field;
22: import java.lang.reflect.InvocationTargetException;
23: import java.security.AccessController;
24: import java.security.PrivilegedActionException;
25: import java.util.ArrayList;
26: import java.util.Collection;
27: import java.util.List;
28:
29: /**
30: * This class has responsibility for creating new instances of various kinds of objects. It handles security
31: * restrictions as well.
32: */
33: class DefaultInstanceBuilder extends AbstractInstanceBuilder {
34:
35: private static final Logger LOG = LoggerFactory.getLogger(DefaultInstanceBuilder.class);
36:
37: DefaultInstanceBuilder(CloneBuilderImpl builder, UnitOfWorkImpl uow) {
38: super(builder, uow);
39: }
40:
41: /**
42: * Builds a new instance of the specified class.
43: *
44: * @return New object of the given class.
45: */
46: @Override
47: Object buildClone(Object cloneOwner, Field field, Object original, CloneConfiguration config) {
48:• if (CloneBuilderImpl.isImmutable(original)) {
49: return original;
50: }
51: final Class<?> javaClass = original.getClass();
52: Object newInstance = buildNewInstanceUsingDefaultConstructor(javaClass);
53:• if (newInstance == null) {
54: final Field[] fields = javaClass.getDeclaredFields();
55: List<Class<?>> fieldClasses = new ArrayList<>();
56: Constructor<?> c;
57: try {
58:• for (Field f : fields) {
59:• if (EntityPropertiesUtils.isFieldTransient(f)) {
60: continue;
61: }
62: Class<?>[] args = {f.getType()};
63: c = getDeclaredConstructorFor(javaClass, args);
64:• if (c == null) {
65: fieldClasses.add(f.getType());
66: } else {
67: try {
68: Object[] params = new Object[1];
69: params[0] = original.getClass().getDeclaredField(f.getName());
70: newInstance = c.newInstance(params);
71: return newInstance;
72: } catch (SecurityException e) {
73: logConstructorAccessException(c, e);
74: try {
75: newInstance = AccessController.doPrivileged(new PrivilegedInstanceCreator(c));
76: } catch (PrivilegedActionException ex) {
77: throw new OWLPersistenceException(ex);
78: }
79:• if (newInstance != null) {
80: return newInstance;
81: }
82: } catch (NoSuchFieldException e) {
83: throw new OWLPersistenceException(e);
84: }
85: }
86: }
87: Class<?>[] args = new Class<?>[fieldClasses.size()];
88: args = fieldClasses.toArray(args);
89: c = getDeclaredConstructorFor(javaClass, args);
90:• if (c != null) {
91: Object[] params = new Object[args.length];
92:• for (int i = 0; i < params.length; i++) {
93: params[i] = null;
94: }
95: try {
96: newInstance = c.newInstance(params);
97: } catch (SecurityException e) {
98: logConstructorAccessException(c, e);
99: try {
100: newInstance = AccessController.doPrivileged(new PrivilegedInstanceCreator(c));
101: } catch (PrivilegedActionException ex) {
102: throw new OWLPersistenceException(ex);
103: }
104: }
105: }
106: } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
107: throw new OWLPersistenceException(e);
108: }
109: }
110:• if (newInstance == null) {
111: throw new OWLPersistenceException(
112: "Unable to create a new object or to find a suitable constructor for class "
113: + javaClass.getName());
114: }
115: return newInstance;
116: }
117:
118: @Override
119: void mergeChanges(Field field, Object target, Object originalValue, Object cloneValue) {
120:• if (originalValue == null) {
121: Object clOrig = builder.getOriginal(cloneValue);
122:• if (clOrig == null) {
123: clOrig = cloneValue;
124: }
125: EntityPropertiesUtils.setFieldValue(field, target, clOrig);
126: return;
127: }
128: Class<?> cls = originalValue.getClass();
129:• if (builder.isTypeManaged(cls) && builder.getOriginal(cloneValue) != null) {
130: EntityPropertiesUtils.setFieldValue(field, target, builder.getOriginal(cloneValue));
131: } else {
132: mergeFieldChanges(originalValue, cloneValue, cls);
133: }
134: }
135:
136: private void mergeFieldChanges(Object originalValue, Object cloneValue, Class<?> cls) {
137: List<Field> fields = EntityPropertiesUtils.getAllFields(cls);
138:• for (Field f : fields) {
139: Object clVal = EntityPropertiesUtils.getFieldValue(f, cloneValue);
140: Object origVal = EntityPropertiesUtils.getFieldValue(f, originalValue);
141:• if (!(clVal instanceof Collection) && !builder.isOriginalInUoW(origVal)) {
142: EntityPropertiesUtils.setFieldValue(f, originalValue, clVal);
143: } else {
144: builder.getInstanceBuilder(origVal).mergeChanges(f, originalValue, origVal, clVal);
145: }
146: }
147: }
148:
149: /**
150: * Builds a new instance of the specified class, using its no-argument constructor.
151: *
152: * @return New object of the given class, or null if the class has no no-argument constructor.
153: */
154: private static Object buildNewInstanceUsingDefaultConstructor(final Class<?> javaClass) {
155: final Constructor<?> c = getDeclaredConstructorFor(javaClass, null);
156: Object newInstance = null;
157:• if (c != null) {
158: try {
159: try {
160: newInstance = c.newInstance((Object[]) null);
161: } catch (SecurityException e) {
162: logConstructorAccessException(c, e);
163: try {
164: newInstance = AccessController
165: .doPrivileged(new PrivilegedInstanceCreator(c));
166: } catch (PrivilegedActionException ex) {
167: logPrivilegedConstructorAccessException(c, ex);
168: return null;
169: }
170: }
171: } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
172: LOG.trace("Class does not have suitable no-arg constructor. {}", e);
173: // Do nothing
174: }
175: }
176: return newInstance;
177: }
178: }