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

import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;

import org.apache.openjpa.enhance.PCRegistry;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.UserException;

/**
 * Abstract implementation provides a set of generic utilities for detecting
 * persistence meta-data of Field/Member. Also provides bean-style properties
 * such as access style or identity type to be used by default when such
 * information is not derivable from available meta-data.
 *
 * @author Abe White
 * @author Pinaki Poddar
 */
public abstract class AbstractMetaDataDefaults
    implements MetaDataDefaults {

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

    private int _access = AccessCode.FIELD;
    private int _identity = ClassMetaData.ID_UNKNOWN;
    private boolean _ignore = true;
    private boolean _interface = true;
    private boolean _pcRegistry = true;
    private int _callback = CALLBACK_RETHROW;
    private boolean _unwrapped = false;

    /**
     * Whether to attempt to use the information from registered classes
     * to populate metadata defaults. Defaults to true.
     */
    public boolean getUsePCRegistry() {
        return _pcRegistry;
    }

    /**
     * Whether to attempt to use the information from registered classes
     * to populate metadata defaults. Defaults to true.
     */
    public void setUsePCRegistry(boolean pcRegistry) {
        _pcRegistry = pcRegistry;
    }

    /**
     * The default access type for base classes with ACCESS_UNKNOWN.
     * ACCESS_FIELD by default.
     */
    @Override
    public int getDefaultAccessType() {
        return _access;
    }

    /**
     * The default access type for base classes with ACCESS_UNKNOWN.
     * ACCESS_FIELD by default.
     */
    public void setDefaultAccessType(int access) {
        _access = access;
    }

    /**
     * The default identity type for unmapped classes without primary
     * key fields. ID_UNKNOWN by default.
     */
    @Override
    public int getDefaultIdentityType() {
        return _identity;
    }

    /**
     * The default identity type for unmapped classes without primary
     * key fields. ID_UNKNOWN by default.
     */
    public void setDefaultIdentityType(int identity) {
        _identity = identity;
    }

    @Override
    public int getCallbackMode() {
        return _callback;
    }

    public void setCallbackMode(int mode) {
        _callback = mode;
    }

    public void setCallbackMode(int mode, boolean on) {
        if (on)
            _callback |= mode;
        else
            _callback &= ~mode;
    }

    @Override
    public boolean getCallbacksBeforeListeners(int type) {
        return false;
    }

    @Override
    public boolean isDeclaredInterfacePersistent() {
        return _interface;
    }

    public void setDeclaredInterfacePersistent(boolean pers) {
        _interface = pers;
    }

    @Override
    public boolean isDataStoreObjectIdFieldUnwrapped() {
        return _unwrapped;
    }

    public void setDataStoreObjectIdFieldUnwrapped(boolean unwrapped) {
        _unwrapped = unwrapped;
    }

    public boolean getIgnoreNonPersistent() {
        return _ignore;
    }

    @Override
    public void setIgnoreNonPersistent(boolean ignore) {
        _ignore = ignore;
    }

    @Override
    public void populate(ClassMetaData meta, int access) {
        populate(meta, access, false);
    }

    @Override
    public void populate(ClassMetaData meta, int access, boolean ignoreTransient) {
        if (meta.getDescribedType() == Object.class)
            return;
        meta.setAccessType(access);

        Log log = meta.getRepository().getLog();
        if (log.isTraceEnabled())
            log.trace(_loc.get("gen-meta", meta));
        if (!_pcRegistry || !populateFromPCRegistry(meta)) {
            if (log.isTraceEnabled())
                log.trace(_loc.get("meta-reflect"));
            populateFromReflection(meta, ignoreTransient);
        }
    }

    /**
     * Populate the given metadata using the {@link PCRegistry}.
     */
    private boolean populateFromPCRegistry(ClassMetaData meta) {
        Class<?> cls = meta.getDescribedType();
        if (!PCRegistry.isRegistered(cls))
            return false;
        try {
            String[] fieldNames = PCRegistry.getFieldNames(cls);
            Class<?>[] fieldTypes = PCRegistry.getFieldTypes(cls);
            Member member;
            FieldMetaData fmd;
            for (int i = 0; i < fieldNames.length; i ++) {
            	String property = fieldNames[i];
                member = getMemberByProperty(meta, property,
                	AccessCode.UNKNOWN, true);
                if (member == null) // transient or indeterminable access
                	continue;
                fmd = meta.addDeclaredField(property, fieldTypes[i]);
                fmd.backingMember(member);
                populate(fmd);
            }
            return true;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (Exception e) {
            if (e instanceof PrivilegedActionException)
                e = ((PrivilegedActionException) e).getException();
            throw new UserException(e);
        }
    }

    protected abstract List<Member> getPersistentMembers(ClassMetaData meta, boolean ignoreTransient);
    /**
     * Generate the given meta-data using reflection.
     * Adds FieldMetaData for each persistent state.
     * Delegate to concrete implementation to determine the persistent
     * members.
     */
    private void populateFromReflection(ClassMetaData meta, boolean ignoreTransient) {
        List<Member> members = getPersistentMembers(meta, ignoreTransient);
        boolean iface = meta.getDescribedType().isInterface();
        // If access is mixed or if the default is currently unknown,
        // process all fields, otherwise only process members of the class
        // level default access type.

        String name;
        boolean def;
        FieldMetaData fmd;
        for (Member member : members) {
            name = getFieldName(member);
            if (name == null || isReservedFieldName(name))
                continue;

            def = isDefaultPersistent(meta, member, name, ignoreTransient);
            if (!def && _ignore)
                continue;

            // passed the tests; persistent type -- we construct with
            // Object.class because setting backing member will set proper
            // type anyway
            fmd = meta.addDeclaredField(name, Object.class);
            fmd.backingMember(member);
            if (!def) {
                fmd.setExplicit(true);
                fmd.setManagement(FieldMetaData.MANAGE_NONE);
            }
            populate(fmd);
        }
    }

    protected void populate(FieldMetaData fmd) {

    }

    /**
     * Return the list of fields in <code>meta</code> that use field access,
     * or <code>null</code> if a list of fields is unobtainable. An empty list
     * should be returned if the list of fields is obtainable, but there
     * happens to be no field access in <code>meta</code>.
     *
     * This is used for error reporting purposes only, so need not be efficient.
     *
     * This implementation returns <code>null</code>.
     */
    protected List<String> getFieldAccessNames(ClassMetaData meta) {
        return null;
    }

    /**
     * Return the list of methods in <code>meta</code> that use property access,
     * or <code>null</code> if a list of methods is unobtainable. An empty list
     * should be returned if the list of methods is obtainable, but there
     * happens to be no property access in <code>meta</code>.
     *
     * This is used for error reporting purposes only, so need not be efficient.
     *
     * This implementation returns <code>null</code>.
     */
    protected List<String> getPropertyAccessNames(ClassMetaData meta) {
        return null;
    }

    /**
     * Return the field name for the given member. This will only be invoked
     * on members of the right type (field vs. method). Return null if the
     * member cannot be managed. Default behavior: For fields, returns the
     * field name. For getter methods, returns the minus "get" or "is" with
     * the next letter lower-cased. For other methods, returns null.
     */
    public static String getFieldName(Member member) {
        if (member instanceof Field)
            return member.getName();
        if (!(member instanceof Method))
        	return null;
        Method method = (Method) member;
        String name = method.getName();
        if (isNormalGetter(method))
        	name = name.substring("get".length());
        else if (isBooleanGetter(method))
        	name = name.substring("is".length());
        else
            return null;

        if (name.length() == 1)
            return name.toLowerCase();
        return Character.toLowerCase(name.charAt(0)) + name.substring(1);
    }

    /**
     * Returns true if the given field name is reserved for unmanaged fields.
     */
    protected boolean isReservedFieldName(String name) {
        // names used by enhancers
        return name.startsWith("openjpa") || name.startsWith("jdo");
    }

    /**
     * Return true if the given member is persistent by default. This will
     * only be invoked on members of the right type (field vs. method).
     * Returns false if member is static or final by default.
     *
     * @param name the field name from {@link #getFieldName}
     */
    protected abstract boolean isDefaultPersistent(ClassMetaData meta,
        Member member, String name, boolean ignoreTransient);

    /**
     * Gets the backing member of the given field. If the field has not been
     * assigned a backing member then get either the instance field or the
     * getter method depending upon the access style of the defining class.
     * <br>
     * Defining class is used instead of declaring class because this method
     * may be invoked during parsing phase when declaring metadata may not be
     * available.
     */
    @Override
    public Member getBackingMember(FieldMetaData fmd) {
        if (fmd == null)
            return null;
        if (fmd.getBackingMember() != null)
        	return fmd.getBackingMember();
        return getMemberByProperty(fmd.getDeclaringMetaData(), fmd.getName(),
            fmd.getAccessType(), true);
    }

    @Override
    public Class<?> getUnimplementedExceptionType() {
        return UnsupportedOperationException.class;
    }

    /**
     * Helper method; returns true if the given class appears to be
     * user-defined.
     */
    protected static boolean isUserDefined(Class<?> cls) {
        return cls != null && !cls.getName().startsWith("java.")
            && !cls.getName().startsWith ("javax.")
            && !cls.getName().startsWith ("jakarta.");
	}

    /**
     * Affirms if the given method matches the following signature
     * <code> public T getXXX() </code>
     * where T is any non-void type.
     */
    public static boolean isNormalGetter(Method method) {
    	String methodName = method.getName();
    	return startsWith(methodName, "get")
    	    && method.getParameterTypes().length == 0
    	    && method.getReturnType() != void.class;
    }

    /**
     * Affirms if the given method matches the following signature
     * <code> public boolean isXXX() </code>
     * <code> public Boolean isXXX() </code>
     */
    public static boolean isBooleanGetter(Method method) {
    	String methodName = method.getName();
    	return startsWith(methodName, "is")
    	    && method.getParameterTypes().length == 0
    	    && isBoolean(method.getReturnType());
    }

    /**
     * Affirms if the given method signature matches bean-style getter method
     * signature.<br>
     * <code> public T getXXX()</code> where T is any non-void type.<br>
     * or<br>
     * <code> public T isXXX()</code> where T is boolean or Boolean.<br>
     */
    public static boolean isGetter(Method method, boolean includePrivate) {
    	if (method == null)
    		return false;
    	int mods = method.getModifiers();
    	if (!(Modifier.isPublic(mods)
    	      || Modifier.isProtected(mods)
    	      || (Modifier.isPrivate(mods) && includePrivate))
    	 || Modifier.isNative(mods)
    	 || Modifier.isStatic(mods))
    		return false;
    	return isNormalGetter(method) || isBooleanGetter(method);
    }

    /**
     * Affirms if the given full string starts with the given head.
     */
    public static boolean startsWith(String full, String head) {
        return full != null && head != null && full.startsWith(head)
            && full.length() > head.length();
    }

    public static boolean isBoolean(Class<?> cls) {
    	return cls == boolean.class || cls == Boolean.class;
    }

    public static List<String> toNames(List<? extends Member> members) {
    	List<String> result = new ArrayList<>();
    	for (Member m : members)
    		result.add(m.getName());
    	return result;
    }

}
