Skip to content

Method: getSet(String)

1: /**
2: * Copyright (C) 2016 Czech Technical University in Prague
3: * <p>
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: * <p>
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 cz.cvut.kbss.jopa.model.lifecycle.LifecycleEvent;
18:
19: import java.lang.reflect.Method;
20: import java.lang.reflect.Modifier;
21: import java.util.*;
22: import java.util.stream.Collectors;
23:
24: public abstract class AbstractIdentifiableType<X> implements IdentifiableType<X> {
25:
26: private final Class<X> javaType;
27:
28: private Identifier identifier;
29:
30: private AbstractIdentifiableType<? super X> supertype;
31:
32: private final Set<AbstractIdentifiableType<? extends X>> subtypes = new HashSet<>(2);
33:
34: private TypesSpecification<X, ?> directTypes;
35:
36: private PropertiesSpecification<X, ?, ?, ?> properties;
37:
38: private final Map<String, Attribute<X, ?>> declaredAttributes = new HashMap<>();
39:
40: private EntityLifecycleListenerManager lifecycleListenerManager = EntityLifecycleListenerManager.empty();
41:
42: AbstractIdentifiableType(Class<X> javaType) {
43: this.javaType = javaType;
44: }
45:
46: void addDeclaredAttribute(final String name, final Attribute<X, ?> a) {
47: declaredAttributes.put(name, a);
48: }
49:
50: void setSupertype(AbstractIdentifiableType<? super X> supertype) {
51: assert supertype != null;
52: this.supertype = supertype;
53: supertype.addSubtype(this);
54: }
55:
56: private void addSubtype(AbstractIdentifiableType<? extends X> subtype) {
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 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.isEmpty();
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 Collections.unmodifiableSet(subtypes);
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 Attribute<? 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<>();
215: plurals.addAll(getDeclaredPluralAttributes());
216: if (supertype != null) {
217: plurals.addAll(supertype.getPluralAttributes());
218: }
219: return plurals;
220: }
221:
222: @Override
223: public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
224: final Set<SingularAttribute<? super X, ?>> singulars = new HashSet<>();
225: singulars.addAll(getDeclaredSingularAttributes());
226: if (supertype != null) {
227: singulars.addAll(supertype.getSingularAttributes());
228: }
229: return singulars;
230: }
231:
232: @Override
233: public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) {
234: final Attribute<? super X, ?> a = getAttribute(name);
235:
236: if (a.isCollection()) {
237: throw singularAttNotFound(name, type, false);
238: }
239: assert a instanceof SingularAttribute;
240: if (!type.isAssignableFrom(a.getJavaType())) {
241: throw singularAttNotFound(name, type, false);
242: }
243:
244: return (SingularAttribute<? super X, Y>) a;
245: }
246:
247: private IllegalArgumentException singularAttNotFound(String name, Class<?> type, boolean declared) {
248: return new IllegalArgumentException(
249: "Singular attribute " + name + " of type " + type + " is not " + (declared ? "declared" : "present") +
250: " in type " + this);
251: }
252:
253: @Override
254: public SingularAttribute<? super X, ?> getSingularAttribute(String name) {
255: return getSingularAttribute(name, Object.class);
256: }
257:
258: @Override
259: public Set<Attribute<X, ?>> getDeclaredAttributes() {
260: return new HashSet<>(declaredAttributes.values());
261: }
262:
263: @Override
264: public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
265: return declaredAttributes.values().stream().filter(Attribute::isCollection)
266: .map(a -> (PluralAttribute<X, ?, ?>) a).collect(Collectors.toSet());
267: }
268:
269: @Override
270: public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
271: return declaredAttributes.values().stream().filter(att -> !att.isCollection()).map(
272: a -> (SingularAttribute<X, ?>) a).collect(Collectors.toSet());
273: }
274:
275: @Override
276: public Attribute<X, ?> getDeclaredAttribute(String name) {
277: if (declaredAttributes.containsKey(name)) {
278: return declaredAttributes.get(name);
279: }
280: throw new IllegalArgumentException("Attribute " + name + " is not declared in type " + name);
281: }
282:
283: @Override
284: public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) {
285: return getDeclaredPluralAttribute("Collection", name, elementType, CollectionAttribute.class);
286: }
287:
288: private <E, R extends PluralAttribute<? super X, ?, E>> R getDeclaredPluralAttribute(String type, String name,
289: Class<E> elementType,
290: Class<R> attType) {
291: final Attribute<? super X, ?> a = getDeclaredAttribute(name);
292:
293: checkPluralAttribute(a, type, name, elementType, attType, true);
294: return attType.cast(a);
295: }
296:
297: @Override
298: public CollectionAttribute<X, ?> getDeclaredCollection(String name) {
299: return getDeclaredCollection(name, Object.class);
300: }
301:
302: @Override
303: public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) {
304: return getDeclaredPluralAttribute("List", name, elementType, ListAttribute.class);
305: }
306:
307: @Override
308: public ListAttribute<X, ?> getDeclaredList(String name) {
309: return getDeclaredList(name, Object.class);
310: }
311:
312: @Override
313: public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, Class<V> valueType) {
314: throw new UnsupportedOperationException();
315: }
316:
317: @Override
318: public MapAttribute<X, ?, ?> getDeclaredMap(String name) {
319: return getDeclaredMap(name, Object.class, Object.class);
320: }
321:
322: @Override
323: public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) {
324: return getDeclaredPluralAttribute("Set", name, elementType, SetAttribute.class);
325: }
326:
327: @Override
328: public SetAttribute<X, ?> getDeclaredSet(String name) {
329: return getDeclaredSet(name, Object.class);
330: }
331:
332: @Override
333: public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> type) {
334: final Attribute<X, ?> a = getDeclaredAttribute(name);
335:
336: if (a.isCollection()) {
337: throw singularAttNotFound(name, type, true);
338: }
339: if (!type.isAssignableFrom(a.getJavaType())) {
340: throw singularAttNotFound(name, type, true);
341: }
342:
343: return (SingularAttribute<X, Y>) a;
344: }
345:
346: @Override
347: public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) {
348: return getDeclaredSingularAttribute(name, Object.class);
349: }
350:
351: @Override
352: public TypesSpecification<? super X, ?> getTypes() {
353: if (directTypes != null) {
354: return directTypes;
355: }
356: return supertype != null ? supertype.getTypes() : null;
357: }
358:
359: @Override
360: public PropertiesSpecification<? super X, ?, ?, ?> getProperties() {
361: if (properties != null) {
362: return properties;
363: }
364: return supertype != null ? supertype.getProperties() : null;
365: }
366:
367: @Override
368: public Set<FieldSpecification<? super X, ?>> getFieldSpecifications() {
369: final Set<FieldSpecification<? super X, ?>> specs = new HashSet<>(getAttributes());
370: final TypesSpecification<? super X, ?> types = getTypes();
371: if (types != null) {
372: specs.add(types);
373: }
374: final PropertiesSpecification<? super X, ?, ?, ?> props = getProperties();
375: if (props != null) {
376: specs.add(props);
377: }
378: return specs;
379: }
380:
381: @Override
382: public FieldSpecification<? super X, ?> getFieldSpecification(String fieldName) {
383: if (declaredAttributes.containsKey(fieldName)) {
384: return declaredAttributes.get(fieldName);
385: }
386: if (directTypes != null && directTypes.getName().equals(fieldName)) {
387: return directTypes;
388: } else if (properties != null && properties.getName().equals(fieldName)) {
389: return properties;
390: }
391: if (supertype != null) {
392: return supertype.getFieldSpecification(fieldName);
393: }
394: throw new IllegalArgumentException("Field " + fieldName + " is not present in type " + this);
395: }
396:
397: @Override
398: public Identifier getIdentifier() {
399: if (identifier != null) {
400: return identifier;
401: }
402: if (supertype != null) {
403: return supertype.getIdentifier();
404: }
405: // This shouldn't happen, because every entity has to contain an identifier, otherwise metamodel building fails
406: throw new IllegalArgumentException("Identifier attribute is not present in type " + this);
407: }
408:
409: @Override
410: public Class<X> getJavaType() {
411: return javaType;
412: }
413:
414: public EntityLifecycleListenerManager getLifecycleListenerManager() {
415: return lifecycleListenerManager;
416: }
417:
418: public void setLifecycleListenerManager(EntityLifecycleListenerManager lifecycleListenerManager) {
419: this.lifecycleListenerManager = lifecycleListenerManager;
420: }
421: }