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