| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.persistence.meta; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.time.LocalDate; |
| import java.time.LocalDateTime; |
| import java.time.LocalTime; |
| import java.time.OffsetDateTime; |
| import java.time.OffsetTime; |
| import java.util.Arrays; |
| import java.util.Calendar; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashSet; |
| import java.util.Locale; |
| import java.util.TreeSet; |
| |
| import javax.persistence.metamodel.Attribute; |
| import javax.persistence.metamodel.CollectionAttribute; |
| import javax.persistence.metamodel.ListAttribute; |
| import javax.persistence.metamodel.ManagedType; |
| import javax.persistence.metamodel.MapAttribute; |
| import javax.persistence.metamodel.PluralAttribute; |
| import javax.persistence.metamodel.PluralAttribute.CollectionType; |
| import javax.persistence.metamodel.SetAttribute; |
| import javax.persistence.metamodel.SingularAttribute; |
| |
| import org.apache.openjpa.conf.Compatibility; |
| import org.apache.openjpa.kernel.Filters; |
| import org.apache.openjpa.lib.util.Localizer; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.meta.FieldMetaData; |
| import org.apache.openjpa.meta.JavaTypes; |
| |
| /** |
| * Implements the managed persistent type and its attributes. |
| * |
| * Provides identity and version attribute facilities for Identifiable type but does not |
| * implement it. |
| * |
| * @author Pinaki Poddar |
| * |
| * @param <X> the |
| */ |
| public abstract class AbstractManagedType<X> extends Types.BaseType<X> |
| implements ManagedType<X> { |
| |
| private static final Localizer _loc = Localizer.forPackage(AbstractManagedType.class); |
| public final MetamodelImpl model; |
| public final ClassMetaData meta; |
| |
| private java.util.Set<Attribute<? super X, ?>> attrs = new HashSet<>(); |
| |
| private final DeclaredAttributeFilter<X> declaredAttributeFilter; |
| private final SingularAttributeFilter<X> singularAttributeFilter; |
| private final SingularAttributeFilter<X> pluralAttributeFilter; |
| |
| /** |
| * A protected constructor for creating psudo-managed types. |
| */ |
| protected AbstractManagedType(Class<X> cls, MetamodelImpl model) { |
| super(cls); |
| this.model = model; |
| this.meta = null; |
| declaredAttributeFilter = null; |
| singularAttributeFilter = null; |
| pluralAttributeFilter = null; |
| } |
| |
| /** |
| * Construct a managed type. The supplied metadata must be resolved i.e. all |
| * its fields populated. Because this receiver will populate its attributes |
| * corresponding to the available fields of the metadata. |
| * |
| */ |
| public AbstractManagedType(ClassMetaData meta, MetamodelImpl model) { |
| super((Class<X>) meta.getDescribedType()); |
| |
| this.model = model; |
| this.meta = meta; |
| FieldMetaData[] fmds = meta.getFields(); |
| for (FieldMetaData f : fmds) { |
| int decCode = f.getDeclaredTypeCode(); |
| switch (decCode) { |
| case JavaTypes.BOOLEAN: |
| case JavaTypes.BOOLEAN_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Boolean>(this, f)); |
| break; |
| case JavaTypes.BYTE: |
| case JavaTypes.BYTE_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Byte>(this, f)); |
| break; |
| case JavaTypes.CHAR: |
| case JavaTypes.CHAR_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Character>(this, f)); |
| break; |
| case JavaTypes.DOUBLE: |
| case JavaTypes.DOUBLE_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Double>(this, f)); |
| break; |
| case JavaTypes.FLOAT: |
| case JavaTypes.FLOAT_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Float>(this, f)); |
| break; |
| case JavaTypes.INT: |
| case JavaTypes.INT_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Integer>(this, f)); |
| break; |
| case JavaTypes.LONG: |
| case JavaTypes.LONG_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Long>(this, f)); |
| break; |
| case JavaTypes.SHORT: |
| case JavaTypes.SHORT_OBJ: |
| attrs.add(new Members.SingularAttributeImpl<X, Short>(this, f)); |
| break; |
| case JavaTypes.STRING: |
| attrs.add(new Members.SingularAttributeImpl<X, String>(this, f)); |
| break; |
| case JavaTypes.NUMBER: |
| attrs.add(new Members.SingularAttributeImpl<X, Number>(this, f)); |
| break; |
| case JavaTypes.DATE: |
| attrs.add(new Members.SingularAttributeImpl<X, Date>(this, f)); |
| break; |
| case JavaTypes.LOCAL_DATE: |
| attrs.add(new Members.SingularAttributeImpl<X, LocalDate>(this, f)); |
| break; |
| case JavaTypes.LOCAL_TIME: |
| attrs.add(new Members.SingularAttributeImpl<X, LocalTime>(this, f)); |
| break; |
| case JavaTypes.LOCAL_DATETIME: |
| attrs.add(new Members.SingularAttributeImpl<X, LocalDateTime>(this, f)); |
| break; |
| case JavaTypes.OFFSET_TIME: |
| attrs.add(new Members.SingularAttributeImpl<X, OffsetTime>(this, f)); |
| break; |
| case JavaTypes.OFFSET_DATETIME: |
| attrs.add(new Members.SingularAttributeImpl<X, OffsetDateTime>(this, f)); |
| break; |
| case JavaTypes.CALENDAR: |
| attrs.add(new Members.SingularAttributeImpl<X, Calendar>(this, f)); |
| break; |
| case JavaTypes.BIGDECIMAL: |
| attrs.add(new Members.SingularAttributeImpl<X, BigDecimal>(this, f)); |
| break; |
| case JavaTypes.BIGINTEGER: |
| attrs.add(new Members.SingularAttributeImpl<X, BigInteger>(this, f)); |
| break; |
| case JavaTypes.LOCALE: |
| attrs.add(new Members.SingularAttributeImpl<X, Locale>(this, f)); |
| break; |
| case JavaTypes.OBJECT: |
| case JavaTypes.OID: |
| case JavaTypes.PC: |
| case JavaTypes.PC_UNTYPED: |
| case JavaTypes.INPUT_READER: |
| case JavaTypes.INPUT_STREAM: |
| attrs.add(new Members.SingularAttributeImpl(this, f)); |
| break; |
| case JavaTypes.ARRAY: |
| Compatibility compat = meta.getRepository().getConfiguration().getCompatibilityInstance(); |
| if(compat.getUseListAttributeForArrays() || f.isPersistentCollection()) { |
| attrs.add(new Members.ListAttributeImpl(this, f)); |
| } |
| else { |
| attrs.add(new Members.SingularAttributeImpl(this, f)); |
| } |
| break; |
| case JavaTypes.COLLECTION: |
| switch (MetamodelImpl.categorizeCollection(f.getDeclaredType())) { |
| case COLLECTION: |
| attrs.add(new Members.CollectionAttributeImpl(this, f)); |
| break; |
| case LIST: |
| attrs.add(new Members.ListAttributeImpl(this, f)); |
| break; |
| case SET: |
| attrs.add(new Members.SetAttributeImpl(this, f)); |
| break; |
| } |
| break; |
| case JavaTypes.MAP: |
| attrs.add(new Members.MapAttributeImpl(this, f)); |
| break; |
| case JavaTypes.ENUM: |
| attrs.add(new Members.SingularAttributeImpl(this, f)); |
| break; |
| default: |
| throw new IllegalStateException(_loc.get("field-unrecognized", |
| f.getFullName(false), decCode).getMessage()); |
| } |
| } |
| declaredAttributeFilter = new DeclaredAttributeFilter<>(this); |
| singularAttributeFilter = new SingularAttributeFilter<>(); |
| pluralAttributeFilter = new SingularAttributeFilter<X>().inverse(); |
| } |
| |
| /** |
| * Returns all the attributes of the managed type including attributes of the super type. |
| * |
| */ |
| @Override |
| public java.util.Set<Attribute<? super X, ?>> getAttributes() { |
| return Collections.unmodifiableSet(attrs); |
| } |
| |
| /** |
| * Returns all the attributes declared by this managed type only. |
| * |
| */ |
| @Override |
| public java.util.Set<Attribute<X, ?>> getDeclaredAttributes() { |
| return filter(attrs, new TreeSet<Attribute<X, ?>>(), |
| declaredAttributeFilter); |
| } |
| |
| /** |
| * Returns the single-valued attributes of the managed type. |
| * |
| */ |
| @Override |
| public java.util.Set<SingularAttribute<? super X, ?>> getSingularAttributes() { |
| return filter(attrs, new TreeSet<SingularAttribute<? super X, ?>>(), |
| singularAttributeFilter); |
| } |
| |
| /** |
| * Returns the single-valued attributes declared by the managed type. |
| * |
| */ |
| @Override |
| public java.util.Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() { |
| return filter(attrs, new TreeSet<SingularAttribute<X, ?>>(), |
| declaredAttributeFilter, |
| singularAttributeFilter); |
| } |
| |
| /** |
| * Returns the attribute of the given name and Java type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public <Y> Attribute<? super X, Y> getAttribute(String name, Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeNameFilter<X>(name), |
| new AttributeTypeFilter<X, Y>(type)); |
| if (result == null) |
| notFoundException("attr-not-found", name, type); |
| |
| return (Attribute<? super X, Y>)result; |
| } |
| |
| /** |
| * Returns the single-valued attribute of the given name and Java type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <Y> SingularAttribute<? super X, Y> getSingularAttribute(String name, Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeNameFilter<X>(name), |
| new AttributeTypeFilter<X, Y>(type), |
| singularAttributeFilter); |
| if (result == null) |
| notFoundException("attr-not-found-single", name, type); |
| |
| return (SingularAttribute<? super X, Y>) result; |
| } |
| |
| /** |
| * Returns the declared attribute of the given name and Java type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public <Y> Attribute<X, Y> getDeclaredAttribute(String name, Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeNameFilter<X>(name), |
| new AttributeTypeFilter<X, Y>(type), |
| declaredAttributeFilter); |
| if (result == null) |
| notFoundException("attr-not-found-decl-single",name, type); |
| |
| return (Attribute<X, Y>) result; |
| } |
| |
| /** |
| * Returns the declared single-valued attribute of the given name and Java type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(String name, Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeNameFilter<X>(name), |
| new AttributeTypeFilter<X, Y>(type), |
| declaredAttributeFilter, |
| singularAttributeFilter); |
| if (result == null) |
| notFoundException("attr-not-found-decl-single",name, type); |
| |
| return (SingularAttribute<X, Y>) result; |
| } |
| |
| /** |
| * Returns all collection-valued attributes of the managed type. |
| * |
| */ |
| @Override |
| public java.util.Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() { |
| return filter(attrs, new HashSet<PluralAttribute<? super X, ?, ?>>(), |
| pluralAttributeFilter); |
| } |
| |
| /** |
| * Return all collection-valued attributes declared by the managed type. |
| * |
| */ |
| @Override |
| public java.util.Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() { |
| return filter(attrs, new HashSet<PluralAttribute<X, ?, ?>>(), |
| declaredAttributeFilter, |
| pluralAttributeFilter); |
| } |
| |
| /** |
| * Returns the attribute of the given name, of type java.util.Collection and contains the |
| * given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> CollectionAttribute<? super X, E> getCollection(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new PluralCategoryFilter<X>(CollectionType.COLLECTION), |
| new ElementTypeFilter<X, E>(elementType), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-coll", name, elementType); |
| |
| return (CollectionAttribute<? super X, E>) result; |
| } |
| |
| /** |
| * Returns the attribute of the given name, of type java.util.Set and contains the |
| * given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> SetAttribute<? super X, E> getSet(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new PluralCategoryFilter<X>(CollectionType.SET), |
| new ElementTypeFilter<X, E>(elementType), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-set",name, elementType); |
| |
| return (SetAttribute<? super X, E>) result; |
| } |
| |
| /** |
| * Returns the attribute of the given name, of type java.util.List and contains the |
| * given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> ListAttribute<? super X, E> getList(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new PluralCategoryFilter<X>(CollectionType.LIST), |
| new ElementTypeFilter<X, E>(elementType), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-list",name, elementType); |
| |
| return (ListAttribute<? super X, E>) result; |
| } |
| |
| /** |
| * Returns the attribute of the given name, of type java.util.Map and contains the |
| * given key/value type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <K, V> MapAttribute<? super X, K, V> getMap(String name, Class<K> keyType, |
| Class<V> valueType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeNameFilter<X>(name), |
| new PluralCategoryFilter<X>(CollectionType.MAP), |
| new EntryTypeFilter<X, K, V>(keyType, valueType)); |
| if (result == null) |
| notFoundException("attr-not-found-map", name, keyType, valueType); |
| |
| return (MapAttribute<? super X, K, V>) result; |
| } |
| |
| /** |
| * Returns the declared attribute of the given name, of type java.util.Collection and contains |
| * the given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> CollectionAttribute<X, E> getDeclaredCollection(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new PluralCategoryFilter<X>(CollectionType.COLLECTION), |
| new ElementTypeFilter<X, E>(elementType), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-decl-coll", name, elementType); |
| |
| return (CollectionAttribute<X, E>) result; |
| } |
| |
| /** |
| * Returns the declared attribute of the given name, of type java.util.Set and contains |
| * the given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> SetAttribute<X, E> getDeclaredSet(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new PluralCategoryFilter<X>(CollectionType.SET), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-decl-set", name, elementType); |
| |
| return (SetAttribute<X, E>) result; |
| } |
| |
| /** |
| * Returns the declared attribute of the given name, of type java.util.List and contains |
| * the given element type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <E> ListAttribute<X, E> getDeclaredList(String name, Class<E> elementType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new PluralCategoryFilter<X>(CollectionType.LIST), |
| new ElementTypeFilter<X, E>(elementType), |
| new AttributeNameFilter<X>(name)); |
| if (result == null) |
| notFoundException("attr-not-found-decl-list", name, elementType); |
| |
| return (ListAttribute<X, E>) result; |
| } |
| |
| /** |
| * Returns the declared attribute of the given name, of type java.util.Map and contains |
| * the given key/value type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public <K, V> MapAttribute<X, K, V> getDeclaredMap(String name, Class<K> keyType, |
| Class<V> valueType) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new AttributeNameFilter<X>(name), |
| new PluralCategoryFilter<X>(CollectionType.MAP), |
| new EntryTypeFilter<X, K, V>(keyType, valueType)); |
| if (result == null) |
| notFoundException("attr-not-found-decl-map", name, keyType, valueType); |
| |
| return (MapAttribute<X, K, V>) result; |
| } |
| |
| // ============================================================================== |
| // No type checking |
| // ============================================================================== |
| |
| /** |
| * Returns the attribute of the given name of any type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public Attribute<? super X, ?> getAttribute(String name) { |
| return getAttribute(name, null); |
| } |
| |
| /** |
| * Returns the declared attribute of the given name of any type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public Attribute<X, ?> getDeclaredAttribute(String name) { |
| return getDeclaredAttribute(name, null); |
| } |
| |
| /** |
| * Returns the single-valued attribute of the given name of any type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public SingularAttribute<? super X, ?> getSingularAttribute(String name) { |
| return getSingularAttribute(name, null); |
| } |
| |
| /** |
| * Returns the declared, single-valued attribute of the given name of any type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public SingularAttribute<X, ?> getDeclaredSingularAttribute(String name) { |
| return getDeclaredSingularAttribute(name, null); |
| } |
| |
| /** |
| * Returns the attribute of the given name and of type java.util.Collection. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public CollectionAttribute<? super X, ?> getCollection(String name) { |
| return getCollection(name, null); |
| } |
| |
| /** |
| * Returns the attribute of the given name and of type java.util.Set. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public SetAttribute<? super X, ?> getSet(String name) { |
| return getSet(name, null); |
| } |
| |
| /** |
| * Returns the attribute of the given name and of type java.util.List. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public ListAttribute<? super X, ?> getList(String name) { |
| return getList(name, null); |
| } |
| |
| /** |
| * Returns the attribute of the given name and of type java.util.Map. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public MapAttribute<? super X, ?, ?> getMap(String name) { |
| return getMap(name, null, null); |
| } |
| |
| /** |
| * Returns the declared attribute of the given name and of type java.util.Collection. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public CollectionAttribute<X, ?> getDeclaredCollection(String name) { |
| return getDeclaredCollection(name, null); |
| } |
| |
| /** |
| * Returns the declared attribute of the given name and of type java.util.Set. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public SetAttribute<X, ?> getDeclaredSet(String name) { |
| return getDeclaredSet(name, null); |
| } |
| |
| /** |
| * Returns the declared attribute of the given name and of type java.util.List. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public ListAttribute<X, ?> getDeclaredList(String name) { |
| return getDeclaredList(name, null); |
| } |
| |
| /** |
| * Returns the declared attribute of the given name and of type java.util.Map. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| @Override |
| public MapAttribute<X, ?, ?> getDeclaredMap(String name) { |
| return getDeclaredMap(name, null, null); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Primary Key and Version Attribute related functions |
| //-------------------------------------------------------------------------- |
| /** |
| * Returns the attributes corresponding to the id class of the identifiable type. |
| * |
| * @throws IllegalArgumentException if the this type is not using an id class |
| */ |
| public final java.util.Set<SingularAttribute<? super X, ?>> getIdClassAttributes() { |
| if (meta.isOpenJPAIdentity()) |
| throw new IllegalArgumentException(meta + " does not use IdClass. Object Id type = " + |
| meta.getObjectIdType() + " Identity Type = " + meta.getIdentityType()); |
| return filter(attrs, new HashSet<SingularAttribute<? super X, ?>>(), |
| new IdAttributeFilter<X>()); |
| } |
| |
| /** |
| * Returns the attribute of given type that corresponds to the id attribute of this |
| * identifiable managed type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public final <Y> SingularAttribute<? super X, Y> getId(Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new AttributeTypeFilter<X, Y>(type), |
| new IdAttributeFilter<X>()); |
| if (result != null) |
| return (SingularAttribute<? super X, Y>) result; |
| throw new IllegalArgumentException(); |
| } |
| |
| /** |
| * Returns the declared attribute of given type that corresponds to the id attribute of this |
| * identifiable managed type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public final <Y> SingularAttribute<X, Y> getDeclaredId(Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new AttributeTypeFilter<X, Y>(type), |
| new IdAttributeFilter<X>()); |
| if (result != null) |
| return (SingularAttribute<X, Y>) result; |
| throw new IllegalArgumentException(); |
| } |
| |
| /** |
| * Returns the attribute of given type that corresponds to the version attribute of this |
| * managed type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public <Y> SingularAttribute<? super X, Y> getVersion(Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| new VersionAttributeFilter<X>(), |
| new AttributeTypeFilter<X,Y>(type)); |
| if (result == null) |
| notFoundException("version-not-found", "", type); |
| return (SingularAttribute<? super X, Y>)result; |
| } |
| |
| /** |
| * Returns the declared attribute of given type that corresponds to the version attribute of |
| * this managed type. |
| * |
| * @throws IllegalArgumentException if no such attribute exists |
| */ |
| public <Y> SingularAttribute<X, Y> getDeclaredVersion(Class<Y> type) { |
| Attribute<? super X, ?> result = pick(attrs, |
| declaredAttributeFilter, |
| new VersionAttributeFilter<X>(), |
| new AttributeTypeFilter<X,Y>(type)); |
| if (result == null) |
| notFoundException("decl-version-not-found", "", type); |
| return (SingularAttribute<X, Y>)result; |
| } |
| |
| // ===================================================================== |
| // Support functions |
| // ===================================================================== |
| |
| FieldMetaData getField(String name) { |
| return getField(name, null, null, null, false); |
| } |
| |
| FieldMetaData getField(String name, Class type) { |
| return getField(name, type, null, null, false); |
| } |
| |
| FieldMetaData getField(String name, Class type, boolean declaredOnly) { |
| return getField(name, type, null, null, declaredOnly); |
| } |
| |
| /** |
| * Get the field of the given name after validating the conditions. null |
| * value on any condition implies not to validate. |
| * |
| * @param name simple name i.e. without the class name |
| * @param type the expected type of the field. |
| * @param element |
| * the expected element type of the field. |
| * @param key |
| * the expected key type of the field. |
| * @param declared |
| * is this field declared in this receiver |
| * |
| * @exception IllegalArgumentException |
| * if any of the validation fails. |
| * |
| */ |
| FieldMetaData getField(String name, Class<?> type, Class<?> elementType, |
| Class<?> keyType, boolean decl) { |
| FieldMetaData fmd = decl ? meta.getDeclaredField(name) : meta |
| .getField(name); |
| |
| if (fmd == null) { |
| if (decl && meta.getField(name) != null) { |
| throw new IllegalArgumentException(_loc.get("field-not-decl", |
| name, cls, meta.getField(name).getDeclaringType()) |
| .getMessage()); |
| } else { |
| throw new IllegalArgumentException(_loc.get("field-missing", |
| name, meta.getDescribedType(), |
| Arrays.toString(meta.getFieldNames())).getMessage()); |
| } |
| } |
| assertType("field-type-mismatch", fmd, fmd.getDeclaredType(), type); |
| assertType("field-element-type-mismatch", fmd, fmd.getElement() |
| .getDeclaredType(), elementType); |
| assertType("field-key-type-mismatch", fmd, fmd.getKey() |
| .getDeclaredType(), keyType); |
| return fmd; |
| } |
| |
| void assertType(String msg, FieldMetaData fmd, Class<?> actual, |
| Class<?> expected) { |
| if (expected != null && !expected.isAssignableFrom(actual)) { |
| if (wrap(expected) != wrap(actual)) { |
| throw new IllegalArgumentException(_loc.get(msg, fmd.getName(), |
| actual, expected).getMessage()); |
| } |
| } |
| } |
| |
| Class<?> wrap(Class<?> c) { |
| if (c.isPrimitive()) { |
| if (c == int.class) |
| return Integer.class; |
| if (c == long.class) |
| return Long.class; |
| if (c == boolean.class) |
| return Boolean.class; |
| if (c == byte.class) |
| return Byte.class; |
| if (c == char.class) |
| return Character.class; |
| if (c == double.class) |
| return Double.class; |
| if (c == float.class) |
| return Float.class; |
| if (c == short.class) |
| return Short.class; |
| } |
| return c; |
| } |
| |
| // ------------------------------------------------------------------------- |
| // Exception handling |
| // ------------------------------------------------------------------------- |
| private void notFoundException(String msg, String name, Class<?> t1) { |
| throw new IllegalArgumentException( |
| _loc.get(msg, name, (t1 == null ? "any" : t1.getName()), meta).getMessage()); |
| } |
| |
| private void notFoundException(String msg, String name, Class<?> t1, Class<?> t2) { |
| throw new IllegalArgumentException( |
| _loc.get(msg, new Object[]{name, (t1 == null ? "any" : t1.getName()), |
| (t2 == null ? "any" : t1.getName()), meta}).getMessage()); |
| } |
| // -------------------------------------------------------------------------- |
| // Attribute filtering |
| // -------------------------------------------------------------------------- |
| /** |
| * Affirms if a given element satisfy a condition. |
| * |
| */ |
| public interface Filter<T> { |
| boolean selects(T attr); |
| |
| Filter<T> inverse(); |
| } |
| |
| |
| /** |
| * Applies chain of filters ANDed on the given collection to populate the given result. |
| * A null filter evaluates always TRUE. |
| * The arguments are not passed as variable argument list to suppress warnings in in the caller |
| * for generic varargs array construction. |
| */ |
| |
| public static <T, C extends java.util.Collection<E>, E> C filter(Collection<T> original, |
| C result, Filter<T> f1, Filter<T> f2, Filter<T> f3, Filter<T> f4) { |
| for (T t : original) { |
| if ((f1 == null || f1.selects(t)) && (f2 == null || f2.selects(t)) |
| && (f3 == null || f3.selects(t)) && (f4 == null || f4.selects(t))) |
| result.add((E) t); |
| } |
| return result; |
| } |
| |
| /** |
| * Applies chain of filters ANDed on the given collection to pick a single element. |
| * A null filter evaluates always TRUE. |
| * The arguments are not passed as variable argument list to suppress warnings in in the caller |
| * for generic varargs array construction. |
| */ |
| public static <T> T pick(Collection<T> original, Filter<T> f1, Filter<T> f2, Filter<T> f3, |
| Filter<T> f4) { |
| for (T t : original) { |
| if ((f1 == null || f1.selects(t)) && (f2 == null || f2.selects(t)) |
| && (f3 == null || f3.selects(t)) && (f4 == null || f4.selects(t))) |
| return t; |
| } |
| return null; |
| } |
| |
| static <T, C extends java.util.Collection<E>, E> C filter(Collection<T> original, |
| C result, Filter<T> f1) { |
| return filter(original, result, f1, null, null, null); |
| } |
| |
| static <T, C extends java.util.Collection<E>, E> C filter(Collection<T> original, |
| C result, Filter<T> f1, Filter<T> f2) { |
| return filter(original, result, f1, f2, null, null); |
| } |
| |
| static <T, C extends java.util.Collection<E>, E> C filter(Collection<T> original, |
| C result, Filter<T> f1, Filter<T> f2, Filter<T> f3) { |
| return filter(original, result, f1, f2, f3, null); |
| } |
| |
| static <T> T pick(Collection<T> original, Filter<T> f1) { |
| return pick(original, f1, null, null, null); |
| } |
| |
| static <T> T pick(Collection<T> original, Filter<T> f1, Filter<T> f2) { |
| return pick(original, f1, f2, null, null); |
| } |
| |
| static <T> T pick(Collection<T> original, Filter<T> f1, Filter<T> f2, Filter<T> f3) { |
| return pick(original, f1, f2, f3, null); |
| } |
| |
| |
| /** |
| * Affirms if the given attribute is a Singular attribute. |
| * |
| */ |
| public static final class SingularAttributeFilter<X> implements |
| Filter<Attribute<? super X, ?>> { |
| private final boolean _invert; |
| |
| public SingularAttributeFilter() { |
| this(false); |
| } |
| |
| public SingularAttributeFilter(boolean inverted) { |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| return _invert ? attr.isCollection() : !attr.isCollection(); |
| } |
| |
| @Override |
| public SingularAttributeFilter<X> inverse() { |
| return new SingularAttributeFilter<>(!_invert); |
| } |
| } |
| |
| public static final class DeclaredAttributeFilter<X> implements |
| Filter<Attribute<? super X, ?>> { |
| private final ManagedType<X> owner; |
| private final boolean _invert; |
| |
| DeclaredAttributeFilter(ManagedType<X> owner) { |
| this(owner, false); |
| } |
| |
| DeclaredAttributeFilter(ManagedType<X> owner, boolean inverted) { |
| this.owner = owner; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| return _invert ? attr.getDeclaringType() != owner : attr |
| .getDeclaringType() == owner; |
| } |
| |
| @Override |
| public DeclaredAttributeFilter<X> inverse() { |
| return new DeclaredAttributeFilter<>(owner, !_invert); |
| } |
| } |
| |
| /** |
| * Selects if the attribute type matches the given Java class. |
| * null matches any type. |
| */ |
| public static final class AttributeTypeFilter<X, Y> implements Filter<Attribute<? super X, ?>> { |
| private final Class<Y> _type; |
| private final boolean _invert; |
| |
| public AttributeTypeFilter(Class<Y> type) { |
| this(type, false); |
| } |
| |
| public AttributeTypeFilter(Class<Y> type, boolean inverted) { |
| _type = type; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| boolean result = _type == null || Filters.canConvert(attr.getJavaType(), _type, false); |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public AttributeTypeFilter<X, Y> inverse() { |
| return new AttributeTypeFilter<>(_type, !_invert); |
| } |
| } |
| |
| public static final class AttributeNameFilter<X> implements |
| Filter<Attribute<? super X, ?>> { |
| private final String _name; |
| private final boolean _invert; |
| |
| public AttributeNameFilter(String name) { |
| this(name, false); |
| } |
| |
| public AttributeNameFilter(String name, boolean inverted) { |
| _name = name; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| return _invert ? !attr.getName().equals(_name) : attr.getName() |
| .equals(_name); |
| } |
| |
| @Override |
| public AttributeNameFilter<X> inverse() { |
| return new AttributeNameFilter<>(_name, !_invert); |
| } |
| } |
| |
| public static final class PluralCategoryFilter<X> implements |
| Filter<Attribute<? super X, ?>> { |
| private final CollectionType _category; |
| private final boolean _invert; |
| |
| public PluralCategoryFilter(CollectionType category) { |
| this(category, false); |
| } |
| |
| public PluralCategoryFilter(CollectionType category, boolean inverted) { |
| _category = category; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| boolean result = (attr instanceof PluralAttribute<?, ?, ?>) |
| && ((PluralAttribute<?, ?, ?>) attr).getCollectionType() == _category; |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public PluralCategoryFilter<X> inverse() { |
| return new PluralCategoryFilter<>(_category, !_invert); |
| } |
| } |
| |
| /** |
| * Selects plural attribute of given element type. |
| * null element type imply <em>any</em> element type. |
| */ |
| |
| public static final class ElementTypeFilter<X, E> implements Filter<Attribute<? super X, ?>> { |
| private final Class<E> _elementType; |
| private final boolean _invert; |
| |
| public ElementTypeFilter(Class<E> eType) { |
| this(eType, false); |
| } |
| |
| public ElementTypeFilter(Class<E> eType, boolean inverted) { |
| _elementType = eType; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| boolean result = (attr instanceof PluralAttribute<?, ?, ?>) |
| && (_elementType == null |
| || ((PluralAttribute<?, ?, ?>) attr).getElementType().getJavaType() |
| == _elementType); |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public ElementTypeFilter<X, E> inverse() { |
| return new ElementTypeFilter<>(_elementType, !_invert); |
| } |
| } |
| |
| public static final class EntryTypeFilter<X, K, V> implements |
| Filter<Attribute<? super X, ?>> { |
| private final Class<K> _keyType; |
| private final Class<V> _valueType; |
| private final boolean _invert; |
| |
| public EntryTypeFilter(Class<K> kType, Class<V> vType) { |
| this(kType, vType, false); |
| } |
| |
| public EntryTypeFilter(Class<K> kType, Class<V> vType, boolean inverted) { |
| _keyType = kType; |
| _valueType = vType; |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| boolean result = (attr instanceof MapAttribute<?, ?, ?>) |
| && (_keyType == null |
| || ((MapAttribute<?, ?, ?>) attr).getKeyType().getJavaType() == _keyType) |
| && (_valueType == null |
| || ((MapAttribute<?, ?, ?>) attr).getElementType().getJavaType() == _valueType); |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public EntryTypeFilter<X, K, V> inverse() { |
| return new EntryTypeFilter<>(_keyType, _valueType, !_invert); |
| } |
| } |
| |
| public static final class IdAttributeFilter<X> implements |
| Filter<Attribute<? super X, ?>> { |
| private final boolean _invert; |
| |
| public IdAttributeFilter() { |
| this(false); |
| } |
| |
| public IdAttributeFilter(boolean inverted) { |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| boolean result = ((Members.Member<?, ?>) attr).fmd.isPrimaryKey(); |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public IdAttributeFilter<X> inverse() { |
| return new IdAttributeFilter<>(!_invert); |
| } |
| } |
| |
| public static final class VersionAttributeFilter<X> implements Filter<Attribute<? super X, ?>> { |
| private final boolean _invert; |
| |
| public VersionAttributeFilter() { |
| this(false); |
| } |
| |
| public VersionAttributeFilter(boolean inverted) { |
| _invert = inverted; |
| } |
| |
| @Override |
| public boolean selects(Attribute<? super X, ?> attr) { |
| FieldMetaData fmd = ((Members.Member<?, ?>) attr).fmd; |
| boolean result = fmd.isVersion(); |
| return _invert ? !result : result; |
| } |
| |
| @Override |
| public IdAttributeFilter<X> inverse() { |
| return new IdAttributeFilter<>(!_invert); |
| } |
| } |
| |
| } |