<%_ if (position === 'import') { _%>
import <%= packageName %>.domain.*;
import <%= packageName %>.repository.CommonTableFieldRepository;
import java.time.ZonedDateTime;
<%_ } _%>
<%_ if (position === 'extendsImport') { _%>
import <%= packageName %>.domain.*;
import <%= packageName %>.repository.CommonTableFieldRepository;
<%_ } _%>
<%_ if (position === 'importInterface') { _%>
import <%= packageName %>.domain.Owner;
<%_ } _%>
<%_ if (position === 'methodInterface') { _%>

    Owner getExtData(Owner source);

    void saveExtData(Owner source);

    void saveExtDataByModelId(Owner source, <%= databaseTypeSql ? 'Long' : 'String'%> modelId);
<%_ } _%>
<%_ if (position === 'method') { _%>

    <%_ if (databaseTypeSql && ormTool === 'hibernate') { _%>
    @Transactional(readOnly = true)
    <%_ } _%>
   public Owner getExtData(Owner source) {
        Map<String, Object> extData = source.getExtData();
        // 如果支持多模型就不能用getEntityName来获得类型的。要通过ContentModelId来获得。要考虑。如果不影响。save有影响。
        commonExtDataRepository.findByOwnerIdAndOwnerType(source.getId(), source.getOwnerEntityName()).forEach(
            commonExtData -> {
                switch (commonExtData.getCommonFieldType()) {
                    case "CommonBoolean":
                        CommonBoolean commonBoolean = (CommonBoolean) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonBoolean.getValue());
                        break;
                    case "CommonString":
                        CommonString commonString = (CommonString) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonString.getValue());
                        break;
                    case "CommonLong":
                        CommonLong commonLong = (CommonLong) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonLong.getValue());
                        break;
                    case "CommonInteger":
                        CommonInteger commonInteger = (CommonInteger) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonInteger.getValue());
                        break;
                    case "CommonZonedDateTime":
                        CommonZonedDateTime commonZonedDateTime = (CommonZonedDateTime) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonZonedDateTime.getValue());
                        break;
                    case "CommonFloat":
                        CommonFloat commonFloat = (CommonFloat) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonFloat.getValue());
                        break;
                    case "CommonDouble":
                        CommonDouble commonDouble = (CommonDouble) commonExtData.getValue();
                        extData.put(commonExtData.getFieldName(), commonDouble.getValue());
                        break;
                }
            });
        return  source;
    }

    public void saveExtData(Owner source) {
        Map<String, Object> extData = source.getExtData();
        Object contentModel = BeanUtil.getFieldValue(source, "contentModel");
        CommonTable multiModel = null;
        if (contentModel instanceof CommonTable) {
            multiModel = (CommonTable) contentModel;
        }
        // todo 如果支持多模型就不能用getEntityName来获得类型的,这只是原始类型。要通过contentModel来获得。。save有影响。
        CommonTable finalMultiModel = multiModel;
        extData.forEach((key, value) -> {
            CommonTableField field;
            if (finalMultiModel != null) {
                field = commonTableFieldRepository.findOneByCommonTableIdAndEntityFieldName(finalMultiModel.getId(), key);
            } else {
                field = commonTableFieldRepository.findOneByCommonTableEntityNameAndEntityFieldName(source.getOwnerEntityName(), key);
            }
            if (field != null) {
                switch (field.getType()) {
                    case STRING:
                        saveString(source,key,value);
                        break;
                    case ZONED_DATE_TIME:
                        saveZonedDataTime(source,key,value);
                        break;
                    case DOUBLE:
                        saveDouble(source,key,value);
                        break;
                    case LONG:
                        saveLong(source,key,value);
                        break;
                    case FLOAT:
                        saveFloat(source,key,value);
                        break;
                    case INTEGER:
                        saveInteger(source,key,value);
                        break;
                    case BOOLEAN:
                        saveBoolean(source,key,value);
                }
            }
        });
    }

    /**
     * 通过source中包含的modelId来获得相应的commonTable及commonField.
     * @param source 源数据
     * @param modelId 模型Id
     */
    public void saveExtDataByModelId(Owner source, <%= databaseTypeSql ? 'Long' : 'String'%> modelId) {
        Map<String, Object> extData = source.getExtData();
        extData.forEach((key, value) -> {
            CommonTableField field = commonTableFieldRepository.findOneByCommonTableIdAndEntityFieldName(modelId, key);
            if (field != null) {
                switch (field.getType()) {
                    case STRING:
                        saveString(source,key,value);
                        break;
                    case ZONED_DATE_TIME:
                        saveZonedDataTime(source,key,value);
                        break;
                    case DOUBLE:
                        saveDouble(source,key,value);
                        break;
                    case LONG:
                        saveLong(source,key,value);
                        break;
                    case FLOAT:
                        saveFloat(source,key,value);
                        break;
                    case INTEGER:
                        saveInteger(source,key,value);
                        break;
                    case BOOLEAN:
                        saveBoolean(source,key,value);
                }
            }
        });
    }

    private void saveString(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonString commonString = (CommonString) commonExtData.getValue();
            if (commonString == null ) {
                commonString = new CommonString().value((String) value);
                update = true;
            } else if (!commonString.getValue().equals(value)) {
                update = true;
                commonString.setValue((String) value);
            }
            if (update) {
                commonExtData.setValue(commonString);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonString().value((String) value));
            commonExtData.setFieldName(key);
            commonExtData.setOwner(source);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveBoolean(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonBoolean commonBoolean = (CommonBoolean) commonExtData.getValue();
            if (commonBoolean == null ) {
                commonBoolean = new CommonBoolean().value((Boolean) value);
                update = true;
            } else if (!commonBoolean.getValue().equals(value)) {
                update = true;
                commonBoolean.setValue((Boolean) value);
            }
            if (update) {
                commonExtData.setValue(commonBoolean);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonBoolean().value((Boolean) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveZonedDataTime(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonZonedDateTime commonZonedDateTime = (CommonZonedDateTime) commonExtData.getValue();
            if (commonZonedDateTime == null ) {
                commonZonedDateTime = new CommonZonedDateTime().value((ZonedDateTime) value);
                update = true;
            } else if (!commonZonedDateTime.getValue().equals(value)) {
                update = true;
                commonZonedDateTime.setValue((ZonedDateTime) value);
            }
            if (update) {
                commonExtData.setValue(commonZonedDateTime);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonZonedDateTime().value((ZonedDateTime) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveDouble(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonDouble commonDouble = (CommonDouble) commonExtData.getValue();
            if (commonDouble == null ) {
                commonDouble = new CommonDouble().value((Double) value);
                update = true;
            } else if (!commonDouble.getValue().equals(value)) {
                update = true;
                commonDouble.setValue((Double) value);
            }
            if (update) {
                commonExtData.setValue(commonDouble);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonDouble().value((Double) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveLong(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonLong commonLong = (CommonLong) commonExtData.getValue();
            if (commonLong == null ) {
                commonLong = new CommonLong().value((Long) value);
                update = true;
            } else if (!commonLong.getValue().equals(value)) {
                update = true;
                commonLong.setValue((Long) value);
            }
            if (update) {
                commonExtData.setValue(commonLong);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonLong().value((Long) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveFloat(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonFloat commonFloat = (CommonFloat) commonExtData.getValue();
            if (commonFloat == null ) {
                commonFloat = new CommonFloat().value((Float) value);
                update = true;
            } else if (!commonFloat.getValue().equals(value)) {
                update = true;
                commonFloat.setValue((Float) value);
            }
            if (update) {
                commonExtData.setValue(commonFloat);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonFloat().value((Float) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }

    private void saveInteger(Owner source, String key, Object value) {
        CommonExtData commonExtData = commonExtDataRepository.findByOwnerIdAndOwnerTypeAndFieldName(source.getId(),source.getOwnerEntityName(), key).orElse(new CommonExtData());
        if (commonExtData.getId() != null) {
            boolean update = false;
            CommonInteger commonInteger = (CommonInteger) commonExtData.getValue();
            if (commonInteger == null ) {
                commonInteger = new CommonInteger().value((Integer) value);
                update = true;
            } else if (!commonInteger.getValue().equals(value)) {
                update = true;
                commonInteger.setValue((Integer) value);
            }
            if (update) {
                commonExtData.setValue(commonInteger);
                commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'updateById'%>(commonExtData);
            }
        } else {
            commonExtData.setValue(new CommonInteger().value((Integer) value));
            commonExtData.setOwner(source);
            commonExtData.setFieldName(key);
            commonExtDataRepository.<%= ormTool !== 'mybatis' ? 'save' : 'insert'%>(commonExtData);
        }
    }
<%_ } _%>
