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, CloneConfiguration)
M: 167 C: 20
11%
M: 15 C: 5
25%
M: 9 C: 2
18%
M: 45 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: 2 C: 41
95%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 1 C: 10
91%
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%

Coverage

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