/* * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) * * 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 com.querydsl.codegen; import java.lang.annotation.Annotation; import java.util.*; import javax.annotation.Nullable; import com.google.common.base.Function; import com.mysema.codegen.StringUtils; import com.mysema.codegen.model.Constructor; import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeAdapter; import com.mysema.codegen.model.TypeCategory; /** * {@code EntityType} represents a model of a query domain type with properties * * @author tiwe */ public class EntityType extends TypeAdapter implements Comparable<EntityType> { private final Map<Class<?>,Annotation> annotations = new HashMap<Class<?>,Annotation>(); private final Set<Constructor> constructors = new HashSet<Constructor>(); private int escapeSuffix = 1; private final Set<Delegate> delegates = new HashSet<Delegate>(); private final Set<Property> properties = new TreeSet<Property>(); private final Set<String> propertyNames = new HashSet<String>(); private final Set<String> escapedPropertyNames = new HashSet<String>(); private final Set<Supertype> superTypes; private final Map<Object, Object> data = new HashMap<Object,Object>(); private String modifiedSimpleName; /** * Create a new {@code EntityType} instance for the given type * * @param type */ public EntityType(Type type) { this(type, new LinkedHashSet<Supertype>(), DefaultVariableNameFunction.INSTANCE); } /** * Create a new {@code EntityType} instance for the given type * * @param type the type to be used * @param variableNameFunction the variable name function to be used */ public EntityType(Type type, Function<EntityType, String> variableNameFunction) { this(type, new LinkedHashSet<Supertype>(), variableNameFunction); } /** * Create a new {@code EntityType} instance for the given type and superTypes * * @param type * @param superTypes */ public EntityType(Type type, Set<Supertype> superTypes) { this(type, superTypes, DefaultVariableNameFunction.INSTANCE); } /** * Create a new {@code EntityType} instance for the given type and superTypes * * @param type the type to be used * @param superTypes the super types to be used * @param variableNameFunction the variable name function to be used */ private EntityType(Type type, Set<Supertype> superTypes, Function<EntityType, String> variableNameFunction) { super(type); this.superTypes = superTypes; this.modifiedSimpleName = variableNameFunction.apply(this); } public void addAnnotation(Annotation annotation) { annotations.put(annotation.annotationType(), annotation); } public void addConstructor(Constructor co) { constructors.add(co); } public void addDelegate(Delegate delegate) { delegates.add(delegate); } public void addProperty(Property field) { if (!propertyNames.contains(field.getName())) { propertyNames.add(field.getName()); escapedPropertyNames.add(field.getEscapedName()); properties.add(validateField(field)); } } public void addSupertype(Supertype entityType) { superTypes.add(entityType); } @Override public int compareTo(EntityType o) { return getType().getSimpleName().compareTo(o.getType().getSimpleName()); } @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof Type) { return getFullName().equals(((Type) o).getFullName()); } else { return false; } } @SuppressWarnings("unchecked") public <T extends Annotation> T getAnnotation(Class<T> type) { return (T) annotations.get(type); } public Collection<Annotation> getAnnotations() { return annotations.values(); } @Override public Type as(TypeCategory category) { if (getCategory() == category) { return this; } else { return super.as(category); } } @Override public TypeCategory getCategory() { if (getType().getCategory() == TypeCategory.ENTITY || !properties.isEmpty()) { return TypeCategory.ENTITY; } else { return TypeCategory.CUSTOM; } } public Set<Constructor> getConstructors() { return constructors; } public Map<Object, Object> getData() { return data; } public Set<Delegate> getDelegates() { return delegates; } public TypeCategory getOriginalCategory() { return super.getCategory(); } public Set<Property> getProperties() { return properties; } @Nullable public Supertype getSuperType() { return superTypes.size() == 1 ? superTypes.iterator().next() : null; } public Set<Supertype> getSuperTypes() { return superTypes; } /** * Use {@link #getModifiedSimpleName()} */ @Deprecated public String getUncapSimpleName() { return modifiedSimpleName; } public String getModifiedSimpleName() { return modifiedSimpleName; } @Override public int hashCode() { return getFullName().hashCode(); } public boolean hasArrays() { return hasPropertyWithType(TypeCategory.ARRAY); } public boolean hasEntityFields() { return hasPropertyWithType(TypeCategory.ENTITY); } public boolean hasInits() { for (Property property : properties) { if (!property.getInits().isEmpty()) { return true; } } return false; } public boolean hasLists() { return hasPropertyWithType(TypeCategory.LIST); } public boolean hasCollections() { return hasPropertyWithType(TypeCategory.COLLECTION); } public boolean hasSets() { return hasPropertyWithType(TypeCategory.SET); } public boolean hasMaps() { return hasPropertyWithType(TypeCategory.MAP); } private boolean hasPropertyWithType(TypeCategory category) { for (Property property : properties) { if (property.getType().getCategory() == category) { return true; } } return false; } public void include(Supertype supertype) { EntityType entityType = supertype.getEntityType(); for (Delegate delegate : entityType.getDelegates()) { addDelegate(delegate); } for (Property property : entityType.getProperties()) { addProperty(property.createCopy(this)); } } private Property validateField(Property field) { if (field.getName().equals(modifiedSimpleName) || field.getEscapedName().equals(modifiedSimpleName)) { do { modifiedSimpleName = StringUtils.uncapitalize(getType().getSimpleName()) + (escapeSuffix++); } while (propertyNames.contains(modifiedSimpleName)); } return field; } public Set<String> getPropertyNames() { return propertyNames; } public Set<String> getEscapedPropertyNames() { return escapedPropertyNames; } public Type getInnerType() { return type; } }