All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.persistence.meta.AbstractManagedType Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/*
 * 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.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.SetAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.PluralAttribute.CollectionType;

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  the 
 */
public abstract class AbstractManagedType extends Types.BaseType 
    implements ManagedType {
    
    private static final Localizer _loc = Localizer.forPackage(AbstractManagedType.class);
    public final MetamodelImpl model;
    public final ClassMetaData meta;

    private java.util.Set> attrs = new HashSet>();

    private final DeclaredAttributeFilter declaredAttributeFilter;
    private final SingularAttributeFilter singularAttributeFilter;
    private final SingularAttributeFilter pluralAttributeFilter;
    
    /**
     * A protected constructor for creating psudo-managed types.
     */
    protected AbstractManagedType(Class 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) 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(this, f));
                break;
            case JavaTypes.BYTE:
            case JavaTypes.BYTE_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.CHAR:
            case JavaTypes.CHAR_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.DOUBLE:
            case JavaTypes.DOUBLE_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.FLOAT:
            case JavaTypes.FLOAT_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.INT:
            case JavaTypes.INT_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.LONG:
            case JavaTypes.LONG_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.SHORT:
            case JavaTypes.SHORT_OBJ:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.STRING:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.NUMBER:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.DATE:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.CALENDAR:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.BIGDECIMAL:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.BIGINTEGER:
                attrs.add(new Members.SingularAttributeImpl(this, f));
                break;
            case JavaTypes.LOCALE:
                attrs.add(new Members.SingularAttributeImpl(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().inverse();
    }

    /**
     * Returns all the attributes of the managed type including attributes of the super type.
     * 
     */
    public java.util.Set> getAttributes() {
        return Collections.unmodifiableSet(attrs);
    }

    /**
     * Returns all the attributes declared by this managed type only.
     * 
     */
    public java.util.Set> getDeclaredAttributes() {
        return filter(attrs, new TreeSet>(),
                declaredAttributeFilter);
    }

    /**
     * Returns the single-valued attributes of the managed type.
     * 
     */
    public java.util.Set> getSingularAttributes() {
        return filter(attrs, new TreeSet>(),
                singularAttributeFilter);
    }

    /**
     * Returns the single-valued attributes declared by the managed type.
     * 
     */
    public java.util.Set> getDeclaredSingularAttributes() {
        return filter(attrs, new TreeSet>(),
                declaredAttributeFilter, 
                singularAttributeFilter);
    }

    /**
     * Returns the attribute of the given name and Java type.
     * 
     * @throws IllegalArgumentException  if no such attribute exists
     */
    public  Attribute getAttribute(String name, Class type) {
        Attribute result = pick(attrs,
                new AttributeNameFilter(name),
                new AttributeTypeFilter(type));
        if (result == null)
            notFoundException("attr-not-found", name, type);
        
        return (Attribute)result;
    }
    
    /**
     * Returns the single-valued attribute of the given name and Java type.
     * 
     * @throws IllegalArgumentException  if no such attribute exists
     */
    public  SingularAttribute getSingularAttribute(String name, Class type) {
        Attribute result = pick(attrs,
                new AttributeNameFilter(name),
                new AttributeTypeFilter(type), 
                singularAttributeFilter);
        if (result == null)
            notFoundException("attr-not-found-single", name, type);
         
        return (SingularAttribute) result;
    }
    
    /**
     * Returns the declared attribute of the given name and Java type.
     * 
     * @throws IllegalArgumentException  if no such attribute exists
     */
    public  Attribute getDeclaredAttribute(String name, Class type) {
        Attribute result = pick(attrs,
                new AttributeNameFilter(name),
                new AttributeTypeFilter(type), 
                declaredAttributeFilter);
        if (result == null)
            notFoundException("attr-not-found-decl-single",name, type);
            
        return (Attribute) result;
    }

    /**
     * Returns the declared single-valued attribute of the given name and Java type.
     * 
     * @throws IllegalArgumentException  if no such attribute exists
     */
    public  SingularAttribute getDeclaredSingularAttribute(String name, Class type) {
        Attribute result = pick(attrs,
                new AttributeNameFilter(name),
                new AttributeTypeFilter(type), 
                declaredAttributeFilter,
                singularAttributeFilter);
        if (result == null)
            notFoundException("attr-not-found-decl-single",name, type);

        return (SingularAttribute) result;
    }

    /**
     * Returns all collection-valued attributes of the managed type.
     * 
     */
    public java.util.Set> getPluralAttributes() {
        return filter(attrs, new HashSet>(),
                pluralAttributeFilter);
    }

    /**
     * Return all collection-valued attributes declared by the managed type.
     * 
     */
    public java.util.Set> getDeclaredPluralAttributes() {
        return filter(attrs, new HashSet>(),
                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
     */
    public  CollectionAttribute getCollection(String name, Class elementType) {
        Attribute result = pick(attrs,
                new PluralCategoryFilter(CollectionType.COLLECTION),
                new ElementTypeFilter(elementType),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-coll", name, elementType);

        return (CollectionAttribute) 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
     */
    public  SetAttribute getSet(String name, Class elementType) {
        Attribute result = pick(attrs,
                new PluralCategoryFilter(CollectionType.SET),
                new ElementTypeFilter(elementType),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-set",name, elementType);

        return (SetAttribute) 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
     */
    public  ListAttribute getList(String name, Class elementType) {
        Attribute result = pick(attrs,
                new PluralCategoryFilter(CollectionType.LIST),
                new ElementTypeFilter(elementType),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-list",name, elementType);

        return (ListAttribute) 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
     */
    public  MapAttribute getMap(String name, Class keyType, 
        Class valueType) {
        Attribute result = pick(attrs,
                new AttributeNameFilter(name),
                new PluralCategoryFilter(CollectionType.MAP),
                new EntryTypeFilter(keyType, valueType));
        if (result == null)
            notFoundException("attr-not-found-map", name, keyType, valueType);

        return (MapAttribute) 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
     */
    public  CollectionAttribute getDeclaredCollection(String name,  Class elementType) {
        Attribute result = pick(attrs, 
                declaredAttributeFilter,
                new PluralCategoryFilter(CollectionType.COLLECTION),
                new ElementTypeFilter(elementType),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-decl-coll", name, elementType);

        return (CollectionAttribute) 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
     */
    public  SetAttribute getDeclaredSet(String name, Class elementType) {
        Attribute result = pick(attrs, 
                declaredAttributeFilter,
                new PluralCategoryFilter(CollectionType.SET),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-decl-set", name, elementType);

        return (SetAttribute) 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
     */
    public  ListAttribute getDeclaredList(String name, Class elementType) {
        Attribute result = pick(attrs, 
                declaredAttributeFilter,
                new PluralCategoryFilter(CollectionType.LIST),
                new ElementTypeFilter(elementType),
                new AttributeNameFilter(name));
        if (result == null)
            notFoundException("attr-not-found-decl-list", name, elementType);

        return (ListAttribute) 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
     */
    public  MapAttribute getDeclaredMap(String name, Class keyType, 
        Class valueType) {
        Attribute result = pick(attrs,
                declaredAttributeFilter,
                new AttributeNameFilter(name),
                new PluralCategoryFilter(CollectionType.MAP),
                new EntryTypeFilter(keyType, valueType));
        if (result == null)
            notFoundException("attr-not-found-decl-map", name, keyType, valueType);

        return (MapAttribute) result;
    }

    // ==============================================================================
    // No type checking
    // ==============================================================================
    
    /**
     * Returns the attribute of the given name of any type.
     * 
     * @throws IllegalArgumentException  if no such attribute exists
     */
    public Attribute 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
     */
    public Attribute 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
     */
    public SingularAttribute 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
     */
    public SingularAttribute 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
     */
    public CollectionAttribute 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
     */
    public SetAttribute 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
     */
    public ListAttribute 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
     */
    public MapAttribute 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
     */
    public CollectionAttribute 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
     */
    public SetAttribute 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
     */
    public ListAttribute 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
     */
    public MapAttribute 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> 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>(),
                new IdAttributeFilter());
    }
    
    /**
     *  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  SingularAttribute getId(Class type) {
         Attribute result =  pick(attrs, 
                 new AttributeTypeFilter(type), 
                 new IdAttributeFilter());
         if (result != null)
             return (SingularAttribute) 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  SingularAttribute getDeclaredId(Class type) {
         Attribute result =  pick(attrs, 
                 declaredAttributeFilter,
                 new AttributeTypeFilter(type), 
                 new IdAttributeFilter());
         if (result != null)
             return (SingularAttribute) 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  SingularAttribute getVersion(Class type) {
         Attribute result = pick(attrs, 
                 new VersionAttributeFilter(), 
                 new AttributeTypeFilter(type));
         if (result == null) 
             notFoundException("version-not-found", "", type);
         return (SingularAttribute)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  SingularAttribute getDeclaredVersion(Class type) {
         Attribute result = pick(attrs,
                 declaredAttributeFilter,
                 new VersionAttributeFilter(), 
                 new AttributeTypeFilter(type));
         if (result == null) 
             notFoundException("decl-version-not-found", "", type);
         return (SingularAttribute)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 static interface Filter {
        boolean selects(T attr);

        Filter 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 , E> C filter(Collection original, 
        C result, Filter f1, Filter f2, Filter f3, Filter 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 pick(Collection original, Filter f1, Filter f2, Filter f3, 
        Filter 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 , E> C filter(Collection original, 
            C result, Filter f1) {
        return filter(original, result, f1, null, null, null);
    }
    
    static , E> C filter(Collection original, 
            C result, Filter f1, Filter f2) {
        return filter(original, result, f1, f2, null, null);
    }
    
    static , E> C filter(Collection original, 
            C result, Filter f1, Filter f2, Filter f3) {
        return filter(original, result, f1, f2, f3, null);
    }
    
    static  T pick(Collection original, Filter f1) {
        return pick(original, f1, null, null, null);
    }

    static  T pick(Collection original, Filter f1, Filter f2) {
        return pick(original, f1, f2, null, null);
    }
    
    static  T pick(Collection original, Filter f1, Filter f2, Filter f3) {
        return pick(original, f1, f2, f3, null);
    }
    

    /**
     * Affirms if the given attribute is a Singular attribute.
     * 
     */
    public static final class SingularAttributeFilter implements
            Filter> {
        private final boolean _invert;

        public SingularAttributeFilter() {
            this(false);
        }

        public SingularAttributeFilter(boolean inverted) {
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            return _invert ? attr.isCollection() : !attr.isCollection();
        }

        public SingularAttributeFilter inverse() {
            return new SingularAttributeFilter(!_invert);
        }
    }

    public static final class DeclaredAttributeFilter implements
            Filter> {
        private final ManagedType owner;
        private final boolean _invert;

        DeclaredAttributeFilter(ManagedType owner) {
            this(owner, false);
        }

        DeclaredAttributeFilter(ManagedType owner, boolean inverted) {
            this.owner = owner;
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            return _invert ? attr.getDeclaringType() != owner : attr
                    .getDeclaringType() == owner;
        }

        public DeclaredAttributeFilter 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 implements Filter> {
        private final Class _type;
        private final boolean _invert;

        public AttributeTypeFilter(Class type) {
            this(type, false);
        }

        public AttributeTypeFilter(Class type, boolean inverted) {
            _type = type;
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            boolean result = _type == null || Filters.canConvert(attr.getJavaType(), _type, false);
            return _invert ? !result : result;
        }

        public AttributeTypeFilter inverse() {
            return new AttributeTypeFilter(_type, !_invert);
        }        
    }

    public static final class AttributeNameFilter implements
            Filter> {
        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;
        }

        public boolean selects(Attribute attr) {
            return _invert ? !attr.getName().equals(_name) : attr.getName()
                    .equals(_name);
        }

        public AttributeNameFilter inverse() {
            return new AttributeNameFilter(_name, !_invert);
        }
    }

    public static final class PluralCategoryFilter implements
            Filter> {
        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;
        }

        public boolean selects(Attribute attr) {
            boolean result = (attr instanceof PluralAttribute)
                    && ((PluralAttribute) attr).getCollectionType() == _category;
            return _invert ? !result : result;
        }

        public PluralCategoryFilter inverse() {
            return new PluralCategoryFilter(_category, !_invert);
        }
    }

    /**
     * Selects plural attribute of given element type.
     * null element type imply any element type.
     */
    
    public static final class ElementTypeFilter implements Filter> {
        private final Class _elementType;
        private final boolean _invert;

        public ElementTypeFilter(Class eType) {
            this(eType, false);
        }

        public ElementTypeFilter(Class eType, boolean inverted) {
            _elementType = eType;
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            boolean result = (attr instanceof PluralAttribute)
                    && (_elementType == null 
                    || ((PluralAttribute) attr).getElementType().getJavaType() 
                         == _elementType);
            return _invert ? !result : result;
        }

        public ElementTypeFilter inverse() {
            return new ElementTypeFilter(_elementType, !_invert);
        }
    }

    public static final class EntryTypeFilter implements
            Filter> {
        private final Class _keyType;
        private final Class _valueType;
        private final boolean _invert;

        public EntryTypeFilter(Class kType, Class vType) {
            this(kType, vType, false);
        }

        public EntryTypeFilter(Class kType, Class vType, boolean inverted) {
            _keyType = kType;
            _valueType = vType;
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            boolean result = (attr instanceof MapAttribute)
                    && (_keyType == null 
                    || ((MapAttribute) attr).getKeyType().getJavaType() == _keyType)
                    && (_valueType == null 
                    || ((MapAttribute) attr).getElementType().getJavaType() == _valueType);
            return _invert ? !result : result;
        }

        public EntryTypeFilter inverse() {
            return new EntryTypeFilter(_keyType, _valueType, !_invert);
        }
    }

    public static final class IdAttributeFilter implements
            Filter> {
        private final boolean _invert;

        public IdAttributeFilter() {
            this(false);
        }

        public IdAttributeFilter(boolean inverted) {
            _invert = inverted;
        }

        public boolean selects(Attribute attr) {
            boolean result = ((Members.Member) attr).fmd.isPrimaryKey();
            return _invert ? !result : result;
        }

        public IdAttributeFilter inverse() {
            return new IdAttributeFilter(!_invert);
        }
    }
    
    public static final class VersionAttributeFilter implements Filter> {
        private final boolean _invert;

        public VersionAttributeFilter() {
            this(false);
        }
        
        public VersionAttributeFilter(boolean inverted) {
            _invert = inverted;
        }
        
        public boolean selects(Attribute attr) {
            FieldMetaData fmd = ((Members.Member) attr).fmd;
            boolean result = fmd.isVersion();
            return _invert ? !result : result;
        }
        
        public IdAttributeFilter inverse() {
            return new IdAttributeFilter(!_invert);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy