/**
* Copyright 2013-2014 Ralph Schaer <ralphschaer@gmail.com>
*
* 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 ch.rasc.extclassgenerator.association;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
import ch.rasc.extclassgenerator.Model;
import ch.rasc.extclassgenerator.ModelAssociation;
import ch.rasc.extclassgenerator.ModelAssociationType;
import ch.rasc.extclassgenerator.ModelBean;
import ch.rasc.extclassgenerator.ModelGenerator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
/**
* Base class for the association objects
*/
@JsonInclude(Include.NON_NULL)
public abstract class AbstractAssociation {
private final String type;
private final String model;
private String associationKey;
private String foreignKey;
private String primaryKey;
private String instanceName;
/**
* Creates an instance of the AbstractAssociation. Sets {@link #getType()}
* and {@link #getModel()} to the provided parameters.
*
* @param type The type of the association.
* @param model The name of the model that is being associated with.
*/
public AbstractAssociation(String type, String model) {
this.type = type;
this.model = model;
}
public String getAssociationKey() {
return associationKey;
}
/**
* The name of the property in the data to read the association from.
* Defaults to the name of the associated model.
* <p>
* Corresponds to the <a href=
* "http://docs.sencha.com/ext-js/4-2/#!/api/Ext.data.association.Association-cfg-associationKey"
* >associationKey</a> config property.
*
* @param associationKey name of the property in the json data
*/
public void setAssociationKey(String associationKey) {
this.associationKey = associationKey;
}
public String getForeignKey() {
return foreignKey;
}
/**
* The name of the foreign key on the associated model that links it to the
* owner model. Defaults to the lowercase name of the owner model + "_id"
* (HAS_MANY) or to the field name (BELONGS_TO, HAS_ONE) + "_id".
* <p>
* Corresponds to the <a href=
* "http://docs.sencha.com/ext-js/4-2/#!/api/Ext.data.association.HasMany-cfg-foreignKey"
* >foreignKey</a> config property.
*
* @param foreignKey the new name for the foreignKey
*/
public void setForeignKey(String foreignKey) {
this.foreignKey = foreignKey;
}
public String getPrimaryKey() {
return primaryKey;
}
/**
* The name of the primary key on the associated model. <br>
* In general this will be the value of {@link Model#idProperty()}.
* <p>
* Corresponds to the <a href=
* "http://docs.sencha.com/ext-js/4-2/#!/api/Ext.data.association.Association-cfg-primaryKey"
* >primaryKey</a> config property.
*
* @param primaryKey the new name for the primaryKey
*/
public void setPrimaryKey(String primaryKey) {
this.primaryKey = primaryKey;
}
public String getType() {
return type;
}
public String getModel() {
return model;
}
public String getInstanceName() {
return instanceName;
}
public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
}
protected static String getModelName(Class<?> model) {
Model modelAnnotation = model.getAnnotation(Model.class);
if (modelAnnotation != null && StringUtils.hasText(modelAnnotation.value())) {
return modelAnnotation.value();
}
return model.getName();
}
public static AbstractAssociation createAssociation(ModelAssociation associationAnnotation) {
ModelAssociationType type = associationAnnotation.value();
String name = associationAnnotation.propertyName();
if (!StringUtils.hasText(name)) {
return null;
}
Class<?> associationClass = associationAnnotation.model();
if (associationClass == Object.class) {
return null;
}
AbstractAssociation association;
if (type == ModelAssociationType.HAS_MANY) {
association = new HasManyAssociation(associationClass);
} else if (type == ModelAssociationType.BELONGS_TO) {
association = new BelongsToAssociation(associationClass);
} else {
association = new HasOneAssociation(associationClass);
}
association.setAssociationKey(name);
if (StringUtils.hasText(associationAnnotation.foreignKey())) {
association.setForeignKey(associationAnnotation.foreignKey());
}
if (StringUtils.hasText(associationAnnotation.primaryKey())) {
association.setPrimaryKey(associationAnnotation.primaryKey());
} else if (type == ModelAssociationType.BELONGS_TO || type == ModelAssociationType.HAS_ONE) {
Model associationModelAnnotation = associationClass.getAnnotation(Model.class);
if (associationModelAnnotation != null && StringUtils.hasText(associationModelAnnotation.idProperty())
&& !associationModelAnnotation.idProperty().equals("id")) {
association.setPrimaryKey(associationModelAnnotation.idProperty());
}
}
if (type == ModelAssociationType.HAS_MANY) {
HasManyAssociation hasManyAssociation = (HasManyAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(null, name, association.getType(), "setterName"));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(null, name, association.getType(), "getterName"));
}
if (associationAnnotation.autoLoad()) {
hasManyAssociation.setAutoLoad(true);
}
if (StringUtils.hasText(associationAnnotation.name())) {
hasManyAssociation.setName(associationAnnotation.name());
} else {
hasManyAssociation.setName(name);
}
} else if (type == ModelAssociationType.BELONGS_TO) {
BelongsToAssociation belongsToAssociation = (BelongsToAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
belongsToAssociation.setSetterName(associationAnnotation.setterName());
} else {
belongsToAssociation.setSetterName("set" + StringUtils.capitalize(name));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
belongsToAssociation.setGetterName(associationAnnotation.getterName());
} else {
belongsToAssociation.setGetterName("get" + StringUtils.capitalize(name));
}
if (associationAnnotation.autoLoad()) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(null, name, association.getType(), "autoLoad"));
}
if (StringUtils.hasText(associationAnnotation.name())) {
LogFactory.getLog(ModelGenerator.class).warn(getWarningText(null, name, association.getType(), "name"));
}
} else {
HasOneAssociation hasOneAssociation = (HasOneAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
hasOneAssociation.setSetterName(associationAnnotation.setterName());
} else {
hasOneAssociation.setSetterName("set" + StringUtils.capitalize(name));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
hasOneAssociation.setGetterName(associationAnnotation.getterName());
} else {
hasOneAssociation.setGetterName("get" + StringUtils.capitalize(name));
}
if (associationAnnotation.autoLoad()) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(null, name, association.getType(), "autoLoad"));
}
if (StringUtils.hasText(associationAnnotation.name())) {
LogFactory.getLog(ModelGenerator.class).warn(getWarningText(null, name, association.getType(), "name"));
}
}
if (StringUtils.hasText(associationAnnotation.instanceName())) {
association.setInstanceName(associationAnnotation.instanceName());
}
return association;
}
public static AbstractAssociation createAssociation(ModelAssociation associationAnnotation, ModelBean model,
Class<?> typeOfFieldOrReturnValue, Class<?> declaringClass, String name) {
ModelAssociationType type = associationAnnotation.value();
Class<?> associationClass = associationAnnotation.model();
if (associationClass == Object.class) {
associationClass = typeOfFieldOrReturnValue;
}
AbstractAssociation association;
if (type == ModelAssociationType.HAS_MANY) {
association = new HasManyAssociation(associationClass);
} else if (type == ModelAssociationType.BELONGS_TO) {
association = new BelongsToAssociation(associationClass);
} else {
association = new HasOneAssociation(associationClass);
}
association.setAssociationKey(name);
if (StringUtils.hasText(associationAnnotation.foreignKey())) {
association.setForeignKey(associationAnnotation.foreignKey());
} else if (type == ModelAssociationType.HAS_MANY) {
association.setForeignKey(StringUtils.uncapitalize(declaringClass.getSimpleName()) + "_id");
} else if (type == ModelAssociationType.BELONGS_TO || type == ModelAssociationType.HAS_ONE) {
association.setForeignKey(name + "_id");
}
if (StringUtils.hasText(associationAnnotation.primaryKey())) {
association.setPrimaryKey(associationAnnotation.primaryKey());
} else if (type == ModelAssociationType.HAS_MANY && StringUtils.hasText(model.getIdProperty())
&& !model.getIdProperty().equals("id")) {
association.setPrimaryKey(model.getIdProperty());
} else if (type == ModelAssociationType.BELONGS_TO || type == ModelAssociationType.HAS_ONE) {
Model associationModelAnnotation = associationClass.getAnnotation(Model.class);
if (associationModelAnnotation != null && StringUtils.hasText(associationModelAnnotation.idProperty())
&& !associationModelAnnotation.idProperty().equals("id")) {
association.setPrimaryKey(associationModelAnnotation.idProperty());
}
}
if (type == ModelAssociationType.HAS_MANY) {
HasManyAssociation hasManyAssociation = (HasManyAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "setterName"));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "getterName"));
}
if (associationAnnotation.autoLoad()) {
hasManyAssociation.setAutoLoad(true);
}
if (StringUtils.hasText(associationAnnotation.name())) {
hasManyAssociation.setName(associationAnnotation.name());
} else {
hasManyAssociation.setName(name);
}
} else if (type == ModelAssociationType.BELONGS_TO) {
BelongsToAssociation belongsToAssociation = (BelongsToAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
belongsToAssociation.setSetterName(associationAnnotation.setterName());
} else {
belongsToAssociation.setSetterName("set" + StringUtils.capitalize(name));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
belongsToAssociation.setGetterName(associationAnnotation.getterName());
} else {
belongsToAssociation.setGetterName("get" + StringUtils.capitalize(name));
}
if (associationAnnotation.autoLoad()) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "autoLoad"));
}
if (StringUtils.hasText(associationAnnotation.name())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "name"));
}
} else {
HasOneAssociation hasOneAssociation = (HasOneAssociation) association;
if (StringUtils.hasText(associationAnnotation.setterName())) {
hasOneAssociation.setSetterName(associationAnnotation.setterName());
} else {
hasOneAssociation.setSetterName("set" + StringUtils.capitalize(name));
}
if (StringUtils.hasText(associationAnnotation.getterName())) {
hasOneAssociation.setGetterName(associationAnnotation.getterName());
} else {
hasOneAssociation.setGetterName("get" + StringUtils.capitalize(name));
}
if (associationAnnotation.autoLoad()) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "autoLoad"));
}
if (StringUtils.hasText(associationAnnotation.name())) {
LogFactory.getLog(ModelGenerator.class).warn(
getWarningText(declaringClass, name, association.getType(), "name"));
}
}
if (StringUtils.hasText(associationAnnotation.instanceName())) {
association.setInstanceName(associationAnnotation.instanceName());
}
return association;
}
private static String getWarningText(Class<?> declaringClass, String name, String type, String propertyName) {
String warning = "Field ";
if (declaringClass != null) {
warning += declaringClass.getName();
warning += ".";
}
warning += name;
return warning + ": A '" + type + "' association does not support property '" + propertyName
+ "'. Property will be ignored.";
}
}