blob: a3b0dee027714bd94f2ca9fe989b32a20537bc21 [file] [log] [blame]
/*
* 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);
}
}
}