Skip to content

Method: addOtherProperties(PropertiesSpecification)

1: /**
2: * Copyright (C) 2019 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.model.metamodel;
16:
17: import java.lang.reflect.Modifier;
18: import java.util.*;
19: import java.util.stream.Collectors;
20:
21: public abstract class AbstractIdentifiableType<X> implements IdentifiableType<X> {
22:
23: private final Class<X> javaType;
24:
25: private Identifier<X, ?> identifier;
26:
27: private AbstractIdentifiableType<? super X> supertype;
28:
29: private Set<AbstractIdentifiableType<? extends X>> subtypes;
30:
31: private TypesSpecification<X, ?> directTypes;
32:
33: private PropertiesSpecification<X, ?, ?, ?> properties;
34:
35: private final Map<String, AbstractAttribute<X, ?>> declaredAttributes = new HashMap<>();
36:
37: private EntityLifecycleListenerManager lifecycleListenerManager = EntityLifecycleListenerManager.empty();
38:
39: AbstractIdentifiableType(Class<X> javaType) {
40: this.javaType = javaType;
41: }
42:
43: void addDeclaredAttribute(final String name, final AbstractAttribute<X, ?> a) {
44: declaredAttributes.put(name, a);
45: }
46:
47: void setSupertype(AbstractIdentifiableType<? super X> supertype) {
48: assert supertype != null;
49: this.supertype = supertype;
50: supertype.addSubtype(this);
51: }
52:
53: private void addSubtype(AbstractIdentifiableType<? extends X> subtype) {
54: if (subtypes == null) {
55: this.subtypes = new HashSet<>(2);
56: }
57: subtypes.add(subtype);
58: }
59:
60: void addDirectTypes(TypesSpecification<X, ?> a) {
61: this.directTypes = a;
62: }
63:
64: void addOtherProperties(PropertiesSpecification<X, ?, ?, ?> a) {
65: this.properties = a;
66: }
67:
68: public void setIdentifier(final Identifier<X, ?> identifier) {
69: this.identifier = identifier;
70: }
71:
72: @Override
73: public boolean hasSingleIdAttribute() {
74: return true; // We do not support id classes
75: }
76:
77: @Override
78: public <Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type) {
79: // TODO
80: throw new UnsupportedOperationException();
81: }
82:
83: @Override
84: public AbstractIdentifiableType<? super X> getSupertype() {
85: return supertype;
86: }
87:
88: /**
89: * Whether this managed type has any managed subtypes (entities or mapped superclasses).
90: *
91: * @return {@code true} when managed subtypes exist, {@code false} otherwise
92: */
93: public boolean hasSubtypes() {
94: return subtypes != null;
95: }
96:
97: /**
98: * Whether the Java type represented by this type is an abstract class.
99: *
100: * @return {@code true} if the represented Java type is abstract, {@code false} otherwise
101: */
102: public boolean isAbstract() {
103: return Modifier.isAbstract(javaType.getModifiers());
104: }
105:
106: public Set<AbstractIdentifiableType<? extends X>> getSubtypes() {
107: return subtypes != null ? Collections.unmodifiableSet(subtypes) : Collections.emptySet();
108: }
109:
110: @Override
111: public <Y> SingularAttribute<? super X, Y> getVersion(Class<Y> type) {
112: // TODO
113: throw new UnsupportedOperationException();
114: }
115:
116: @Override
117: public boolean hasVersionAttribute() {
118: return false;
119: }
120:
121: @Override
122: public Set<Attribute<? super X, ?>> getAttributes() {
123: final Set<Attribute<? super X, ?>> attributes = new HashSet<>(declaredAttributes.values());
124: if (supertype != null) {
125: attributes.addAll(supertype.getAttributes());
126: }
127: return attributes;
128: }
129:
130: @Override
131: public AbstractAttribute<? super X, ?> getAttribute(String name) {
132: Objects.requireNonNull(name);
133: if (declaredAttributes.containsKey(name)) {
134: return declaredAttributes.get(name);
135: }
136: if (supertype != null) {
137: return supertype.getAttribute(name);
138: }
139: throw new IllegalArgumentException("Attribute " + name + " is not present in type " + this.toString());
140: }
141:
142: @Override
143: public CollectionAttribute<? super X, ?> getCollection(String name) {
144: return getCollection(name, Object.class);
145: }
146:
147: @Override
148: public <E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType) {
149: return getPluralAttribute("Collection", name, elementType, CollectionAttribute.class);
150: }
151:
152: private <E, R extends PluralAttribute<? super X, ?, E>> R getPluralAttribute(String type, String name,
153: Class<E> elementType,
154: Class<R> attType) {
155: final Attribute<? super X, ?> a = getAttribute(name);
156:
157: checkPluralAttribute(a, type, name, elementType, attType, false);
158: return attType.cast(a);
159: }
160:
161: private <E, R extends PluralAttribute<? super X, ?, E>> void checkPluralAttribute(Attribute<? super X, ?> att,
162: String type, String name,
163: Class<E> elementType,
164: Class<R> attType,
165: boolean declared) {
166: if (!attType.isAssignableFrom(att.getClass())) {
167: throw pluralAttNotFound(type, name, elementType, declared);
168: }
169:
170: final PluralAttribute<? super X, ?, E> colAtt = (PluralAttribute<? super X, ?, E>) att;
171: if (!elementType.isAssignableFrom(colAtt.getBindableJavaType())) {
172: throw pluralAttNotFound(type, name, elementType, declared);
173: }
174: }
175:
176: private IllegalArgumentException pluralAttNotFound(String type, String name, Class<?> elementType,
177: boolean declared) {
178: return new IllegalArgumentException(type + " attribute " + name + " with element type " + elementType +
179: " is not " + (declared ? "declared" : "present") + " in type " + this);
180: }
181:
182: @Override
183: public <E> ListAttribute<? super X, E> getList(String name, Class<E> elementType) {
184: return getPluralAttribute("List", name, elementType, ListAttribute.class);
185: }
186:
187: @Override
188: public ListAttribute<? super X, ?> getList(String name) {
189: return getList(name, Object.class);
190: }
191:
192: @Override
193: public <K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, Class<V> valueType) {
194: throw new UnsupportedOperationException();
195: }
196:
197: @Override
198: public MapAttribute<? super X, ?, ?> getMap(String name) {
199: return getMap(name, Object.class, Object.class);
200: }
201:
202: @Override
203: public <E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType) {
204: return getPluralAttribute("Set", name, elementType, SetAttribute.class);
205: }
206:
207: @Override
208: public SetAttribute<? super X, ?> getSet(String name) {
209: return getSet(name, Object.class);
210: }
211:
212: @Override
213: public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
214: final Set<PluralAttribute<? super X, ?, ?>> plurals = new HashSet<>(getDeclaredPluralAttributes());
215: if (supertype != null) {
216: plurals.addAll(supertype.getPluralAttributes());
217: }
218: return plurals;
219: }
220:
221: @Override
222: public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
223: final Set<SingularAttribute<? super X, ?>> singulars = new HashSet<>(getDeclaredSingularAttributes());
224: if (supertype != null) {
225: singulars.addAll(supertype.getSingularAttributes());
226: }
227: return singulars;
228: }
229:
230: @Override
231: public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) {
232: final Attribute<? super X, ?> a = getAttribute(name);
233:
234: if (a.isCollection()) {
235: throw singularAttNotFound(name, type, false);
236: }
237: assert a instanceof SingularAttribute;
238: if (!type.isAssignableFrom(a.getJavaType())) {
239: throw singularAttNotFound(name, type, false);
240: }
241:
242: return (SingularAttribute<? super X, Y>) a;
243: }
244:
245: private IllegalArgumentException singularAttNotFound(String name, Class<?> type, boolean declared) {
246: return new IllegalArgumentException(
247: "Singular attribute " + name + " of type " + type + " is not " + (declared ? "declared" : "present") +
248: " in type " + this);
249: }
250:
251: @Override
252: public SingularAttribute<? super X, ?> getSingularAttribute(String name) {
253: return getSingularAttribute(name, Object.class);
254: }
255:
256: @Override
257: public Set<Attribute<X, ?>> getDeclaredAttributes() {
258: return new HashSet<>(declaredAttributes.values());
259: }
260:
261: @Override
262: public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
263: return declaredAttributes.values().stream().filter(Attribute::isCollection)
264: .map(a -> (PluralAttribute<X, ?, ?>) a).collect(Collectors.toSet());
265: }
266:
267: @Override
268: public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
269: return declaredAttributes.values().stream().filter(att -> !att.isCollection()).map(
270: a -> (SingularAttribute<X, ?>) a).collect(Collectors.toSet());
271: }
272:
273: @Override
274: public AbstractAttribute<X, ?> getDeclaredAttribute(String name) {
275: if (declaredAttributes.containsKey(name)) {
276: return declaredAttributes.get(name);
277: }
278: throw new IllegalArgumentException("Attribute " + name + " is not declared in type " + name);
279: }
280:
281: @Override
282: public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) {
283: return getDeclaredPluralAttribute("Collection", name, elementType, CollectionAttribute.class);
284: }
285:
286: private <E, R extends PluralAttribute<? super X, ?, E>> R getDeclaredPluralAttribute(String type, String name,
287: Class<E> elementType,
288: Class<R> attType) {
289: final Attribute<? super X, ?> a = getDeclaredAttribute(name);
290:
291: checkPluralAttribute(a, type, name, elementType, attType, true);
292: return attType.cast(a);
293: }
294:
295: @Override
296: public CollectionAttribute<X, ?> getDeclaredCollection(String name) {
297: return getDeclaredCollection(name, Object.class);
298: }
299:
300: @Override
301: public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) {
302: return getDeclaredPluralAttribute("List", name, elementType, ListAttribute.class);
303: }
304:
305: @Override
306: public ListAttribute<X, ?> getDeclaredList(String name) {
307: return getDeclaredList(name, Object.class);
308: }
309:
310: @Override
311: public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType) {
312: throw new UnsupportedOperationException();
313: }
314:
315: @Override
316: public MapAttribute<X, ?, ?> getDeclaredMap(String name) {
317: return getDeclaredMap(name, Object.class, Object.class);
318: }
319:
320: @Override
321: public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) {
322: return getDeclaredPluralAttribute("Set", name, elementType, SetAttribute.class);
323: }
324:
325: @Override
326: public SetAttribute<X, ?> getDeclaredSet(String name) {
327: return getDeclaredSet(name, Object.class);
328: }
329:
330: @Override
331: public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> type) {
332: final Attribute<X, ?> a = getDeclaredAttribute(name);
333:
334: if (a.isCollection()) {
335: throw singularAttNotFound(name, type, true);
336: }
337: if (!type.isAssignableFrom(a.getJavaType())) {
338: throw singularAttNotFound(name, type, true);
339: }
340:
341: return (SingularAttribute<X, Y>) a;
342: }
343:
344: @Override
345: public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) {
346: return getDeclaredSingularAttribute(name, Object.class);
347: }
348:
349: @Override
350: public TypesSpecification<? super X, ?> getTypes() {
351: if (directTypes != null) {
352: return directTypes;
353: }
354: return supertype != null ? supertype.getTypes() : null;
355: }
356:
357: @Override
358: public PropertiesSpecification<? super X, ?, ?, ?> getProperties() {
359: if (properties != null) {
360: return properties;
361: }
362: return supertype != null ? supertype.getProperties() : null;
363: }
364:
365: @Override
366: public Set<FieldSpecification<? super X, ?>> getFieldSpecifications() {
367: final Set<FieldSpecification<? super X, ?>> specs = new HashSet<>(getAttributes());
368: final TypesSpecification<? super X, ?> types = getTypes();
369: if (types != null) {
370: specs.add(types);
371: }
372: final PropertiesSpecification<? super X, ?, ?, ?> props = getProperties();
373: if (props != null) {
374: specs.add(props);
375: }
376: specs.add(getIdentifier());
377: return specs;
378: }
379:
380: @Override
381: public FieldSpecification<? super X, ?> getFieldSpecification(String fieldName) {
382: if (declaredAttributes.containsKey(fieldName)) {
383: return declaredAttributes.get(fieldName);
384: }
385: if (directTypes != null && directTypes.getName().equals(fieldName)) {
386: return directTypes;
387: } else if (properties != null && properties.getName().equals(fieldName)) {
388: return properties;
389: } else if (identifier != null && identifier.getName().equals(fieldName)) {
390: return identifier;
391: }
392: if (supertype != null) {
393: return supertype.getFieldSpecification(fieldName);
394: }
395: throw new IllegalArgumentException("Field " + fieldName + " is not present in type " + this);
396: }
397:
398: @Override
399: public Identifier<? super X, ?> getIdentifier() {
400: if (identifier != null) {
401: return identifier;
402: }
403: if (supertype != null) {
404: return supertype.getIdentifier();
405: }
406: // This shouldn't happen, because every entity has to contain an identifier, otherwise metamodel building fails
407: throw new IllegalArgumentException("Identifier attribute is not present in type " + this);
408: }
409:
410: @Override
411: public Class<X> getJavaType() {
412: return javaType;
413: }
414:
415: public EntityLifecycleListenerManager getLifecycleListenerManager() {
416: return lifecycleListenerManager;
417: }
418:
419: public void setLifecycleListenerManager(EntityLifecycleListenerManager lifecycleListenerManager) {
420: this.lifecycleListenerManager = lifecycleListenerManager;
421: }
422: }