-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added custom groovy binding script (#12)
* added custom groovy binding script * created Attribute Binder abstraction; different attribute binder for different cases * moved bindRequest type check into AttributeBindRequest * added description to the custom binding script in the UI
- Loading branch information
1 parent
a393ac1
commit 7fc9b0d
Showing
23 changed files
with
514 additions
and
194 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
modules/core/db/update/hsql/18/180406-2-updateImportAttributeMapper.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
alter table DDCDI_IMPORT_ATTRIBUTE_MAPPER add column CUSTOM_ATTRIBUTE_BIND_SCRIPT longvarchar ; |
48 changes: 48 additions & 0 deletions
48
modules/core/src/de/diedavids/cuba/dataimport/binding/AssociationAttributeBinder.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.chile.core.model.MetaPropertyPath | ||
import com.haulmont.cuba.core.entity.Entity | ||
import de.diedavids.cuba.dataimport.data.SimpleDataLoader | ||
import de.diedavids.cuba.dataimport.service.MultipleAssociationValuesFoundException | ||
import groovy.util.logging.Slf4j | ||
|
||
|
||
@Slf4j | ||
class AssociationAttributeBinder implements AttributeBinder { | ||
|
||
SimpleDataLoader simpleDataLoader | ||
|
||
@Override | ||
void bindAttribute(Entity entity, AttributeBindRequest bindRequest) { | ||
try { | ||
def value = handleAssociationAttribute(bindRequest.importEntityPropertyPath, bindRequest.rawValue, entity) | ||
entity.setValueEx(bindRequest.entityAttributePath, value) | ||
} | ||
catch (MultipleAssociationValuesFoundException e) { | ||
e.dataRow = bindRequest.dataRow | ||
e.propertyPath = bindRequest.importEntityPropertyPath | ||
log.warn("Multiple associations found for data row: [${e.dataRow}] and attribute: ${e.propertyPath} with value ${e.value}. Found associations: ${e.allResults}. Will be ignored.") | ||
} | ||
} | ||
|
||
private void handleAssociationAttribute(MetaPropertyPath path, String rawValue, Entity entity) { | ||
def propertyPathFromAssociation = path.path.drop(1) | ||
def propertyPath = propertyPathFromAssociation.join('.') | ||
def associationJavaType = path.metaProperties[0].javaType | ||
def associationProperty = path.metaProperties[0].name | ||
|
||
def associationValue = loadAssociationValue(associationJavaType, propertyPath, rawValue) | ||
entity.setValueEx(associationProperty, associationValue) | ||
} | ||
|
||
private loadAssociationValue(Class<?> associationJavaType, String propertyPath, String rawValue) { | ||
def allResults = simpleDataLoader.loadAllByProperty(associationJavaType, propertyPath, rawValue) | ||
|
||
if (allResults.size() > 1) { | ||
throw new MultipleAssociationValuesFoundException(value: rawValue, allResults: allResults) | ||
} else { | ||
return allResults.first() | ||
} | ||
} | ||
|
||
} |
61 changes: 61 additions & 0 deletions
61
modules/core/src/de/diedavids/cuba/dataimport/binding/AttributeBindRequest.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.chile.core.model.MetaClass | ||
import com.haulmont.chile.core.model.MetaProperty | ||
import com.haulmont.chile.core.model.MetaPropertyPath | ||
import com.haulmont.cuba.core.global.Metadata | ||
import de.diedavids.cuba.dataimport.dto.DataRow | ||
import de.diedavids.cuba.dataimport.entity.ImportAttributeMapper | ||
import de.diedavids.cuba.dataimport.entity.ImportConfiguration | ||
|
||
class AttributeBindRequest { | ||
|
||
private static final String PATH_SEPARATOR = '.' | ||
|
||
ImportConfiguration importConfiguration | ||
DataRow dataRow | ||
ImportAttributeMapper importAttributeMapper | ||
|
||
Metadata metadata | ||
|
||
|
||
String getRawValue() { | ||
((String) dataRow[importAttributeMapper.fileColumnAlias]).trim() | ||
} | ||
|
||
String getImportEntityClassName() { | ||
importConfiguration.entityClass | ||
} | ||
|
||
String getEntityAttributePath() { | ||
importAttributeMapper.entityAttribute - (importEntityClassName + PATH_SEPARATOR) | ||
} | ||
|
||
MetaClass getImportEntityMetaClass() { | ||
metadata.getClass(importEntityClassName) | ||
} | ||
|
||
MetaPropertyPath getImportEntityPropertyPath() { | ||
importEntityMetaClass.getPropertyPath(entityAttributePath) | ||
} | ||
|
||
MetaProperty getMetaProperty() { | ||
importEntityMetaClass.getPropertyNN(entityAttributePath) | ||
} | ||
|
||
boolean isCustomScriptBindingRequest() { | ||
importAttributeMapper.customAttributeBindScript | ||
} | ||
|
||
boolean isAssociationBindingRequest() { | ||
importEntityPropertyPath.metaProperties.size() > 1 | ||
} | ||
|
||
boolean isDatatypeBindingRequest() { | ||
metaProperty.type == MetaProperty.Type.DATATYPE | ||
} | ||
|
||
boolean isEnumBindingRequest() { | ||
metaProperty.type == MetaProperty.Type.ENUM | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
modules/core/src/de/diedavids/cuba/dataimport/binding/AttributeBinder.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.entity.Entity | ||
|
||
interface AttributeBinder { | ||
|
||
void bindAttribute(Entity entity, AttributeBindRequest bindRequest) | ||
} |
42 changes: 42 additions & 0 deletions
42
modules/core/src/de/diedavids/cuba/dataimport/binding/AttributeBinderFactory.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.global.DataManager | ||
import com.haulmont.cuba.core.global.Scripting | ||
import de.diedavids.cuba.dataimport.data.SimpleDataLoader | ||
import org.springframework.stereotype.Component | ||
|
||
import javax.inject.Inject | ||
|
||
@Component | ||
class AttributeBinderFactory { | ||
|
||
@Inject | ||
SimpleDataLoader simpleDataLoader | ||
|
||
@Inject | ||
Scripting scripting | ||
|
||
@Inject | ||
DataManager dataManager | ||
|
||
AttributeBinder createAttributeBinderFromBindingRequest(AttributeBindRequest bindRequest) { | ||
|
||
if (bindRequest.customScriptBindingRequest) { | ||
return new CustomScriptAttributeBinder( | ||
scripting: scripting, | ||
dataManager: dataManager | ||
) | ||
} else if (bindRequest.isAssociationBindingRequest()) { | ||
return new AssociationAttributeBinder( | ||
simpleDataLoader: simpleDataLoader | ||
) | ||
} else if (bindRequest.isDatatypeBindingRequest()) { | ||
return new DatatypeAttributeBinder() | ||
} else if (bindRequest.isEnumBindingRequest()) { | ||
return new EnumAttributeBinder() | ||
} | ||
|
||
throw new IllegalStateException("No valid Attribute binder for AttributeBindRequest: $bindRequest found") | ||
} | ||
|
||
} |
45 changes: 45 additions & 0 deletions
45
modules/core/src/de/diedavids/cuba/dataimport/binding/CustomScriptAttributeBinder.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.entity.Entity | ||
import com.haulmont.cuba.core.global.DataManager | ||
import com.haulmont.cuba.core.global.Scripting | ||
import groovy.util.logging.Slf4j | ||
|
||
@Slf4j | ||
class CustomScriptAttributeBinder implements AttributeBinder { | ||
|
||
Scripting scripting | ||
|
||
DataManager dataManager | ||
|
||
@Override | ||
void bindAttribute(Entity entity, AttributeBindRequest bindRequest) { | ||
Binding binding = createScriptBinding(bindRequest) | ||
tryToExecuteCustomScriptAndSetValue(bindRequest, binding, entity) | ||
} | ||
|
||
private void tryToExecuteCustomScriptAndSetValue(AttributeBindRequest bindRequest, Binding binding, Entity entity) { | ||
try { | ||
def value = getValue(bindRequest, binding) | ||
entity.setValueEx(bindRequest.entityAttributePath, value) | ||
} | ||
catch (Exception e) { | ||
log.error("Error while executing custom binding script: ${e.getClass()}", e) | ||
} | ||
} | ||
|
||
private Binding createScriptBinding(AttributeBindRequest bindRequest) { | ||
new Binding( | ||
importConfiguration: bindRequest.importConfiguration, | ||
importAttributeMapper: bindRequest.importAttributeMapper, | ||
dataRow: bindRequest.dataRow, | ||
entityAttribute: bindRequest.entityAttributePath, | ||
dataManager: dataManager, | ||
rawValue: bindRequest.rawValue | ||
) | ||
} | ||
|
||
private Object getValue(AttributeBindRequest bindRequest, Binding binding) { | ||
scripting.evaluateGroovy(bindRequest.importAttributeMapper.customAttributeBindScript, binding) | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
modules/core/src/de/diedavids/cuba/dataimport/binding/DatatypeAttributeBinder.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.entity.Entity | ||
import de.diedavids.cuba.dataimport.dto.DataRow | ||
import de.diedavids.cuba.dataimport.entity.ImportConfiguration | ||
import groovy.util.logging.Slf4j | ||
|
||
import java.text.SimpleDateFormat | ||
|
||
@Slf4j | ||
class DatatypeAttributeBinder implements AttributeBinder { | ||
|
||
|
||
@Override | ||
void bindAttribute(Entity entity, AttributeBindRequest bindRequest) { | ||
entity.setValueEx(bindRequest.entityAttributePath, getValue(bindRequest)) | ||
} | ||
|
||
private getValue(AttributeBindRequest bindRequest) { | ||
switch (bindRequest.metaProperty.javaType) { | ||
case Integer: return getIntegerValue(bindRequest.rawValue, bindRequest.dataRow) | ||
case Double: return getDoubleValue(bindRequest.rawValue, bindRequest.dataRow) | ||
case Date: return getDateValue(bindRequest.importConfiguration, bindRequest.rawValue) | ||
case Boolean: return getBooleanValue(bindRequest.importConfiguration, bindRequest.rawValue, bindRequest.dataRow) | ||
case String: return getStringValue(bindRequest.rawValue) | ||
} | ||
} | ||
|
||
private Integer getIntegerValue(String rawValue, DataRow dataRow) { | ||
try { | ||
return Integer.parseInt(rawValue) | ||
} | ||
catch (NumberFormatException e) { | ||
log.warn("Number could not be read: '$rawValue' in [$dataRow]. Will be ignored.") | ||
} | ||
} | ||
|
||
@SuppressWarnings('BooleanMethodReturnsNull') | ||
private Boolean getBooleanValue(ImportConfiguration importConfiguration, String rawValue, DataRow dataRow) { | ||
|
||
def customBooleanTrueValue = importConfiguration.booleanTrueValue | ||
def customBooleanFalseValue = importConfiguration.booleanFalseValue | ||
|
||
if (customBooleanTrueValue || customBooleanFalseValue) { | ||
if (customBooleanTrueValue.equalsIgnoreCase(rawValue)) { | ||
return true | ||
} | ||
|
||
return customBooleanFalseValue.equalsIgnoreCase(rawValue) ? false : null | ||
} | ||
|
||
try { | ||
return Boolean.parseBoolean(rawValue) | ||
} | ||
catch (NumberFormatException e) { | ||
log.warn("Number could not be read: '$rawValue' in [$dataRow]. Will be ignored.") | ||
} | ||
} | ||
|
||
private String getStringValue(String rawValue) { | ||
rawValue | ||
} | ||
|
||
@SuppressWarnings('SimpleDateFormatMissingLocale') | ||
private Date getDateValue(ImportConfiguration importConfiguration, String rawValue) { | ||
SimpleDateFormat formatter = new SimpleDateFormat(importConfiguration.dateFormat) | ||
formatter.parse(rawValue) | ||
} | ||
|
||
private Double getDoubleValue(String rawValue, DataRow dataRow) { | ||
try { | ||
return Double.parseDouble(rawValue) | ||
} | ||
catch (NumberFormatException e) { | ||
log.warn("Number could not be read: '$rawValue' in [$dataRow]. Will be ignored.") | ||
} | ||
} | ||
|
||
} |
52 changes: 52 additions & 0 deletions
52
modules/core/src/de/diedavids/cuba/dataimport/binding/EntityBinderImpl.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.entity.Entity | ||
import com.haulmont.cuba.core.global.Metadata | ||
import de.diedavids.cuba.dataimport.dto.DataRow | ||
import de.diedavids.cuba.dataimport.entity.ImportAttributeMapper | ||
import de.diedavids.cuba.dataimport.entity.ImportConfiguration | ||
import groovy.util.logging.Slf4j | ||
import org.springframework.stereotype.Component | ||
|
||
import javax.inject.Inject | ||
|
||
@Slf4j | ||
@Component(EntityBinder.NAME) | ||
class EntityBinderImpl implements EntityBinder { | ||
|
||
@Inject | ||
Metadata metadata | ||
|
||
@Inject | ||
AttributeBinderFactory attributeBinderFactory | ||
|
||
|
||
@Override | ||
Entity bindAttributes(ImportConfiguration importConfiguration, DataRow dataRow, Entity entity) { | ||
|
||
importConfiguration.importAttributeMappers.each { ImportAttributeMapper importAttributeMapper -> | ||
bindAttribute(importConfiguration, dataRow, entity, importAttributeMapper) | ||
} | ||
|
||
entity | ||
} | ||
|
||
private void bindAttribute(ImportConfiguration importConfiguration, DataRow dataRow, Entity entity, ImportAttributeMapper importAttributeMapper) { | ||
|
||
AttributeBindRequest bindRequest = createAttributeBindRequest(importConfiguration, dataRow, importAttributeMapper) | ||
AttributeBinder binder = attributeBinderFactory.createAttributeBinderFromBindingRequest(bindRequest) | ||
|
||
binder.bindAttribute(entity, bindRequest) | ||
|
||
} | ||
|
||
AttributeBindRequest createAttributeBindRequest(ImportConfiguration importConfiguration, DataRow dataRow, ImportAttributeMapper importAttributeMapper) { | ||
new AttributeBindRequest( | ||
importConfiguration: importConfiguration, | ||
importAttributeMapper: importAttributeMapper, | ||
dataRow: dataRow, | ||
metadata: metadata | ||
) | ||
} | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
modules/core/src/de/diedavids/cuba/dataimport/binding/EnumAttributeBinder.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package de.diedavids.cuba.dataimport.binding | ||
|
||
import com.haulmont.cuba.core.entity.Entity | ||
import groovy.util.logging.Slf4j | ||
|
||
@Slf4j | ||
class EnumAttributeBinder implements AttributeBinder { | ||
|
||
@Override | ||
void bindAttribute(Entity entity, AttributeBindRequest bindRequest) { | ||
entity.setValueEx(bindRequest.entityAttributePath, getValue(bindRequest)) | ||
} | ||
|
||
private getValue(AttributeBindRequest bindRequest) { | ||
bindRequest.metaProperty.javaType.fromId(bindRequest.rawValue) | ||
} | ||
|
||
} |
Oops, something went wrong.