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

org.apache.cayenne.gen.PropertyUtils Maven / Gradle / Ivy

/*****************************************************************
 *   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
 *
 *    https://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.cayenne.gen;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.cayenne.EmbeddableObject;
import org.apache.cayenne.Fault;
import org.apache.cayenne.Persistent;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.di.AdhocObjectFactory;
import org.apache.cayenne.di.DIRuntimeException;
import org.apache.cayenne.exp.property.BaseIdProperty;
import org.apache.cayenne.exp.property.BaseProperty;
import org.apache.cayenne.exp.property.DateProperty;
import org.apache.cayenne.exp.property.EmbeddableProperty;
import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.ListProperty;
import org.apache.cayenne.exp.property.MapProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.SetProperty;
import org.apache.cayenne.exp.property.StringProperty;
import org.apache.cayenne.gen.property.PropertyDescriptorCreator;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.Embeddable;
import org.apache.cayenne.map.EmbeddableAttribute;
import org.apache.cayenne.map.EmbeddedAttribute;
import org.apache.cayenne.map.ObjAttribute;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
import org.slf4j.Logger;

/**
 * @since 4.2
 */
public class PropertyUtils {

    private static final String PK_PROPERTY_SUFFIX = "_PK_PROPERTY";
    private static final char DUPLICATE_NAME_SUFFIX = '_';
    private static final Map FACTORY_METHODS = new HashMap<>();

    static {
        FACTORY_METHODS.put(BaseProperty.class.getName(), "createBase");
        FACTORY_METHODS.put(NumericProperty.class.getName(), "createNumeric");
        FACTORY_METHODS.put(StringProperty.class.getName(), "createString");
        FACTORY_METHODS.put(DateProperty.class.getName(), "createDate");
        FACTORY_METHODS.put(ListProperty.class.getName(), "createList");
        FACTORY_METHODS.put(SetProperty.class.getName(), "createSet");
        FACTORY_METHODS.put(MapProperty.class.getName(), "createMap");
        FACTORY_METHODS.put(EmbeddableProperty.class.getName(), "createEmbeddable");
        FACTORY_METHODS.put(NumericIdProperty.class.getName(), "createNumericId");
        FACTORY_METHODS.put(BaseIdProperty.class.getName(), "createBaseId");
    }

    private static final List> JAVA_DATE_TYPES = Arrays.asList(
            java.util.Date.class,
            java.time.LocalDate.class,
            java.time.LocalTime.class,
            java.time.LocalDateTime.class,
            java.sql.Date.class,
            java.sql.Time.class,
            java.sql.Timestamp.class
    );

    private final ImportUtils importUtils;

    private List propertyList;
    private AdhocObjectFactory adhocObjectFactory;

    private Logger logger;

    public PropertyUtils(ImportUtils importUtils) {
        this.importUtils = importUtils;
        this.propertyList = new ArrayList<>();

    }

    public PropertyUtils(ImportUtils importUtils,
                         AdhocObjectFactory adhocObjectFactory,
                         List propertyList,
                         Logger logger) {
        this.importUtils = importUtils;
        this.adhocObjectFactory = adhocObjectFactory;
        this.propertyList = propertyList;
        this.logger = logger;
    }

    public void addImportForPK(EntityUtils entityUtils) {
        DbEntity entity = entityUtils.objEntity.getDbEntity();
        if(entity == null) {
            return;
        }
        boolean needToCreatePK = false;

        for(DbAttribute attribute : entity.getPrimaryKeys()) {
            if(!entityUtils.declaresDbAttribute(attribute)) {
                String javaBySqlType = TypesMapping.getJavaBySqlType(attribute);
                importUtils.addType(javaBySqlType);
                importUtils.addType(getPkPropertyTypeForType(javaBySqlType));
                needToCreatePK = true;
            }
        }

        if(needToCreatePK) {
            importUtils.addType(PropertyFactory.class.getName());
        }
    }

    public void addImportForSelfProperty(ObjEntity entity) {
        importUtils.addType(PropertyFactory.class.getName());
        importUtils.addType(SelfProperty.class.getName());
        importUtils.addType(entity.getJavaClassName());
    }

    public void addImport(ObjAttribute attribute) {
        importUtils.addType(PropertyFactory.class.getName());
        importUtils.addType(attribute.getType());
        importUtils.addType(getPropertyDescriptor(attribute.getType()).getPropertyType());
        if(attribute.isLazy()) {
            importUtils.addType(Fault.class.getName());
        }
    }

    public void addImport(EmbeddedAttribute attribute) {
        importUtils.addType(PropertyFactory.class.getName());
        importUtils.addType(attribute.getType());
        importUtils.addType(getPropertyDescriptor(EmbeddableObject.class.getName()).getPropertyType());
    }

    public void addImport(EmbeddableAttribute attribute) {
        importUtils.addType(PropertyFactory.class.getName());
        importUtils.addType(attribute.getType());
        importUtils.addType(getPropertyDescriptor(attribute.getType()).getPropertyType());
    }

    public void addImport(ObjRelationship relationship) {
        importUtils.addType(PropertyFactory.class.getName());
        if (relationship.getTargetEntity() != null) {
            importUtils.addType(relationship.getTargetEntity().getClassName());
        } else {
            importUtils.addType(Persistent.class.getName());
        }
        importUtils.addType(getPropertyTypeForJavaClass(relationship));
        if (relationship.isToMany()) {
            importUtils.addType(relationship.getCollectionType());
        }
    }

    public String selfPropertyDefinition(ObjEntity entity) {
        String propertyType = importUtils.formatJavaType(entity.getJavaClassName());
        return String.format("public static final SelfProperty<%s> SELF = PropertyFactory.createSelf(%s.class);",
                propertyType, propertyType);
    }

    public String propertyDefinition(ObjEntity entity, DbAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();

        String attributeType = TypesMapping.getJavaBySqlType(attribute);
        String propertyType = getPkPropertyTypeForType(TypesMapping.getJavaBySqlType(attribute));
        String propertyFactoryMethod = factoryMethodForPropertyType(propertyType);
        attributeType = importUtils.formatJavaType(attributeType, false);

        return String.format("public static final %s<%s> %s = PropertyFactory.%s(\"%s\", \"%s\", %s.class);",
                importUtils.formatJavaType(propertyType),
                attributeType,
                utils.capitalizedAsConstant(attribute.getName()) + PK_PROPERTY_SUFFIX,
                propertyFactoryMethod,
                attribute.getName(),
                entity.getName(),
                attributeType
        );
    }

    public String propertyDefinition(ObjAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();
        String attributeType = utils.stripGeneric(importUtils.formatJavaType(attribute.getType(), false));
        PropertyDescriptor propertyDescriptor = getPropertyDescriptor(attribute.getType());
        return String.format("public static final %s<%s> %s = %s(\"%s\", %s.class);",
                importUtils.formatJavaType(propertyDescriptor.getPropertyType()),
                attributeType,
                generatePropertyName(attribute),
                propertyDescriptor.getPropertyFactoryMethod(),
                attribute.getName(),
                attributeType
        );
    }

    protected String generatePropertyName(ObjAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();
        ObjEntity entity = attribute.getEntity();
        String name = utils.capitalizedAsConstant(attribute.getName());
        // ensure that final name is unique
        while(entity.getAttribute(name) != null) {
            name = name + DUPLICATE_NAME_SUFFIX;
        }
        return name;
    }

    public String propertyDefinition(EmbeddedAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();
        String attributeType = utils.stripGeneric(importUtils.formatJavaType(attribute.getType(), false));
        PropertyDescriptor propertyDescriptor = getPropertyDescriptor(EmbeddableObject.class.getName());
        return String.format("public static final %s<%s> %s = %s(\"%s\", %s.class);",
                importUtils.formatJavaType(propertyDescriptor.getPropertyType()),
                attributeType,
                generatePropertyName(attribute),
                propertyDescriptor.getPropertyFactoryMethod(),
                attribute.getName(),
                attributeType
        );
    }

    public String propertyDefinition(EmbeddableAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();
        String attributeType = utils.stripGeneric(importUtils.formatJavaType(attribute.getType(), false));
        PropertyDescriptor propertyDescriptor = getPropertyDescriptor(attribute.getType());
        return String.format("public static final %s<%s> %s = %s(\"%s\", %s.class);",
                importUtils.formatJavaType(propertyDescriptor.getPropertyType()),
                attributeType,
                generatePropertyName(attribute),
                propertyDescriptor.getPropertyFactoryMethod(),
                attribute.getName(),
                attributeType
        );
    }

    protected String generatePropertyName(EmbeddableAttribute attribute) {
        StringUtils utils = StringUtils.getInstance();
        Embeddable embeddable = attribute.getEmbeddable();
        String name = utils.capitalizedAsConstant(attribute.getName());
        // ensure that final name is unique
        while(embeddable.getAttribute(name) != null) {
            name = name + DUPLICATE_NAME_SUFFIX;
        }
        return name;
    }

    public String propertyDefinition(ObjRelationship relationship) {
        if (relationship.isToMany()) {
            return toManyRelationshipDefinition(relationship);
        } else {
            return toOneRelationshipDefinition(relationship);
        }
    }

    private String toManyRelationshipDefinition(ObjRelationship relationship) {
        if (Map.class.getName().equals(relationship.getCollectionType())) {
            return mapRelationshipDefinition(relationship);
        } else {
            return collectionRelationshipDefinition(relationship);
        }
    }

    private String mapRelationshipDefinition(ObjRelationship relationship) {
        StringUtils utils = StringUtils.getInstance();

        String propertyType = getPropertyTypeForJavaClass(relationship);
        String propertyFactoryMethod = factoryMethodForPropertyType(propertyType);
        String mapKeyType = importUtils.formatJavaType(EntityUtils.getMapKeyTypeInternal(relationship));
        String attributeType = getRelatedTypeName(relationship);

        return String.format("public static final %s<%s, %s> %s = PropertyFactory.%s(\"%s\", %s.class, %s.class);",
                importUtils.formatJavaType(propertyType),
                mapKeyType,
                attributeType,
                utils.capitalizedAsConstant(relationship.getName()),
                propertyFactoryMethod,
                relationship.getName(),
                mapKeyType,
                attributeType
        );
    }

    private String collectionRelationshipDefinition(ObjRelationship relationship) {
        StringUtils utils = StringUtils.getInstance();

        String propertyType = getPropertyTypeForJavaClass(relationship);
        String propertyFactoryMethod = factoryMethodForPropertyType(propertyType);
        String entityType = getRelatedTypeName(relationship);

        return String.format("public static final %s<%s> %s = PropertyFactory.%s(\"%s\", %s.class);",
                importUtils.formatJavaType(propertyType),
                entityType,
                utils.capitalizedAsConstant(relationship.getName()),
                propertyFactoryMethod,
                relationship.getName(),
                entityType
        );
    }

    private String getRelatedTypeName(ObjRelationship relationship) {
        if(relationship.getTargetEntity() == null) {
            return Persistent.class.getSimpleName();
        }

        return importUtils.formatJavaType(relationship.getTargetEntity().getClassName());
    }

    private String toOneRelationshipDefinition(ObjRelationship relationship) {
        StringUtils utils = StringUtils.getInstance();

        String propertyType = EntityProperty.class.getName();
        String propertyFactoryMethod = "createEntity";
        String attributeType = getRelatedTypeName(relationship);

        return String.format("public static final %s<%s> %s = PropertyFactory.%s(\"%s\", %s.class);",
                importUtils.formatJavaType(propertyType),
                attributeType,
                utils.capitalizedAsConstant(relationship.getName()),
                propertyFactoryMethod,
                relationship.getName(),
                attributeType
        );
    }

    private String factoryMethodForPropertyType(String propertyType) {
        return FACTORY_METHODS.get(propertyType);
    }

    private String getPkPropertyTypeForType(String attributeType) {
        try {
            Class javaClass = Class.forName(attributeType);
            if (Number.class.isAssignableFrom(javaClass)) {
                return NumericIdProperty.class.getName();
            }
        } catch (ClassNotFoundException ex) {
            return BaseIdProperty.class.getName();
        }
        return BaseIdProperty.class.getName();
    }

    private String getPropertyTypeForJavaClass(ObjRelationship relationship) {
        if (relationship.isToMany()) {
            String collectionType = relationship.getCollectionType();
            if (java.util.Map.class.getName().equals(collectionType)) {
                return MapProperty.class.getName();
            }

            if (java.util.List.class.getName().equals(collectionType) || java.util.Collection.class.getName().equals(collectionType)) {
                return ListProperty.class.getName();
            }

            return SetProperty.class.getName();
        }

        return EntityProperty.class.getName();
    }

    public PropertyDescriptor getPropertyDescriptor(String attrType) {
        try {
            Class type = adhocObjectFactory.getJavaClass(attrType);
            for(PropertyDescriptorCreator creator : propertyList) {
                Optional optionalPropertyDescriptor = creator.apply(type);
                if(optionalPropertyDescriptor.isPresent()) {
                    return optionalPropertyDescriptor.get();
                }
            }
        } catch (DIRuntimeException ex) {
            if(logger != null) {
                logger.warn("WARN: Class not found: " + attrType + ". Will use default PropertyDescriptor.");
            }
            return PropertyDescriptor.defaultDescriptor();
        }
        return PropertyDescriptor.defaultDescriptor();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy