Package info.archinnov.achilles.internal.metadata.parsing

Source Code of info.archinnov.achilles.internal.metadata.parsing.EntityIntrospector

/*
* Copyright (C) 2012-2014 DuyHai DOAN
*
*  Licensed 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 info.archinnov.achilles.internal.metadata.parsing;

import static com.google.common.base.Optional.fromNullable;
import static info.archinnov.achilles.internal.helper.LoggerHelper.fieldToStringFn;
import static info.archinnov.achilles.internal.metadata.parsing.NamingHelper.applyNamingStrategy;
import static info.archinnov.achilles.internal.table.SchemaNameNormalizer.extractTableNameFromCanonical;
import static info.archinnov.achilles.internal.table.SchemaNameNormalizer.validateSchemaName;
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import com.google.common.base.Optional;
import info.archinnov.achilles.annotations.Column;
import info.archinnov.achilles.annotations.Id;
import info.archinnov.achilles.internal.validation.Validator;
import info.archinnov.achilles.type.NamingStrategy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
import info.archinnov.achilles.annotations.Consistency;
import info.archinnov.achilles.annotations.Entity;
import info.archinnov.achilles.annotations.Strategy;
import info.archinnov.achilles.exception.AchillesBeanMappingException;
import info.archinnov.achilles.internal.context.ConfigurationContext;
import info.archinnov.achilles.internal.metadata.parsing.context.EntityParsingContext;
import info.archinnov.achilles.type.ConsistencyLevel;
import info.archinnov.achilles.type.InsertStrategy;
import info.archinnov.achilles.type.Pair;

public class EntityIntrospector {
    private static final Logger log = LoggerFactory.getLogger(EntityIntrospector.class);

    private PropertyFilter filter = PropertyFilter.Singleton.INSTANCE.get();

    protected String[] deriveGetterName(Field field) {
        log.debug("Derive getter name for field {} from class {}", field.getName(), field.getDeclaringClass()
                .getCanonicalName());

        String camelCase = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);

        String[] getters;

        if (StringUtils.equals(field.getType().toString(), "boolean")) {
            getters = new String[] { "is" + camelCase, "get" + camelCase };
        } else {
            getters = new String[] { "get" + camelCase };
        }
        if (log.isTraceEnabled()) {
            log.trace("Derived getters : {}", StringUtils.join(getters, ","));
        }
        return getters;
    }

    protected String deriveSetterName(Field field) {
        log.debug("Derive setter name for field {} from class {}", field.getName(), field.getDeclaringClass()
                .getCanonicalName());

        String fieldName = field.getName();
        String setter = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        log.trace("Derived setter : {}", setter);
        return setter;
    }

    public Method findGetter(Class<?> beanClass, Field field) {
        log.debug("Find getter for field {} in class {}", field.getName(), beanClass.getCanonicalName());

        Method getterMethod = null;
        String fieldName = field.getName();
        String[] getters = this.deriveGetterName(field);

        for (String getter : getters) {
            try {
                getterMethod = beanClass.getMethod(getter);
                if (getterMethod.getReturnType() != field.getType()) {
                    throw new AchillesBeanMappingException("The getter for field '" + fieldName + "' of type '"
                            + field.getDeclaringClass().getCanonicalName() + "' does not return correct type");
                }
            } catch (NoSuchMethodException e) {
                // Do nothing here
            }
        }
        if (getterMethod == null) {
            throw new AchillesBeanMappingException("The getter for field '" + fieldName + "' of type '"
                    + field.getDeclaringClass().getCanonicalName() + "' does not exist");
        }

        log.trace("Derived getter method : {}", getterMethod.getName());
        return getterMethod;
    }

    public Method findSetter(Class<?> beanClass, Field field) {
        log.debug("Find setter for field {} in class {}", field.getName(), beanClass.getCanonicalName());

        String fieldName = field.getName();

        try {
            String setter = this.deriveSetterName(field);
            Method setterMethod = beanClass.getMethod(setter, field.getType());

            if (!setterMethod.getReturnType().toString().equals("void")) {
                throw new AchillesBeanMappingException("The setter for field '" + fieldName + "' of type '"
                        + field.getDeclaringClass().getCanonicalName()
                        + "' does not return correct type or does not have the correct parameter");
            }

            log.trace("Derived setter method : {}", setterMethod.getName());
            return setterMethod;

        } catch (NoSuchMethodException e) {
            throw new AchillesBeanMappingException("The setter for field '" + fieldName + "' of type '"
                    + field.getDeclaringClass().getCanonicalName() + "' does not exist or is incorrect");
        }
    }

    public Method[] findAccessors(Class<?> beanClass, Field field) {
        log.debug("Find accessors for field {} in class {}", field.getName(), beanClass.getCanonicalName());

        Method[] accessors = new Method[2];

        accessors[0] = findGetter(beanClass, field);
        accessors[1] = findSetter(beanClass, field);

        return accessors;
    }

    public String inferKeyspaceName(Class<?> entityClass, Optional<String> currentKeyspaceNameO, NamingStrategy namingStrategy) {
        String keyspaceName = currentKeyspaceNameO.or("");
        if(isNoneBlank(keyspaceName)) return keyspaceName;

        Entity annotation = entityClass.getAnnotation(Entity.class);

        keyspaceName = applyNamingStrategy(annotation.keyspace(), namingStrategy);

        Validator.validateBeanMappingTrue(isNotBlank(keyspaceName),"No keyspace name found for entity '"+entityClass.getCanonicalName()+"'. Keyspace name is looked up using either the @Entity annotation or in configuration parameter");

        keyspaceName = validateSchemaName(keyspaceName);
        return keyspaceName;
    }

    public String inferTableName(Class<?> entityClass, String canonicalName, NamingStrategy namingStrategy) {
        Entity annotation = entityClass.getAnnotation(Entity.class);
        String tableName;
        if (isNotBlank(annotation.table())) {
            tableName = validateSchemaName(applyNamingStrategy(annotation.table(), namingStrategy));
        } else {
            tableName = validateSchemaName(applyNamingStrategy(extractTableNameFromCanonical(canonicalName), namingStrategy));
        }
        log.debug("Inferred tableName for entity {} : {}", canonicalName, tableName);
        return tableName;
    }

    public String inferTableComment(Class<?> entity, String defaultComment) {
        String comment = defaultComment;
        Entity annotation = entity.getAnnotation(Entity.class);
        if (isNotBlank(annotation.comment())) {
            comment = annotation.comment().trim().replaceAll("'","''");
        }
        return comment;
    }

    public <T> Pair<ConsistencyLevel, ConsistencyLevel> findConsistencyLevels(Class<T> entity, String tableName, ConfigurationContext configContext) {
        log.debug("Find consistency levels for entity class {}", entity.getCanonicalName());

        ConsistencyLevel readLevel = configContext.getDefaultReadConsistencyLevel();
        ConsistencyLevel writeLevel = configContext.getDefaultWriteConsistencyLevel();

        Consistency clevel = entity.getAnnotation(Consistency.class);

        if (clevel != null) {
            readLevel = clevel.read();
            writeLevel = clevel.write();
        }

        readLevel = fromNullable(configContext.getReadConsistencyLevelForTable(tableName)).or(readLevel);
        writeLevel = fromNullable(configContext.getWriteConsistencyLevelForTable(tableName)).or(writeLevel);

        log.trace("Found consistency levels : {}/{}", readLevel, writeLevel);

        return Pair.create(readLevel, writeLevel);
    }

    public List<Field> getInheritedPrivateFields(Class<?> type) {
        log.debug("Find inherited private fields from hierarchy for entity class {}", type.getCanonicalName());

        List<Field> fields = new ArrayList<>();

        Class<?> i = type;
        while (i != null && i != Object.class) {
            for (Field declaredField : i.getDeclaredFields()) {
                if (filter.matches(declaredField)) {
                    fields.add(declaredField);
                }
            }
            i = i.getSuperclass();
        }
        if (log.isTraceEnabled()) {
            log.trace("Found inherited private fields : {}", Lists.transform(fields, fieldToStringFn));
        }
        return fields;
    }

    public Field getInheritedPrivateFields(Class<?> type, Class<?> annotation) {
        log.debug("Find private field from hierarchy with annotation {} for entity class {}",
                annotation.getCanonicalName(), type.getCanonicalName());

        Class<?> i = type;
        while (i != null && i != Object.class) {
            for (Field declaredField : i.getDeclaredFields()) {
                if (filter.matches(declaredField, annotation)) {
                    log.trace("Found inherited private field : {}", declaredField);
                    return declaredField;
                }
            }
            i = i.getSuperclass();
        }
        return null;
    }

    public Field getInheritedPrivateFields(Class<?> type, Class<?> annotation, String name) {
        log.debug("Find private field with name {} having annotation {} from hierarchy for entity class {}", name,
                annotation.getCanonicalName(), type.getCanonicalName());

        Class<?> i = type;
        while (i != null && i != Object.class) {
            for (Field declaredField : i.getDeclaredFields()) {
                if (filter.matches(declaredField, annotation, name)) {
                    log.trace("Found inherited private field : {}", declaredField);
                    return declaredField;
                }
            }
            i = i.getSuperclass();
        }
        return null;
    }

    public InsertStrategy getInsertStrategy(Class<?> type, EntityParsingContext parsingContext) {
        Strategy strategy = type.getAnnotation(Strategy.class);

        return strategy != null ? strategy.insert() : parsingContext.getDefaultInsertStrategy();
    }

    public NamingStrategy determineClassNamingStrategy(ConfigurationContext configContext, Class<?> currentEntityClass) {
        final Strategy strategy = currentEntityClass.getAnnotation(Strategy.class);
        return strategy != null ? strategy.naming() : configContext.getGlobalNamingStrategy();
    }

    public String inferCQLColumnName(Field field, NamingStrategy namingStrategy) {
        final String columnName = field.getName();
        log.trace("Inferring property columnName for property {}", columnName);
        final Column column = field.getAnnotation(Column.class);
        final Id id = field.getAnnotation(Id.class);

        if (column != null) {
            return determineColumnNameUsingStrategy(column.name(), columnName, namingStrategy);
        } else if (id != null) {
            return determineColumnNameUsingStrategy(id.name(), columnName, namingStrategy);
        } else {
            return applyNamingStrategy(columnName, namingStrategy);
        }
    }

    private String determineColumnNameUsingStrategy(String customColumnName, String canonicalName, NamingStrategy namingStrategy) {
        return isNoneBlank(customColumnName) ? customColumnName: applyNamingStrategy(canonicalName, namingStrategy);
    }

    public static enum Singleton {
        INSTANCE;

        private final EntityIntrospector instance = new EntityIntrospector();

        public EntityIntrospector get() {
            return instance;
        }
    }
}
TOP

Related Classes of info.archinnov.achilles.internal.metadata.parsing.EntityIntrospector

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.