/*
 * 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;

import static javax.persistence.AccessType.FIELD;
import static javax.persistence.AccessType.PROPERTY;
import static org.apache.openjpa.persistence.PersistenceStrategy.BASIC;
import static org.apache.openjpa.persistence.PersistenceStrategy.ELEM_COLL;
import static org.apache.openjpa.persistence.PersistenceStrategy.EMBEDDED;
import static org.apache.openjpa.persistence.PersistenceStrategy.MANY_MANY;
import static org.apache.openjpa.persistence.PersistenceStrategy.MANY_ONE;
import static org.apache.openjpa.persistence.PersistenceStrategy.ONE_MANY;
import static org.apache.openjpa.persistence.PersistenceStrategy.ONE_ONE;
import static org.apache.openjpa.persistence.PersistenceStrategy.PERS;
import static org.apache.openjpa.persistence.PersistenceStrategy.PERS_COLL;
import static org.apache.openjpa.persistence.PersistenceStrategy.PERS_MAP;
import static org.apache.openjpa.persistence.PersistenceStrategy.TRANSIENT;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import javax.persistence.Transient;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.AbstractMetaDataDefaults;
import org.apache.openjpa.meta.AccessCode;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UserException;

/**
 * JPA-based metadata defaults.
 *
 * @author Patrick Linskey
 * @author Abe White
 * @author Pinaki Poddar
 */
public class PersistenceMetaDataDefaults
    extends AbstractMetaDataDefaults {

    private static final Localizer _loc = Localizer.forPackage
        (PersistenceMetaDataDefaults.class);

    private static final Map<Class<?>, PersistenceStrategy> _strats =
        new HashMap<>();
    private static final Set<String> _ignoredAnnos = new HashSet<>();

    static {
        _strats.put(Basic.class, BASIC);
        _strats.put(ManyToOne.class, MANY_ONE);
        _strats.put(OneToOne.class, ONE_ONE);
        _strats.put(Embedded.class, EMBEDDED);
        _strats.put(EmbeddedId.class, EMBEDDED);
        _strats.put(OneToMany.class, ONE_MANY);
        _strats.put(ManyToMany.class, MANY_MANY);
        _strats.put(Persistent.class, PERS);
        _strats.put(PersistentCollection.class, PERS_COLL);
        _strats.put(ElementCollection.class, ELEM_COLL);
        _strats.put(PersistentMap.class, PERS_MAP);

        _ignoredAnnos.add(DetachedState.class.getName());
        _ignoredAnnos.add(PostLoad.class.getName());
        _ignoredAnnos.add(PostPersist.class.getName());
        _ignoredAnnos.add(PostRemove.class.getName());
        _ignoredAnnos.add(PostUpdate.class.getName());
        _ignoredAnnos.add(PrePersist.class.getName());
        _ignoredAnnos.add(PreRemove.class.getName());
        _ignoredAnnos.add(PreUpdate.class.getName());
    }

	/**
     * Set of Inclusion Filters based on member type, access type or transient
     * annotations. Used to determine the persistent field/methods.
     */
    protected AccessFilter propertyAccessFilter = new AccessFilter(PROPERTY);
    protected AccessFilter fieldAccessFilter = new AccessFilter(FIELD);

    protected MemberFilter fieldFilter = new MemberFilter(Field.class);
    protected MemberFilter methodFilter = new MemberFilter(Method.class);
    protected TransientFilter nonTransientFilter = new TransientFilter(false);
    protected AnnotatedFilter annotatedFilter = new AnnotatedFilter();
    protected GetterFilter getterFilter = new GetterFilter();
    protected SetterFilter setterFilter = new SetterFilter();
    private Boolean _isAbstractMappingUniDirectional = null;
    private Boolean _isNonDefaultMappingAllowed = null;
    private String _defaultSchema;
    private Boolean _isCascadePersistPersistenceUnitDefaultEnabled = null;

    public PersistenceMetaDataDefaults() {
        setCallbackMode(CALLBACK_RETHROW | CALLBACK_ROLLBACK |
            CALLBACK_FAIL_FAST);
        setDataStoreObjectIdFieldUnwrapped(true);
    }

    /**
     * Return the code for the strategy of the given member. Return null if
     * no strategy.
     */
    public static PersistenceStrategy getPersistenceStrategy
    (FieldMetaData fmd, Member member) {
        return getPersistenceStrategy(fmd, member, false);
    }

    /**
     * Return the code for the strategy of the given member. Return null if
     * no strategy.
     */
    public static PersistenceStrategy getPersistenceStrategy
        (FieldMetaData fmd, Member member, boolean ignoreTransient) {
        if (member == null)
            return null;
        AnnotatedElement el = (AnnotatedElement) member;
        if (!ignoreTransient && (AccessController.doPrivileged(J2DoPrivHelper
            .isAnnotationPresentAction(el, Transient.class))).booleanValue())
            return TRANSIENT;
        if (fmd != null
            && fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT)
            return null;

        // look for persistence strategy in annotation table
        PersistenceStrategy pstrat = null;
        for (Annotation anno : el.getDeclaredAnnotations()) {
            if (pstrat != null && _strats.containsKey(anno.annotationType()))
                throw new MetaDataException(_loc.get("already-pers", member));
            if (pstrat == null)
                pstrat = _strats.get(anno.annotationType());
        }
        if (pstrat != null)
            return pstrat;

        Class type;
        int code;
        if (fmd != null) {
            type = fmd.getType();
            code = fmd.getTypeCode();
        } else if (member instanceof Field) {
            type = ((Field) member).getType();
            code = JavaTypes.getTypeCode(type);
        } else {
            type = ((Method) member).getReturnType();
            code = JavaTypes.getTypeCode(type);
        }

        switch (code) {
            case JavaTypes.ARRAY:
                if (type == byte[].class
                    || type == char[].class
                    || type == Byte[].class
                    || type == Character[].class)
                    return BASIC;
                break;
            case JavaTypes.BOOLEAN:
            case JavaTypes.BOOLEAN_OBJ:
            case JavaTypes.BYTE:
            case JavaTypes.BYTE_OBJ:
            case JavaTypes.CHAR:
            case JavaTypes.CHAR_OBJ:
            case JavaTypes.DOUBLE:
            case JavaTypes.DOUBLE_OBJ:
            case JavaTypes.FLOAT:
            case JavaTypes.FLOAT_OBJ:
            case JavaTypes.INT:
            case JavaTypes.INT_OBJ:
            case JavaTypes.LONG:
            case JavaTypes.LONG_OBJ:
            case JavaTypes.SHORT:
            case JavaTypes.SHORT_OBJ:
            case JavaTypes.STRING:
            case JavaTypes.BIGDECIMAL:
            case JavaTypes.BIGINTEGER:
            case JavaTypes.DATE:
            case JavaTypes.LOCAL_DATE:
            case JavaTypes.LOCAL_TIME:
            case JavaTypes.LOCAL_DATETIME:
            case JavaTypes.OFFSET_TIME:
            case JavaTypes.OFFSET_DATETIME:
                return BASIC;
            case JavaTypes.OBJECT:
                if (Enum.class.isAssignableFrom(type))
                    return BASIC;
                break;
        }

        //### EJB3: what if defined in XML?
        if ((AccessController.doPrivileged(J2DoPrivHelper
            .isAnnotationPresentAction(type, Embeddable.class))).booleanValue())
            return EMBEDDED;
        if (Serializable.class.isAssignableFrom(type))
            return BASIC;
        return null;
    }

    /**
     * Auto-configuration method for the default access type of base classes
     * with ACCESS_UNKNOWN
     */
    public void setDefaultAccessType(String type) {
        if ("PROPERTY".equals(type.toUpperCase(Locale.ENGLISH)))
            setDefaultAccessType(AccessCode.PROPERTY);
        else if ("FIELD".equals(type.toUpperCase(Locale.ENGLISH)))
            setDefaultAccessType(AccessCode.FIELD);
        else
        	throw new IllegalArgumentException(_loc.get("access-invalid",
        	    type).toString());
    }

    /**
     * Populates the given class metadata. The access style determines which
     * field and/or getter method will contribute as the persistent property
     * of the given class. If the given access is unknown, then the access
     * type is to be determined at first.
     *
     * @see #determineAccessType(ClassMetaData)
     */
    @Override
    public void populate(ClassMetaData meta, int access) {
        populate(meta, access, false);
    }

    /**
     * Populates the given class metadata. The access style determines which
     * field and/or getter method will contribute as the persistent property
     * of the given class. If the given access is unknown, then the access
     * type is to be determined at first.
     *
     * @see #determineAccessType(ClassMetaData)
     */
    @Override
    public void populate(ClassMetaData meta, int access, boolean ignoreTransient) {
    	if (AccessCode.isUnknown(access)) {
    		access = determineAccessType(meta);
    	}
    	if (AccessCode.isUnknown(access)) {
    		error(meta, _loc.get("access-unknown", meta));
    	}
        super.populate(meta, access, ignoreTransient);
        meta.setDetachable(true);
        // do not call get*Fields as it will lock down the fields.
    }

    @Override
    protected void populate(FieldMetaData fmd) {
        setCascadeNone(fmd);
        setCascadeNone(fmd.getKey());
        setCascadeNone(fmd.getElement());
    }

    /**
     * Turns off auto cascading of persist, refresh, attach, detach.
     */
    static void setCascadeNone(ValueMetaData vmd) {
        vmd.setCascadePersist(ValueMetaData.CASCADE_NONE);
        vmd.setCascadeRefresh(ValueMetaData.CASCADE_NONE);
        vmd.setCascadeAttach(ValueMetaData.CASCADE_NONE);
        vmd.setCascadeDetach(ValueMetaData.CASCADE_NONE);
    }

    ClassMetaData getCachedSuperclassMetaData(ClassMetaData meta) {
    	if (meta == null)
    		return null;
    	Class<?> cls = meta.getDescribedType();
    	Class<?> sup = cls.getSuperclass();
    	if (sup == null || "java.lang.Object".equals(
    	    sup.getName()))
    		return null;
    	MetaDataRepository repos = meta.getRepository();
    	ClassMetaData supMeta = repos.getCachedMetaData(sup);
    	if (supMeta == null)
    		supMeta = repos.getMetaData(sup, null, false);
    	return supMeta;
    }

    /**
     * Recursive helper to determine access type based on annotation placement
     * on members for the given class without an explicit access annotation.
     *
     * @return must return a not-unknown access code
     */
    private int determineAccessType(ClassMetaData meta) {
    	if (meta == null)
    		return AccessCode.UNKNOWN;
        if (meta.getDescribedType().isInterface()) // managed interfaces
        	return AccessCode.PROPERTY;
    	if (!AccessCode.isUnknown(meta))
    		return meta.getAccessType();
    	int access = determineExplicitAccessType(meta.getDescribedType());
    	if (!AccessCode.isUnknown(access))
    		return access;
    	access = determineImplicitAccessType(meta.getDescribedType(),
    	            meta.getRepository().getConfiguration());
    	if (!AccessCode.isUnknown(access))
    		return access;

    	ClassMetaData sup = getCachedSuperclassMetaData(meta);
    	ClassMetaData tmpSup = sup;
    	while (tmpSup != null && tmpSup.isExplicitAccess()) {
            tmpSup = getCachedSuperclassMetaData(tmpSup);
            if (tmpSup != null) {
                sup = tmpSup;
            }
    	}
    	if (sup != null && !AccessCode.isUnknown(sup))
    		return sup.getAccessType();

        trace(meta, _loc.get("access-default", meta, AccessCode.toClassString(getDefaultAccessType())));
        return getDefaultAccessType();
    }

    /**
     * Determines the access type for the given class by placement of
     * annotations on field or getter method. Does not consult the
     * super class.
     *
     * Annotation can be placed on either fields or getters but not on both.
     * If no field or getter is annotated then UNKNOWN access code is returned.
     */
    private int determineImplicitAccessType(Class<?> cls, OpenJPAConfiguration
        conf) {
    	if (cls.isInterface()) // Managed interfaces
    		return AccessCode.PROPERTY;
        Field[] allFields = AccessController.doPrivileged(J2DoPrivHelper.
                getDeclaredFieldsAction(cls));
		Method[] methods = AccessController.doPrivileged(
				J2DoPrivHelper.getDeclaredMethodsAction(cls));
        List<Field> fields = filter(allFields, new TransientFilter(true));
        /*
         * OpenJPA 1.x permitted private properties to be persistent.  This is
         * contrary to the JPA 1.0 specification, which states that persistent
         * properties must be public or protected. OpenJPA 2.0+ will adhere
         * to the specification by default, but provides a compatibility
         * option to provide pre-2.0 behavior.
         */
        getterFilter.setIncludePrivate(
            conf.getCompatibilityInstance().getPrivatePersistentProperties());
        List<Method> getters = filter(methods, getterFilter);
        if (fields.isEmpty() && getters.isEmpty())
        	return AccessCode.EMPTY;

        fields = filter(fields, annotatedFilter);
        getters = filter(getters, annotatedFilter);

        List<Method> setters = filter(methods, setterFilter);
        getters =  matchGetterAndSetter(getters, setters);

        boolean mixed = !fields.isEmpty() && !getters.isEmpty();
        if (mixed)
        	throw new UserException(_loc.get("access-mixed",
        		cls, toFieldNames(fields), toMethodNames(getters)));
        if (!fields.isEmpty()) {
        	return AccessCode.FIELD;
        }
        if (!getters.isEmpty()) {
        	return AccessCode.PROPERTY;
        }
        return AccessCode.UNKNOWN;
    }

    /**
     * Explicit access type, if any, is generally detected by the parser. This
     * is only used for metadata of an embeddable type which is encountered
     * as a field during some other owning entity.
     *
     * @see ValueMetaData#addEmbeddedMetaData()
     */
    private int determineExplicitAccessType(Class<?> cls) {
        Access access = cls.getAnnotation(Access.class);
        return access == null ? AccessCode.UNKNOWN : ((access.value() ==
            AccessType.FIELD ? AccessCode.FIELD : AccessCode.PROPERTY) |
            AccessCode.EXPLICIT);
    }

    /**
     * Matches the given getters with the given setters. Removes the getters
     * that do not have a corresponding setter.
     */
    private List<Method> matchGetterAndSetter(List<Method> getters,
    		List<Method> setters) {
        Collection<Method> unmatched =  new ArrayList<>();

        for (Method getter : getters) {
            String getterName = getter.getName();
            Class<?> getterReturnType = getter.getReturnType();
            String expectedSetterName = "set" + getterName.substring(
                (isBooleanGetter(getter) ? "is" : "get").length());
            boolean matched = false;
            for (Method setter : setters) {
                Class<?> setterArgType = setter.getParameterTypes()[0];
                String actualSetterName = setter.getName();
                matched = actualSetterName.equals(expectedSetterName)
                    && setterArgType == getterReturnType;
                if (matched)
                    break;
            }
            if (!matched) {
                unmatched.add(getter);
            }

        }
        getters.removeAll(unmatched);
        return getters;
    }

    /**
     * Gets the fields that are possible candidate for being persisted. The
     * result depends on the current access style of the given class.
     */
    List<Field> getPersistentFields(ClassMetaData meta, boolean ignoreTransient) {
    	boolean explicit = meta.isExplicitAccess();
    	boolean unknown  = AccessCode.isUnknown(meta);
    	boolean isField  = AccessCode.isField(meta);

    	if (explicit || unknown || isField) {
    		Field[] fields = AccessController.doPrivileged(J2DoPrivHelper.
                getDeclaredFieldsAction(meta.getDescribedType()));

        	return filter(fields, fieldFilter,
        	    ignoreTransient ? null : nonTransientFilter,
        		unknown || isField  ? null : annotatedFilter,
        	    explicit ? (isField ? null : fieldAccessFilter) : null);
    	}
    	return Collections.EMPTY_LIST;
    }

    /**
     * Gets the methods that are possible candidate for being persisted. The
     * result depends on the current access style of the given class.
     */
    List<Method> getPersistentMethods(ClassMetaData meta, boolean ignoreTransient) {
    	boolean explicit = meta.isExplicitAccess();
    	boolean unknown  = AccessCode.isUnknown(meta.getAccessType());
    	boolean isProperty  = AccessCode.isProperty(meta.getAccessType());

    	if (explicit || unknown || isProperty) {
    		Method[] publicMethods = AccessController.doPrivileged(
              J2DoPrivHelper.getDeclaredMethodsAction(meta.getDescribedType()));

            /*
             * OpenJPA 1.x permitted private accessor properties to be persistent.  This is
             * contrary to the JPA 1.0 specification, which states that persistent
             * properties must be public or protected. OpenJPA 2.0+ will adhere
             * to the specification by default, but provides a compatibility
             * option to provide pre-2.0 behavior.
             */
            getterFilter.setIncludePrivate(
                meta.getRepository().getConfiguration().getCompatibilityInstance().getPrivatePersistentProperties());

            List<Method> getters = filter(publicMethods, methodFilter,
                getterFilter,
                ignoreTransient ? null : nonTransientFilter,
        		unknown || isProperty ? null : annotatedFilter,
                explicit ? (isProperty ? null : propertyAccessFilter) : null);

            List<Method> setters = filter(publicMethods, setterFilter);
            return getters = matchGetterAndSetter(getters, setters);
    	}

    	return Collections.EMPTY_LIST;
    }

    /**
     * Gets the members that are backing members for attributes being persisted.
     * Unlike {@linkplain #getPersistentFields(ClassMetaData)} and
     * {@linkplain #getPersistentMethods(ClassMetaData)} which returns
     * <em>possible</em> candidates, the result of this method is definite.
     *
     * Side-effect of this method is if the given class metadata has
     * no access type set, this method will set it.
     */
    @Override
    public List<Member> getPersistentMembers(ClassMetaData meta, boolean ignoreTransient) {
    	List<Member> members = new ArrayList<>();
    	List<Field> fields   = getPersistentFields(meta, ignoreTransient);
    	List<Method> getters = getPersistentMethods(meta, ignoreTransient);

    	boolean isMixed = !fields.isEmpty() && !getters.isEmpty();
    	boolean isEmpty = fields.isEmpty() && getters.isEmpty();

    	boolean explicit    = meta.isExplicitAccess();
    	boolean unknown     = AccessCode.isUnknown(meta.getAccessType());

    	if (isEmpty) {
    		warn(meta, _loc.get("access-empty", meta));
    		return Collections.EMPTY_LIST;
    	}
    	if (explicit) {
    		if (isMixed) {
    			assertNoDuplicate(fields, getters);
                meta.setAccessType(AccessCode.MIXED | meta.getAccessType());
    			members.addAll(fields);
    			members.addAll(getters);
    		} else {
    			members.addAll(fields.isEmpty() ? getters : fields);
    		}
    	} else {
    		if (isMixed)
                error(meta, _loc.get("access-mixed", meta, fields, getters));
    		if (fields.isEmpty()) {
    			meta.setAccessType(AccessCode.PROPERTY);
    			members.addAll(getters);
    		} else {
    			meta.setAccessType(AccessCode.FIELD);
    			members.addAll(fields);
    		}
    	}
    	return members;
    }

    void assertNoDuplicate(List<Field> fields, List<Method> getters) {

    }

    void error(ClassMetaData meta, Localizer.Message message) {
    	Log log = meta.getRepository().getConfiguration()
    		.getLog(OpenJPAConfiguration.LOG_RUNTIME);
    	log.error(message.toString());
    	throw new UserException(message.toString());
    }

    void warn(ClassMetaData meta, Localizer.Message message) {
    	Log log = meta.getRepository().getConfiguration()
		.getLog(OpenJPAConfiguration.LOG_RUNTIME);
    	log.warn(message.toString());
    }

    void trace(ClassMetaData meta, Localizer.Message message) {
        Log log = meta.getRepository().getConfiguration()
        .getLog(OpenJPAConfiguration.LOG_RUNTIME);
        log.trace(message.toString());
    }

    @Override
    protected List<String> getFieldAccessNames(ClassMetaData meta) {
    	return toNames(getPersistentFields(meta, false));
    }

    @Override
    protected List<String> getPropertyAccessNames(ClassMetaData meta) {
    	return toNames(getPersistentMethods(meta, false));
    }

    protected boolean isDefaultPersistent(ClassMetaData meta, Member member,
        String name) {
        return isDefaultPersistent(meta, member, name, false);
    }

    @Override
    protected boolean isDefaultPersistent(ClassMetaData meta, Member member,
        String name, boolean ignoreTransient) {
        int mods = member.getModifiers();
        if (Modifier.isTransient(mods))
            return false;
        int access = meta.getAccessType();

        if (member instanceof Field) {
            // If mixed or unknown, default property access, keep explicit
            // field members
            if (AccessCode.isProperty(access)) {
                if (!isAnnotatedAccess(member, AccessType.FIELD))
                    return false;
            }
        }
        else if (member instanceof Method) {
            // If mixed or unknown, field default access, keep explicit property
            // members
            if (AccessCode.isField(access)) {
                if (!isAnnotatedAccess(member, AccessType.PROPERTY))
                    return false;
            }
            try {
                String setterName;
                if (member.getName().startsWith("is")) {
                    setterName = "set" + member.getName().substring(2);
                } else {
                    setterName = "set" + member.getName().substring(3);
                }
                // check for setters for methods
                Method setter =
                    (Method) AccessController.doPrivileged(J2DoPrivHelper.getDeclaredMethodAction(
                        meta.getDescribedType(), setterName, new Class[] { ((Method) member).getReturnType() }));
                if (setter == null && !isAnnotatedTransient(member)) {
                    logNoSetter(meta, name, null);
                    return false;
                }
            } catch (Exception e) {
                // e.g., NoSuchMethodException
                if (!isAnnotatedTransient(member))
                    logNoSetter(meta, name, e);
                return false;
            }
        }

        PersistenceStrategy strat = getPersistenceStrategy(null, member, ignoreTransient);
        if (strat == null) {
            warn(meta, _loc.get("no-pers-strat", meta.getDescribedTypeString() + "." + name));
            return false;
        } else if (strat == PersistenceStrategy.TRANSIENT) {
            return false;
        } else {
            return true;
        }
    }

    private boolean isAnnotatedTransient(Member member) {
        return member instanceof AnnotatedElement
            && (AccessController.doPrivileged(J2DoPrivHelper
                .isAnnotationPresentAction(((AnnotatedElement) member),
                    Transient.class))).booleanValue();
    }

    /**
     * May be used to determine if member is annotated with the specified
     * access type.
     * @param member class member
     * @param type expected access type
     * @return true if access is specified on member and that access
     *         type matches the expected type
     */
    private boolean isAnnotatedAccess(Member member, AccessType type) {
    	if (member == null)
    		return false;
        Access anno =
            AccessController.doPrivileged(J2DoPrivHelper
                .getAnnotationAction((AnnotatedElement)member,
                Access.class));
        return anno != null && anno.value() == type;
    }

    private boolean isAnnotated(Member member) {
    	return member != null && member instanceof AnnotatedElement
    	    && annotatedFilter.includes((AnnotatedElement)member);
    }

    private boolean isNotTransient(Member member) {
        return member != null && member instanceof AnnotatedElement
            && nonTransientFilter.includes((AnnotatedElement)member);
    }

    /**
     * Gets either the instance field or the getter method depending upon the
     * access style of the given meta-data.
     */
    @Override
    public Member getMemberByProperty(ClassMetaData meta, String property,
    	int access, boolean applyDefaultRule) {
    	Class<?> cls = meta.getDescribedType();
        Field field = Reflection.findField(cls, property, false);;
        Method getter = Reflection.findGetter(cls, property, false);
        Method setter = Reflection.findSetter(cls, property, false);
        int accessCode = AccessCode.isUnknown(access) ? meta.getAccessType() :
        	access;
        if (field == null && getter == null)
        	error(meta, _loc.get("access-no-property", cls, property));
    	if ((isNotTransient(getter) && isAnnotated(getter)) &&
    	     isNotTransient(field) && isAnnotated(field))
    		throw new IllegalStateException(_loc.get("access-duplicate",
    			field, getter).toString());

        if (AccessCode.isField(accessCode)) {
           if (isAnnotatedAccess(getter, AccessType.PROPERTY)) {
        	   meta.setAccessType(AccessCode.MIXED | meta.getAccessType());
               return getter;
           }
           return field == null ? getter : field;
        } else if (AccessCode.isProperty(accessCode)) {
            if (isAnnotatedAccess(field, AccessType.FIELD)) {
         	   meta.setAccessType(AccessCode.MIXED | meta.getAccessType());
               return field;
            }
            return getter == null ? field : getter;
        } else if (AccessCode.isUnknown(accessCode)) {
        	if (isAnnotated(field)) {
        		meta.setAccessType(AccessCode.FIELD);
        		return field;
        	} else if (isAnnotated(getter)) {
        		meta.setAccessType(AccessCode.PROPERTY);
        		return getter;
        	} else {
        		warn(meta, _loc.get("access-none", meta, property));
        		throw new IllegalStateException(
                    _loc.get("access-none", meta, property).toString());
        	}
        } else {
        	throw new InternalException(meta + " " +
        		AccessCode.toClassString(meta.getAccessType()));
        }
    }

    // ========================================================================
    //  Selection Filters select specific elements from a collection.
    //  Used to determine the persistent members of a given class.
    // ========================================================================

    /**
     * Inclusive element filtering predicate.
     *
     */
    private interface InclusiveFilter<T extends AnnotatedElement> {
        /**
         * Return true to include the given element.
         */
        boolean includes(T e);
    }

    /**
     * Filter the given collection with the conjunction of filters. The given
     * collection itself is not modified.
     */
    <T extends AnnotatedElement> List<T> filter(T[] array,
    	InclusiveFilter... filters) {
        List<T> result = new ArrayList<>();
        for (T e : array) {
            boolean include = true;
            for (InclusiveFilter f : filters) {
                if (f != null && !f.includes(e)) {
                    include = false;
                    break;
                }
            }
            if (include)
                result.add(e);
        }
        return result;
    }

    <T extends AnnotatedElement> List<T> filter(List<T> list,
        	InclusiveFilter... filters) {
        List<T> result = new ArrayList<>();
        for (T e : list) {
            boolean include = true;
            for (InclusiveFilter f : filters) {
                if (f != null && !f.includes(e)) {
                    include = false;
                    break;
                }
            }
            if (include)
                result.add(e);
        }
        return result;
    }

    /**
     * Selects getter method. A getter method name starts with 'get', returns a
     * non-void type and has no argument. Or starts with 'is', returns a boolean
     * and has no argument.
     *
     */
    static class GetterFilter implements InclusiveFilter<Method> {

        private boolean includePrivate;

        @Override
        public boolean includes(Method method) {
            return isGetter(method, isIncludePrivate());
        }

        public void setIncludePrivate(boolean includePrivate) {
            this.includePrivate = includePrivate;
        }

        public boolean isIncludePrivate() {
            return includePrivate;
        }
    }

    /**
     * Selects setter method. A setter method name starts with 'set', returns a
     * void and has single argument.
     *
     */
    static class SetterFilter implements InclusiveFilter<Method> {
        @Override
        public boolean includes(Method method) {
            return isSetter(method);
        }
        /**
         * Affirms if the given method matches the following signature
         * <code> public void setXXX(T t) </code>
         */
        public static boolean isSetter(Method method) {
        	String methodName = method.getName();
        	return startsWith(methodName, "set")
        	    && method.getParameterTypes().length == 1
        	    && method.getReturnType() == void.class;
        }
    }

    /**
     * Selects elements which is annotated with @Access annotation and that
     * annotation has the given AccessType value.
     *
     */
    static class AccessFilter implements InclusiveFilter<AnnotatedElement> {
        final AccessType target;

        public AccessFilter(AccessType target) {
            this.target = target;
        }

        @Override
        public boolean includes(AnnotatedElement obj) {
        	Access access = obj.getAnnotation(Access.class);
        	return access != null && access.value().equals(target);
        }
    }

    /**
     * Selects elements which is annotated with @Access annotation and that
     * annotation has the given AccessType value.
     *
     */
    static class MemberFilter implements InclusiveFilter<AnnotatedElement> {
        final Class<?> target;

        public MemberFilter(Class<?> target) {
            this.target = target;
        }

        @Override
        public boolean includes(AnnotatedElement obj) {
        	int mods = ((Member)obj).getModifiers();

            return obj.getClass() == target &&
                 !(Modifier.isStatic(mods) || Modifier.isFinal(mods)
                || Modifier.isTransient(mods) || Modifier.isNative(mods));

        }
    }

    /**
     * Selects non-transient elements.  Selectively will examine only the
     * transient field modifier.
     */
    static class TransientFilter implements InclusiveFilter<AnnotatedElement> {
        final boolean modifierOnly;

        public TransientFilter(boolean modOnly) {
            modifierOnly = modOnly;
        }

        @Override
        public boolean includes(AnnotatedElement obj) {
            if (modifierOnly) {
                return !Modifier.isTransient(((Member)obj).getModifiers());
            }
        	return !obj.isAnnotationPresent(Transient.class) &&
        	       !Modifier.isTransient(((Member)obj).getModifiers());
        }
    }

    /**
     * Selects all element annotated with <code>javax.persistence.*</code> or
     * <code>org.apache.openjpa.*</code> annotation except the annotations
     * marked to be ignored.
     */
    static class AnnotatedFilter implements InclusiveFilter<AnnotatedElement> {
        @Override
        public boolean includes(AnnotatedElement obj) {
            Annotation[] annos = AccessController.doPrivileged(J2DoPrivHelper
                    .getAnnotationsAction(obj));
        	for (Annotation anno : annos) {
        		String name = anno.annotationType().getName();
                if ((name.startsWith("javax.persistence.")
                  || name.startsWith("org.apache.openjpa.persistence."))
                  && !_ignoredAnnos.contains(name))
                	return true;
        	}
        	return false;
        }
    }

    private void logNoSetter(ClassMetaData meta, String name, Exception e) {
        Log log = meta.getRepository().getConfiguration()
            .getLog(OpenJPAConfiguration.LOG_METADATA);
        if (log.isWarnEnabled())
            log.warn(_loc.get("no-setter-for-getter", name,
                meta.getDescribedType().getName()));
        else if (log.isTraceEnabled())
            // log the exception, if any, if we're in trace-level debugging
            log.warn(_loc.get("no-setter-for-getter", name,
                meta.getDescribedType().getName()), e);
    }

    private Log getLog(ClassMetaData meta) {
        return meta.getRepository().getConfiguration()
            .getLog(OpenJPAConfiguration.LOG_METADATA);
    }

    String toFieldNames(List<Field> fields) {
    	return fields.toString();
    }

    String toMethodNames(List<Method> methods) {
    	return methods.toString();
    }

    @Override
    public boolean isAbstractMappingUniDirectional(OpenJPAConfiguration conf) {
        if (_isAbstractMappingUniDirectional == null)
            setAbstractMappingUniDirectional(conf);
        return _isAbstractMappingUniDirectional;
    }

    public void setAbstractMappingUniDirectional(OpenJPAConfiguration conf) {
        _isAbstractMappingUniDirectional = conf.getCompatibilityInstance().isAbstractMappingUniDirectional();
    }

    @Override
    public boolean isNonDefaultMappingAllowed(OpenJPAConfiguration conf) {
        if (_isNonDefaultMappingAllowed == null)
            setNonDefaultMappingAllowed(conf);
        return _isNonDefaultMappingAllowed;
    }

    public void setNonDefaultMappingAllowed(OpenJPAConfiguration conf) {
        _isNonDefaultMappingAllowed = conf.getCompatibilityInstance().
            isNonDefaultMappingAllowed();
    }

    @Override
    public Boolean isDefaultCascadePersistEnabled() {
        return _isCascadePersistPersistenceUnitDefaultEnabled;
    }

    @Override
    public void setDefaultCascadePersistEnabled(Boolean bool) {
        _isCascadePersistPersistenceUnitDefaultEnabled = bool;
    }

    @Override
    public String getDefaultSchema() {
        return _defaultSchema;
    }

    @Override
    public void setDefaultSchema(String schema) {
        _defaultSchema=schema;
    }
}
