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

org.onetwo.dbm.mapping.AbstractMappedField Maven / Gradle / Ivy

package org.onetwo.dbm.mapping;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.persistence.EnumType;
import javax.persistence.Enumerated;

import org.onetwo.common.reflect.ReflectUtils;
import org.onetwo.common.spring.SpringUtils;
import org.onetwo.common.utils.Assert;
import org.onetwo.common.utils.JFishProperty;
import org.onetwo.common.utils.LangUtils;
import org.onetwo.common.utils.StringUtils;
import org.onetwo.dbm.annotation.DbmFieldConvert;
import org.onetwo.dbm.annotation.DbmFieldListeners;
import org.onetwo.dbm.annotation.DbmGenerated;
import org.onetwo.dbm.annotation.DbmJsonField;
import org.onetwo.dbm.event.spi.DbmEventAction;
import org.onetwo.dbm.id.StrategyType;
import org.onetwo.dbm.jpa.GeneratedValueIAttrs;
import org.onetwo.dbm.mapping.enums.DbmMappingEnumType;
import org.onetwo.dbm.mapping.version.VersionableType;
import org.onetwo.dbm.utils.DbmUtils;
import org.onetwo.dbm.utils.SpringAnnotationFinder;
import org.springframework.beans.ConfigurablePropertyAccessor;


@SuppressWarnings("unchecked")
abstract public class AbstractMappedField implements DbmMappedField{
	
	private final DbmMappedEntry entry;
	
	private String name;
	private String label;
	/***
	 * 是否@Id标识的主键
	 */
	private boolean identify;
//	private PropertyDescriptor property;
	private BaseColumnInfo column;

	private DbmMappedFieldType mappedFieldType = DbmMappedFieldType.FIELD;
	private StrategyType strategyType;
	private final JFishProperty propertyInfo;
	
//	private DataHolder dataHolder = new DataHolder();
	
	private boolean freezing;
	
	private List fieldListeners = Collections.EMPTY_LIST;
	
	private VersionableType versionableType;
	
	/****
	 * 实际映射类型
	 */
	private Class actualMappingColumnType;
	final private DbmJsonField jsonFieldAnnotation;
//	final private DbmFieldConvert dbmFieldAnnotation;
	
	private DbmEnumType enumType;
	
	private DbmFieldValueConverter fieldValueConverter;
	final private boolean mappingGenerated;
	
	private Collection bindedFields;
	/***
	 * 绑定到了哪个字段
	 */
	private DbmMappedField bindToField;
	
	public AbstractMappedField(DbmMappedEntry entry, JFishProperty propertyInfo) {
		super();
		this.entry = entry;
		this.propertyInfo = propertyInfo;
		this.name = propertyInfo.getName();
		
		this.mappingGenerated = propertyInfo.hasAnnotation(DbmGenerated.class);
		
		this.propertyInfo.getAnnotationInfo().setAnnotationFinder(SpringAnnotationFinder.INSTANCE);
		
		if(propertyInfo.hasAnnotation(Enumerated.class)){
			Enumerated enumerated = propertyInfo.getAnnotation(Enumerated.class);
			if (enumerated.value()==EnumType.STRING) {
				this.enumType = DbmEnumType.STRING;
			} else {
				this.enumType = DbmEnumType.ORDINAL;
			}
		} else if (Enum.class.isAssignableFrom(propertyInfo.getType())){
			this.enumType = DbmEnumType.STRING;
		}
		// 如果配置了ORDINAL,并且实现了DbmEnumValueMapping接口,则修改为DbmMappingEnumType
		if(DbmEnumValueMapping.class.isAssignableFrom(this.propertyInfo.getType())) {
			Class actualEnumValueType = ReflectUtils.resolveClassOfGenericType(DbmEnumValueMapping.class, this.propertyInfo.getType());
			this.enumType = new DbmMappingEnumType(actualEnumValueType);
		}
		
		DbmFieldListeners listenersAnntation = propertyInfo.getAnnotation(DbmFieldListeners.class);
		if(listenersAnntation!=null){
			fieldListeners = DbmUtils.initDbmEntityFieldListeners(listenersAnntation);
		}else{
			if(!entry.getFieldListeners().isEmpty()){
				this.fieldListeners = new ArrayList(entry.getFieldListeners());
			}
		}
		this.jsonFieldAnnotation = propertyInfo.getAnnotation(DbmJsonField.class);
		

//		CompositedFieldValueConverter compositedConverter = CompositedFieldValueConverter.composited();
//		if(enumType!=null){
//			compositedConverter.addFieldValueConverter(CompositedFieldValueConverter.ENUM_CONVERTER);
//		}
		/*if (getName().equals("appCode") && getEntry().getEntityName().equals("org.onetwo.common.dbm.model.hib.entity.UserEntity")) {
			System.out.println("test");
		}*/
//		this.dbmFieldAnnotation = propertyInfo.getAnnotation(DbmField.class);
		/*if(jsonFieldAnnotation != null){
			compositedConverter.addFieldValueConverter(JsonFieldValueConverter.getInstance());
		}*/
//		if(this.dbmFieldAnnotation!=null){
//			Class converterClass = this.dbmFieldAnnotation.converterClass();
//			DbmFieldValueConverter converter = DbmUtils.createDbmBean(converterClass);
//			compositedConverter.addFieldValueConverter(converter);
//			/*this.dbmFieldAnnotation.forEach(f -> {
//				Class converterClass = f.converterClass();
//				DbmFieldValueConverter converter = DbmUtils.createDbmBean(converterClass);
//				compositedConverter.addFieldValueConverter(converter);
//			});*/
//		}
		this.fieldValueConverter = this.scanDbmFieldConverters(propertyInfo);
		
		
		this.obtainActaulMappingType();
	}
	
	private CompositedFieldValueConverter scanDbmFieldConverters(JFishProperty propertyInfo) {
		CompositedFieldValueConverter compositedConverter = CompositedFieldValueConverter.composited();
		if(enumType!=null){
			compositedConverter.addFieldValueConverter(CompositedFieldValueConverter.ENUM_CONVERTER);
		}
		
		Set fieldAnnos = propertyInfo.getMergedRepeatableAnnotations(DbmFieldConvert.class);
		fieldAnnos.forEach(f -> {
			Class converterClass = f.converterClass();
			DbmFieldValueConverter converter = DbmUtils.createDbmBean(converterClass);
			compositedConverter.addFieldValueConverter(converter);
		});
		compositedConverter.sort();
		return compositedConverter;
	}
	
	private void obtainActaulMappingType(){
		Class actualType = propertyInfo.getType();
		if(enumType!=null){
			actualType = this.enumType.getJavaType();
		}else if(this.jsonFieldAnnotation !=null ){
//			actualType = String.class;
			actualType = this.jsonFieldAnnotation.convertibleJavaType().getJavaType();
		}
		this.actualMappingColumnType = actualType;
	}

	public boolean isMappingGenerated() {
		return mappingGenerated;
	}

	public DbmFieldValueConverter getFieldValueConverter() {
		return fieldValueConverter;
	}

	public boolean isEnumerated(){
		return enumType!=null;
	}
	
	public boolean isEnumeratedOrdinal() {
		return enumType==DbmEnumType.ORDINAL;
	}
	
	/****
	 * 和 {@link #getValue(Object)}对应
	 * 把value(一般从数据库获取)设置为实体的实际值(经过转换器转换的值,如转为java枚举量)
	 * @see 和 {@link #getValue(Object)}对应
	 */
	@Override
	public void setValue(Object entity, Object value){
		value = DbmUtils.convertFromSqlParameterValue(this, value);
//		Object actaulValue = this.fieldValueConverter.forJava(this, value);;
		Object actaulValue = this.getActualJavaValue(value);;
		propertyInfo.setValue(entity, actaulValue);
		
		// 同时设置此字段绑定的字段的值
		processBindedFieldOnSetValue(entity, actaulValue);
	}
	
	/***
	 * 设置通过@DbmBindValueToField 注解绑定到此字段的其它字段的值
	 * 
	 * @author weishao zeng
	 * @param entity
	 * @param value
	 */
	protected void processBindedFieldOnSetValue(Object entity, Object value) {
		Collection bindedFields = this.getBindedFields();
		if (LangUtils.isEmpty(bindedFields)) {
			return ;
		}
		for(DbmMappedField field : bindedFields) {
			field.setValue(entity, value);
		}
	}
	
	/***
	 * 
	 * 和 {@link #setValue(Object)}对应
	 * 根据字段的配置信息,获取实体字段的实际值,用于保存到数据库
	 * 
	 * @see {@link #setValue(Object)}
	 */
	@Override
	public Object getValue(Object entity){
		Assert.notNull(entity);
		Object value = null;
		
		// 如果绑定到了某个字段,则从这个字段里获取值
		if (this.bindToField!=null) {
			value = this.bindToField.getValue(entity);
			return value;
		}
		
		// 处理复合主键的情况
//		if (!propertyInfo.getType().equals(entity.getClass())) {
		if (this.getEntry().isCompositePK()) {
			ConfigurablePropertyAccessor accessor = SpringUtils.newPropertyAccessor(entity, !propertyInfo.isBeanProperty());
			value = accessor.getPropertyValue(this.propertyInfo.getName());
		} else {
			value = propertyInfo.getValue(entity);
		}
//		value = this.fieldValueConverter.forStore(this, value);
		value = this.getActualStoreValue(value);
		return value;
	}
	

	@Override
	public Object getActualStoreValue(Object fieldValue) {
//		Assert.notNull(fieldValue);
		Object value = this.fieldValueConverter.forStore(this, fieldValue);
		return value;
	}

	@Override
	public Object getActualJavaValue(Object fieldValue) {
//		Assert.notNull(fieldValue);
		Object value = this.fieldValueConverter.forJava(this, fieldValue);
		return value;
	}
	
	public Object fireDbmEntityFieldEvents(final Object fieldValue, DbmEventAction eventAction){
//		boolean doListener = false;
		Object newFieldValue = fieldValue;
		if(eventAction.isInserting()){
			if(!fieldListeners.isEmpty()){
				for(DbmEntityFieldListener fl : fieldListeners){
					newFieldValue = fl.beforeFieldInsert(this, newFieldValue);
//					doListener = true;
				}
			}
		} else if(eventAction.isUpdating()){
			if(!fieldListeners.isEmpty()){
				for(DbmEntityFieldListener fl : fieldListeners){
					newFieldValue = fl.beforeFieldUpdate(this, newFieldValue);
//					doListener = true;
				}
			}
		}
		return newFieldValue;
	}
	
	public Class getColumnType(){
		return actualMappingColumnType;
	}
	
	@Override
	public boolean isIdentify() {
		return identify;
	}


	@Override
	public void setIdentify(boolean identify) {
		this.checkFreezing("setIdentify");
		this.identify = identify;
	}

	@Override
	public BaseColumnInfo getColumn() {
		return column;
	}

	@Override
	public void setColumn(BaseColumnInfo column) {
		this.checkFreezing("setColumn");
		this.column = column;
	}

	@Override
	public String getName() {
		return name;
	}

	void setName(String name) {
		this.checkFreezing("setName");
		this.name = name;
	}


	@Override
	public DbmMappedEntry getEntry() {
		return entry;
	}

	@Override
	public String getLabel() {
		if(StringUtils.isBlank(label)){
			return getName();
		}
		return label;
	}

	@Override
	public void setLabel(String label) {
		this.label = label;
	}

	/*@Override
	public boolean isGeneratedValueFetchBeforeInsert() {
		return isSeqStrategy() || getGeneratedValueIAttrs().getGenerationType()==GenerationType.TABLE;
	}*/

	@Override
	public boolean isGeneratedValue() {
		GeneratedValueIAttrs attrs = getGeneratedValueIAttrs();
		return attrs!=null && !isIdentityStrategy();
	}

	@Override
	public boolean isSeqStrategy() {
		return this.strategyType==StrategyType.SEQ;
	}

	/***
	 * 是否id自增策略
	 */
	@Override
	public boolean isIdentityStrategy() {
		return this.strategyType==StrategyType.IDENTITY;
	}

	@Override
	public StrategyType getStrategyType() {
		return strategyType;
	}

	@Override
	public void setStrategyType(StrategyType strategyType) {
		this.strategyType = strategyType;
	}

	@Override
	public JFishProperty getPropertyInfo() {
		return propertyInfo;
	}

	@Override
	public void freezing() {
		freezing = true;
	}

	@Override
	public void checkFreezing(String name) {
		if(isFreezing()){
			throw new UnsupportedOperationException("the field["+getName()+"] is freezing now, don not supported this operation : " + name);
		}
	}

	@Override
	public boolean isFreezing() {
		return freezing;
	}

	@Override
	public DbmMappedFieldType getMappedFieldType() {
		return mappedFieldType;
	}

	@Override
	public final void setMappedFieldType(DbmMappedFieldType mappedFieldType) {
		this.mappedFieldType = mappedFieldType;
	}
	
	@Override
	public boolean isJoinTableField(){
		return false;
	}

	/*@Override
	public DataHolder getDataHolder() {
		return dataHolder;
	}*/
	
	public String toString(){
		return LangUtils.append(getName());
	}

	public List getFieldListeners() {
		return fieldListeners;
	}

	public boolean isVersionControll() {
		return versionableType!=null;
	}

	public VersionableType getVersionableType() {
		return versionableType;
	}

	public void setVersionableType(VersionableType versionableType) {
		this.versionableType = versionableType;
	}
	
	@Override
	public DbmEnumType getEnumType() {
		return enumType;
	}
	
	public DbmJsonField getJsonFieldAnnotation() {
		return jsonFieldAnnotation;
	}

	public Collection getBindedFields() {
		return bindedFields;
	}

	public void setBindedFields(Collection bindedFields) {
		this.bindedFields = bindedFields;
	}

	public DbmMappedField getBindToField() {
		return bindToField;
	}

	public void setBindToField(DbmMappedField bindToField) {
		this.bindToField = bindToField;
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy