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