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