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