Skip to content

Package: DefaultInstanceBuilder

DefaultInstanceBuilder

nameinstructionbranchcomplexitylinemethod
DefaultInstanceBuilder(CloneBuilderImpl, UnitOfWork)
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, Descriptor)
M: 167 C: 20
11%
M: 15 C: 5
25%
M: 9 C: 2
18%
M: 47 C: 8
15%
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: 2 C: 6
75%
M: 2 C: 3
60%
M: 0 C: 11
100%
M: 0 C: 1
100%
mergeFieldChanges(Object, Object, Class)
M: 0 C: 45
100%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 0 C: 9
100%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2016 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.model.descriptors.Descriptor;
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.ArrayList;
25: import java.util.Collection;
26: import java.util.List;
27:
28: /**
29: * This class has responsibility for creating new instances of various kinds of objects. It handles security
30: * restrictions as well.
31: *
32: * @author kidney
33: */
34: class DefaultInstanceBuilder extends AbstractInstanceBuilder {
35:
36: DefaultInstanceBuilder(CloneBuilderImpl builder, UnitOfWork uow) {
37: super(builder, uow);
38: }
39:
40: /**
41: * Builds a new instance of the specified class.
42: *
43: * @return New object of the given class.
44: */
45: @Override
46: Object buildClone(Object cloneOwner, Field field, Object original, Descriptor repository) {
47:• if (original == null) {
48: return null;
49: }
50: final Class<?> javaClass = original.getClass();
51:• if (CloneBuilderImpl.isImmutable(javaClass)) {
52: return original;
53: }
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
78: .doPrivileged(new PrivilegedInstanceCreator(c));
79: } catch (PrivilegedActionException ex) {
80: throw new OWLPersistenceException(ex);
81: }
82:• if (newInstance != null) {
83: return newInstance;
84: }
85: } catch (NoSuchFieldException e) {
86: throw new OWLPersistenceException(e);
87: }
88: }
89: }
90: Class<?>[] args = new Class<?>[fieldClasses.size()];
91: args = fieldClasses.toArray(args);
92: c = getDeclaredConstructorFor(javaClass, args);
93:• if (c != null) {
94: Object[] params = new Object[args.length];
95:• for (int i = 0; i < params.length; i++) {
96: params[i] = null;
97: }
98: try {
99: newInstance = c.newInstance(params);
100: } catch (SecurityException e) {
101: logConstructorAccessException(c, e);
102: try {
103: newInstance = AccessController
104: .doPrivileged(new PrivilegedInstanceCreator(c));
105: } catch (PrivilegedActionException ex) {
106: throw new OWLPersistenceException(ex);
107: }
108: }
109: }
110: } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
111: throw new OWLPersistenceException(e);
112: }
113: }
114:• if (newInstance == null) {
115: throw new OWLPersistenceException(
116: "Unable to create a new object or to find a suitable constructor for class "
117: + javaClass.getName());
118: }
119: return newInstance;
120: }
121:
122: @Override
123: void mergeChanges(Field field, Object target, Object originalValue, Object cloneValue) {
124:• if (originalValue == null) {
125: Object clOrig = builder.getOriginal(cloneValue);
126:• if (clOrig == null) {
127: clOrig = cloneValue;
128: }
129: EntityPropertiesUtils.setFieldValue(field, target, clOrig);
130: return;
131: }
132: Class<?> cls = originalValue.getClass();
133:• if (builder.isTypeManaged(cls) && builder.getOriginal(cloneValue) != null) {
134: EntityPropertiesUtils.setFieldValue(field, target, builder.getOriginal(cloneValue));
135: } else {
136: mergeFieldChanges(originalValue, cloneValue, cls);
137: }
138: }
139:
140: private void mergeFieldChanges(Object originalValue, Object cloneValue, Class<?> cls) {
141: List<Field> fields = EntityPropertiesUtils.getAllFields(cls);
142:• for (Field f : fields) {
143: Object clVal = EntityPropertiesUtils.getFieldValue(f, cloneValue);
144: Object origVal = EntityPropertiesUtils.getFieldValue(f, originalValue);
145:• if (!(clVal instanceof Collection) && !builder.isOriginalInUoW(origVal)) {
146: EntityPropertiesUtils.setFieldValue(f, originalValue, clVal);
147: } else {
148: builder.getInstanceBuilder(origVal).mergeChanges(f, originalValue, origVal, clVal);
149: }
150: }
151: }
152:
153: /**
154: * Builds a new instance of the specified class, using its no-argument constructor.
155: *
156: * @return New object of the given class, or null if the class has no no-argument constructor.
157: */
158: private Object buildNewInstanceUsingDefaultConstructor(final Class<?> javaClass) {
159: final Constructor<?> c = getDeclaredConstructorFor(javaClass, null);
160: Object newInstance = null;
161:• if (c != null) {
162: try {
163: try {
164: newInstance = c.newInstance((Object[]) null);
165: } catch (SecurityException e) {
166: logConstructorAccessException(c, e);
167: try {
168: newInstance = AccessController
169: .doPrivileged(new PrivilegedInstanceCreator(c));
170: } catch (PrivilegedActionException ex) {
171: logPrivilegedConstructorAccessException(c, ex);
172: return null;
173: }
174: }
175: } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
176: LOG.trace("Class does not have suitable no-arg constructor. {}", e);
177: // Do nothing
178: }
179: }
180: return newInstance;
181: }
182: }