io.atlasmap.core.DefaultAtlasContext Maven / Gradle / Ivy
/**
* Copyright (C) 2017 Red Hat, Inc.
*
* 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 io.atlasmap.core;
import java.lang.management.ManagementFactory;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import javax.management.ObjectName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.atlasmap.api.AtlasConstants;
import io.atlasmap.api.AtlasContext;
import io.atlasmap.api.AtlasContextFactory;
import io.atlasmap.api.AtlasConversionException;
import io.atlasmap.api.AtlasException;
import io.atlasmap.api.AtlasSession;
import io.atlasmap.core.AtlasMappingService.AtlasMappingFormat;
import io.atlasmap.mxbean.AtlasContextMXBean;
import io.atlasmap.spi.AtlasModule;
import io.atlasmap.spi.AtlasModuleInfo;
import io.atlasmap.spi.AtlasModuleInfoRegistry;
import io.atlasmap.spi.AtlasModuleMode;
import io.atlasmap.spi.FieldDirection;
import io.atlasmap.spi.StringDelimiter;
import io.atlasmap.v2.AtlasMapping;
import io.atlasmap.v2.AtlasModelFactory;
import io.atlasmap.v2.AuditStatus;
import io.atlasmap.v2.Audits;
import io.atlasmap.v2.BaseMapping;
import io.atlasmap.v2.Collection;
import io.atlasmap.v2.ConstantField;
import io.atlasmap.v2.DataSource;
import io.atlasmap.v2.DataSourceType;
import io.atlasmap.v2.Field;
import io.atlasmap.v2.FieldType;
import io.atlasmap.v2.LookupTable;
import io.atlasmap.v2.Mapping;
import io.atlasmap.v2.MappingType;
import io.atlasmap.v2.PropertyField;
import io.atlasmap.v2.SimpleField;
import io.atlasmap.v2.Validation;
import io.atlasmap.v2.Validations;
public class DefaultAtlasContext implements AtlasContext, AtlasContextMXBean {
public static final String CONSTANTS_DOCUMENT_ID = "io.atlasmap.core.DefaultAtlasContext.constants.docId";
public static final String PROPERTIES_DOCUMENT_ID = "io.atlasmap.core.DefaultAtlasContext.properties.docId";
private static final Logger LOG = LoggerFactory.getLogger(DefaultAtlasContext.class);
private ObjectName jmxObjectName;
private final UUID uuid;
private DefaultAtlasContextFactory factory;
private AtlasMapping mappingDefinition;
private AtlasMappingFormat atlasMappingFormat;
private URI atlasMappingUri;
private Map sourceModules = new HashMap<>();
private Map targetModules = new HashMap<>();
private Map lookupTables = new HashMap<>();
public DefaultAtlasContext(URI atlasMappingUri) {
this(DefaultAtlasContextFactory.getInstance(), atlasMappingUri, AtlasMappingFormat.XML);
}
public DefaultAtlasContext(DefaultAtlasContextFactory factory, URI atlasMappingUri) {
this(factory, atlasMappingUri, AtlasMappingFormat.XML);
}
public DefaultAtlasContext(DefaultAtlasContextFactory factory, URI atlasMappingUri, AtlasMappingFormat format) {
this.factory = factory;
this.uuid = UUID.randomUUID();
this.atlasMappingUri = atlasMappingUri;
this.atlasMappingFormat = format;
}
public DefaultAtlasContext(DefaultAtlasContextFactory factory, AtlasMapping mapping) {
this.factory = factory;
this.uuid = UUID.randomUUID();
this.mappingDefinition = mapping;
}
/**
* TODO: For dynamic re-load. This needs lock()
*
* @throws AtlasException failed to initialize
*/
protected void init() throws AtlasException {
registerJmx(this);
if (this.atlasMappingUri != null) {
this.mappingDefinition = factory.getMappingService().loadMapping(this.atlasMappingUri, atlasMappingFormat);
}
sourceModules.clear();
ConstantModule constant = new ConstantModule();
constant.setConversionService(factory.getConversionService());
constant.setFieldActionService(factory.getFieldActionService());
sourceModules.put(CONSTANTS_DOCUMENT_ID, constant);
PropertyModule propSource = new PropertyModule(factory.getPropertyStrategy());
propSource.setMode(AtlasModuleMode.SOURCE);
propSource.setConversionService(factory.getConversionService());
propSource.setFieldActionService(factory.getFieldActionService());
sourceModules.put(PROPERTIES_DOCUMENT_ID, propSource);
targetModules.clear();
lookupTables.clear();
if (mappingDefinition.getLookupTables() != null
&& mappingDefinition.getLookupTables().getLookupTable() != null) {
for (LookupTable table : mappingDefinition.getLookupTables().getLookupTable()) {
lookupTables.put(table.getName(), table);
}
}
AtlasModuleInfoRegistry moduleInfoRegistry = factory.getModuleInfoRegistry();
for (DataSource ds : mappingDefinition.getDataSource()) {
AtlasModuleInfo moduleInfo = moduleInfoRegistry.lookupByUri(ds.getUri());
if (moduleInfo == null) {
LOG.error("Cannot find module info for the DataSource uri '{}'", ds.getUri());
continue;
}
if (ds.getDataSourceType() != DataSourceType.SOURCE && ds.getDataSourceType() != DataSourceType.TARGET) {
LOG.error("Unsupported DataSource type '{}'", ds.getDataSourceType());
continue;
}
String docId = ds.getId();
if (docId == null || docId.isEmpty()) {
docId = ds.getDataSourceType() == DataSourceType.SOURCE ? AtlasConstants.DEFAULT_SOURCE_DOCUMENT_ID
: AtlasConstants.DEFAULT_TARGET_DOCUMENT_ID;
}
if (ds.getDataSourceType() == DataSourceType.SOURCE && sourceModules.containsKey(docId)) {
LOG.error("Duplicated {} DataSource ID '{}' was detected, ignoring...", ds.getDataSourceType(),
ds.getId());
continue;
}
if (ds.getDataSourceType() == DataSourceType.TARGET && targetModules.containsKey(docId)) {
LOG.error("Duplicated {} DataSource ID '{}' was detected, ignoring...", ds.getDataSourceType(), docId);
continue;
}
try {
AtlasModule module = moduleInfo.getModuleClass().newInstance();
module.setConversionService(factory.getConversionService());
module.setFieldActionService(factory.getFieldActionService());
module.setUri(ds.getUri());
if (ds.getDataSourceType() == DataSourceType.SOURCE) {
module.setMode(AtlasModuleMode.SOURCE);
getSourceModules().put(docId, module);
} else if (ds.getDataSourceType() == DataSourceType.TARGET) {
module.setMode(AtlasModuleMode.TARGET);
getTargetModules().put(docId, module);
}
module.setDocId(docId);
module.init();
} catch (Throwable t) {
LOG.error("Unable to initialize {} module: {}", ds.getDataSourceType(), moduleInfo.toString());
LOG.error(t.getMessage(), t);
throw new AtlasException(String.format("Unable to initialize %s module: %s", ds.getDataSourceType(),
moduleInfo.toString()), t);
}
}
}
protected void registerJmx(DefaultAtlasContext context) {
try {
setJmxObjectName(new ObjectName(
getDefaultAtlasContextFactory().getJmxObjectName() + ",context=Contexts,uuid=" + uuid.toString()));
ManagementFactory.getPlatformMBeanServer().registerMBean(this, getJmxObjectName());
if (LOG.isDebugEnabled()) {
LOG.debug("Registered AtlasContext {} with JMX", context.getUuid());
}
} catch (Throwable t) {
LOG.warn("Failed to register AtlasContext {} with JMX", context.getUuid());
LOG.warn(t.getMessage(), t);
}
}
/**
* Process single mapping entry in preview mode. Since modules don't participate
* in preview mode, any document format specific function won't be applied.
*
* @param mapping A @link{Mapping} entry to process
*/
@Override
public Audits processPreview(Mapping mapping) {
DefaultAtlasSession session = new DefaultAtlasSession(null);
MappingType mappingType = mapping.getMappingType();
List sourceFields = mapping.getInputField();
List targetFields = mapping.getOutputField();
targetFields.forEach(tf -> tf.setValue(null));
Field sourceField;
Field targetField;
switch (mappingType) {
case MAP:
sourceField = sourceFields.get(0);
targetField = targetFields.get(0);
applyFieldActions(session, sourceField);
if (!convertSourceToTarget(session, sourceField, targetField)) {
break;
}
applyFieldActions(session, targetField);
break;
case COMBINE:
targetField = targetFields.get(0);
sourceFields.forEach(sf -> applyFieldActions(session, sf));
Field combined;
try {
combined = processCombineField(session, mapping, sourceFields, targetField);
} catch (AtlasException e) {
AtlasUtil.addAudit(session, sourceFields.get(0).getDocId(), String.format(
"Failed to combine fields: %s", AtlasUtil.getChainedMessage(e)),
sourceFields.get(0).getPath(), AuditStatus.ERROR, null);
if (LOG.isDebugEnabled()) {
LOG.error("", e);
}
break;
}
if (!convertSourceToTarget(session, combined, targetField)) {
break;
}
applyFieldActions(session, targetField);
break;
case SEPARATE:
sourceField = sourceFields.get(0);
applyFieldActions(session, sourceField);
List separatedFields;
try {
separatedFields = processSeparateField(session, mapping, sourceField);
} catch (AtlasException e) {
AtlasUtil.addAudit(session, sourceField.getDocId(), String.format(
"Failed to separate field: %s", AtlasUtil.getChainedMessage(e)),
sourceField.getPath(), AuditStatus.ERROR, null);
if (LOG.isDebugEnabled()) {
LOG.error("", e);
}
break;
}
if (separatedFields == null) {
break;
}
for (Field f : targetFields) {
targetField = f;
if (targetField.getIndex() == null || targetField.getIndex() < 0) {
AtlasUtil.addAudit(session, targetField.getDocId(), String.format(
"Separate requires zero or positive Index value to be set on targetField targetField.path=%s",
targetField.getPath()), targetField.getPath(), AuditStatus.WARN, null);
continue;
}
if (separatedFields.size() <= targetField.getIndex()) {
String errorMessage = String.format(
"Separate returned fewer segments count=%s when targetField.path=%s requested index=%s",
separatedFields.size(), targetField.getPath(), targetField.getIndex());
AtlasUtil.addAudit(session, targetField.getDocId(), errorMessage, targetField.getPath(),
AuditStatus.WARN, null);
break;
}
if (!convertSourceToTarget(session, separatedFields.get(targetField.getIndex()), targetField)) {
break;
}
applyFieldActions(session, targetField);
}
break;
default:
AtlasUtil.addAudit(session, null, String.format(
"Unsupported mappingType=%s detected", mapping.getMappingType()),
null, AuditStatus.ERROR, null);
}
return session.getAudits();
}
private boolean convertSourceToTarget(DefaultAtlasSession session, Field sourceField, Field targetField) {
Object targetValue = null;
if (sourceField.getFieldType() != null && sourceField.getFieldType().equals(targetField.getFieldType())) {
targetValue = sourceField.getValue();
} else if (sourceField.getValue() != null) {
try {
targetValue = factory.getConversionService().convertType(sourceField.getValue(), sourceField.getFormat(),
targetField.getFieldType(), targetField.getFormat());
} catch (AtlasConversionException e) {
AtlasUtil.addAudit(session, targetField.getDocId(), String.format(
"Failed to convert source value to target type: %s", AtlasUtil.getChainedMessage(e)),
targetField.getPath(), AuditStatus.ERROR, null);
if (LOG.isDebugEnabled()) {
LOG.error("", e);
}
return false;
}
}
targetField.setValue(targetValue);
return true;
}
private boolean applyFieldActions(DefaultAtlasSession session, Field field) {
if (field.getActions() == null) {
return true;
}
try {
factory.getFieldActionService().processActions(field.getActions(), field);
} catch (AtlasException e) {
AtlasUtil.addAudit(session, field.getDocId(), String.format(
"Failed to apply field action: %s", AtlasUtil.getChainedMessage(e)),
field.getPath(), AuditStatus.ERROR, null);
if (LOG.isDebugEnabled()) {
LOG.error("", e);
}
return false;
}
return true;
}
/**
* Process session lifecycle
*
*/
@Override
public void process(AtlasSession userSession) throws AtlasException {
if (!(userSession instanceof DefaultAtlasSession)) {
throw new AtlasException(String.format("Unsupported session class '%s'", userSession.getClass().getName()));
}
if (!this.equals(userSession.getAtlasContext())) {
throw new AtlasException("Cannot execute AtlasSession created by the other AtlasContext");
}
DefaultAtlasSession session = (DefaultAtlasSession) userSession;
if (LOG.isDebugEnabled()) {
LOG.debug("Begin process {}", (session == null ? null : session.toString()));
}
session.head().unset();
session.getAudits().getAudit().clear();
session.getValidations().getValidation().clear();
processValidation(session);
for (Validation v : session.getValidations().getValidation()) {
AtlasUtil.addAudit(session, v);
}
if (session.hasErrors()) {
if (LOG.isDebugEnabled()) {
LOG.error("Aborting due to {} errors in pre-validation", session.errorCount());
}
return;
}
for (AtlasModule module : getSourceModules().values()) {
module.processPreSourceExecution(session);
}
for (AtlasModule module : getTargetModules().values()) {
module.processPreTargetExecution(session);
}
if (session.hasErrors()) {
if (LOG.isDebugEnabled()) {
LOG.error("Aborting due to {} errors in pre-execution", session.errorCount());
}
return;
}
for (BaseMapping baseMapping : session.getMapping().getMappings().getMapping()) {
for (Mapping mapping : extractCollectionMappings(session, baseMapping)) {
session.head().setMapping(mapping).setLookupTable(lookupTables.get(mapping.getLookupTableName()));
if (mapping.getOutputField() == null || mapping.getOutputField().isEmpty()) {
AtlasUtil.addAudit(session, null,
String.format("Mapping does not contain at least one output field: alias=%s desc=%s",
mapping.getAlias(), mapping.getDescription()),
null, AuditStatus.WARN, null);
continue;
}
if (mapping.getInputField() == null || mapping.getInputField().isEmpty()) {
session.head().addAudit(AuditStatus.WARN, null, null, String.format(
"Mapping does not contain at least one source field: alias=%s desc=%s",
mapping.getAlias(), mapping.getDescription()));
} else {
try {
processSourceFieldMappings(session, mapping.getInputField());
}catch (Throwable t) {
Field sourceField = session.head().getSourceField();
String docId = sourceField != null ? sourceField.getDocId() : null;
String path = sourceField != null ? sourceField.getPath() : null;
session.head().addAudit(AuditStatus.ERROR, docId, path, String.format(
"Unexpected exception is thrown while reading source field: %s", t.getMessage()));
if (LOG.isDebugEnabled()) {
LOG.error("", t);
}
}
}
if (!session.head().hasError()) {
try {
processTargetFieldMappings(session, mapping);
} catch (Throwable t) {
Field targetField = session.head().getTargetField();
String docId = targetField != null ? targetField.getDocId() : null;
String path = targetField != null ? targetField.getPath() : null;
session.head().addAudit(AuditStatus.ERROR, docId, path, String.format(
"Unexpected exception is thrown while populating target field: %s", t.getMessage()));
if (LOG.isDebugEnabled()) {
LOG.error("", t);
}
}
}
session.getAudits().getAudit().addAll(session.head().getAudits());
session.head().getAudits().clear();
}
}
for (AtlasModule module : getSourceModules().values()) {
module.processPostValidation(session);
}
for (AtlasModule module : getTargetModules().values()) {
module.processPostValidation(session);
}
for (AtlasModule module : getSourceModules().values()) {
module.processPostSourceExecution(session);
}
for (AtlasModule module : getTargetModules().values()) {
module.processPostTargetExecution(session);
}
if (LOG.isDebugEnabled()) {
LOG.debug("End process {}", session == null ? null : session.toString());
}
}
private List extractCollectionMappings(DefaultAtlasSession session, BaseMapping baseMapping)
throws AtlasException {
if (LOG.isDebugEnabled()) {
LOG.debug("Generating Source Mappings from mapping: {}", baseMapping);
}
if (!baseMapping.getMappingType().equals(MappingType.COLLECTION)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Mapping is not a collection mapping, not cloning: {}", baseMapping);
}
return Arrays.asList((Mapping) baseMapping);
}
List mappings = new LinkedList<>();
for (BaseMapping m : ((Collection) baseMapping).getMappings().getMapping()) {
Mapping mapping = (Mapping) m;
Field sourceField = mapping.getInputField().get(0);
boolean sourceIsCollection = AtlasPath.isCollection(sourceField.getPath());
if (!sourceIsCollection) {
// this is a input non-collection to output collection, ie: contact.firstName ->
// contact[].firstName
// this will be expanded later by generateOutputMappings, for input processing,
// just copy it over
if (LOG.isDebugEnabled()) {
LOG.debug("Internal mapping's source field is not a collection, not cloning: {}", mapping);
}
// this is a output collection such as contact<>.firstName, but input is non
// collection such as contact.firstName
// so just set the output collection field path to be contact<0>.firstName,
// which will cause at least one
// output object to be created for our copied firstName value
for (Field f : mapping.getOutputField()) {
f.setPath(AtlasPath.overwriteCollectionIndex(f.getPath(), 0));
}
mappings.add(mapping);
continue;
}
AtlasModule module = resolveModule(FieldDirection.SOURCE, sourceField);
int sourceCollectionSize = module.getCollectionSize(session, sourceField);
if (LOG.isDebugEnabled()) {
LOG.debug("Internal mapping's source field is a collection. Cloning it for each item ({} clones): {}",
sourceCollectionSize, mapping);
}
for (int i = 0; i < sourceCollectionSize; i++) {
Mapping cloneMapping = (Mapping) AtlasModelFactory.cloneMapping(mapping, false);
for (Field f : mapping.getInputField()) {
Field clonedField = module.cloneField(f);
clonedField.setPath(AtlasPath.overwriteCollectionIndex(clonedField.getPath(), i));
cloneMapping.getInputField().add(clonedField);
}
for (Field f : mapping.getOutputField()) {
AtlasModule targetModule = resolveModule(FieldDirection.TARGET, f);
Field clonedField = targetModule.cloneField(f);
if (AtlasPath.isCollection(clonedField.getPath())) {
clonedField.setPath(AtlasPath.overwriteCollectionIndex(clonedField.getPath(), i));
}
cloneMapping.getOutputField().add(clonedField);
}
mappings.add(cloneMapping);
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Generated {} mappings from mapping: {}", mappings.size(), baseMapping);
}
((Collection) baseMapping).getMappings().getMapping().clear();
((Collection) baseMapping).getMappings().getMapping().addAll(mappings);
return mappings;
}
private AtlasModule resolveModule(FieldDirection direction, Field field) {
if (direction == FieldDirection.SOURCE && field instanceof ConstantField) {
return sourceModules.get(CONSTANTS_DOCUMENT_ID);
}
if (direction == FieldDirection.SOURCE && field instanceof PropertyField) {
return sourceModules.get(PROPERTIES_DOCUMENT_ID);
}
String docId = field.getDocId();
if (docId == null || docId.isEmpty()) {
docId = direction == FieldDirection.SOURCE ? AtlasConstants.DEFAULT_SOURCE_DOCUMENT_ID
: AtlasConstants.DEFAULT_TARGET_DOCUMENT_ID;
}
return direction == FieldDirection.SOURCE ? sourceModules.get(docId) : targetModules.get(docId);
}
private void processSourceFieldMappings(DefaultAtlasSession session, List sourceFields)
throws AtlasException {
for (Field sourceField : sourceFields) {
session.head().setSourceField(sourceField);
AtlasModule module = resolveModule(FieldDirection.SOURCE, sourceField);
if (module == null) {
AtlasUtil.addAudit(session, sourceField.getDocId(),
String.format("Module not found for docId '%s'", sourceField.getDocId()), sourceField.getPath(),
AuditStatus.ERROR, null);
return;
}
if (!module.isSupportedField(sourceField)) {
AtlasUtil.addAudit(session, sourceField.getDocId(),
String.format("Unsupported source field type '%s' for DataSource '%s'",
sourceField.getClass().getName(), module.getUri()),
sourceField.getPath(), AuditStatus.ERROR, null);
return;
}
module.processSourceFieldMapping(session);
}
}
private void processTargetFieldMappings(DefaultAtlasSession session, Mapping mapping) throws AtlasException {
MappingType mappingType = mapping.getMappingType();
List sourceFields = mapping.getInputField();
List targetFields = mapping.getOutputField();
AtlasModule module = null;
Field targetField = null;
switch (mappingType) {
case LOOKUP:
case MAP:
targetField = targetFields.get(0);
module = resolveModule(FieldDirection.TARGET, targetField);
if (!auditTargetFieldType(session, module, targetField)) {
return;
}
session.head().setTargetField(targetField);
module.processTargetFieldMapping(session);
return;
case COMBINE:
targetField = targetFields.get(0);
module = resolveModule(FieldDirection.TARGET, targetField);
if (!auditTargetFieldType(session, module, targetField)) {
return;
}
Field sourceField = processCombineField(session, mapping, sourceFields, targetField);
session.head().setSourceField(sourceField).setTargetField(targetField);
module.processTargetFieldMapping(session);
return;
case SEPARATE:
List separatedFields = processSeparateField(session, mapping, sourceFields.get(0));
if (separatedFields == null) {
return;
}
for (Field f : targetFields) {
targetField = f;
module = resolveModule(FieldDirection.TARGET, targetField);
if (!auditTargetFieldType(session, module, targetField)) {
continue;
}
if (targetField.getIndex() == null || targetField.getIndex() < 0) {
AtlasUtil.addAudit(session, targetField.getDocId(), String.format(
"Separate requires zero or positive Index value to be set on targetField targetField.path=%s",
targetField.getPath()), targetField.getPath(), AuditStatus.WARN, null);
continue;
}
if (separatedFields.size() <= targetField.getIndex()) {
String errorMessage = String.format(
"Separate returned fewer segments count=%s when targetField.path=%s requested index=%s",
separatedFields.size(), targetField.getPath(), targetField.getIndex());
AtlasUtil.addAudit(session, targetField.getDocId(), errorMessage, targetField.getPath(),
AuditStatus.WARN, null);
break;
}
session.head().setSourceField(separatedFields.get(targetField.getIndex())).setTargetField(targetField);
module.processTargetFieldMapping(session);
}
return;
default:
AtlasUtil.addAudit(session, null,
String.format("Unsupported mappingType=%s detected", mapping.getMappingType()), null,
AuditStatus.ERROR, null);
}
}
private boolean auditTargetFieldType(DefaultAtlasSession session, AtlasModule module, Field field) {
if (module == null) {
AtlasUtil.addAudit(session, field.getDocId(), String
.format("Module not found for field type='%s', path='%s'", field.getFieldType(), field.getPath()),
field.getPath(), AuditStatus.ERROR, null);
return false;
}
if (!module.isSupportedField(field)) {
AtlasUtil
.addAudit(session, field.getDocId(),
String.format("Unsupported target field type '%s' for DataSource '%s'",
field.getClass().getName(), module.getUri()),
field.getPath(), AuditStatus.ERROR, null);
return false;
}
return true;
}
private Field processCombineField(DefaultAtlasSession session, Mapping mapping, List sourceFields,
Field targetField) throws AtlasException {
Map combineValues = null;
for (Field sourceField : sourceFields) {
if (sourceField.getIndex() == null || sourceField.getIndex() < 0) {
AtlasUtil.addAudit(session, targetField.getDocId(), String.format(
"Combine requires zero or positive Index value to be set on all sourceFields sourceField.path=%s",
sourceField.getPath()), targetField.getPath(), AuditStatus.WARN, null);
continue;
}
if (combineValues == null) {
// We need to support a sorted map w/ null values
combineValues = new HashMap<>();
}
if ((sourceField.getFieldType() != null) || (sourceField.getValue() != null)) {
String sourceValue;
try {
sourceValue = (String) factory.getConversionService().convertType(sourceField.getValue(),
sourceField.getFormat(), FieldType.STRING, null);
} catch (AtlasConversionException e) {
AtlasUtil.addAudit(session, targetField.getDocId(),
String.format("Suitable converter for sourceField.path=%s hasn't been found",
sourceField.getPath()),
targetField.getPath(), AuditStatus.WARN, null);
sourceValue = sourceField.getValue() != null ? sourceField.getValue().toString() : null;
}
combineValues.put(sourceField.getIndex(), sourceValue);
continue;
}
}
String combinedValue = null;
StringDelimiter delimiter = StringDelimiter.fromName(mapping.getDelimiter());
if (delimiter != null) {
combinedValue = factory.getCombineStrategy().combineValues(combineValues, delimiter);
} else {
combinedValue = factory.getCombineStrategy().combineValues(combineValues);
}
Field answer = AtlasModelFactory.cloneFieldToSimpleField(sourceFields.get(0));
if (combinedValue == null || combinedValue.trim().isEmpty()) {
LOG.debug(String.format("Empty combined string for Combine mapping targetField.path=%s",
targetField.getPath()));
} else {
answer.setValue(combinedValue);
}
return answer;
}
private List processSeparateField(DefaultAtlasSession session, Mapping mapping, Field sourceField)
throws AtlasException {
if (sourceField.getValue() == null) {
AtlasUtil.addAudit(session, sourceField.getDocId(),
String.format("null value can't be separated for sourceField.path=%s",
sourceField.getPath()),
sourceField.getPath(), AuditStatus.WARN, null);
return null;
}
if (!sourceField.getValue().getClass().isAssignableFrom(String.class)) {
Object converted = factory.getConversionService().convertType(
sourceField.getValue(), sourceField.getFormat(), FieldType.STRING, null);
sourceField.setValue(converted);
}
List answer = new ArrayList<>();
String sourceValue;
try {
sourceValue = (String) factory.getConversionService().convertType(sourceField.getValue(),
sourceField.getFormat(), FieldType.STRING, null);
} catch (AtlasConversionException e) {
AtlasUtil.addAudit(session, sourceField.getDocId(), String
.format("Suitable converter for sourceField.path=%s hasn't been found", sourceField.getPath()),
sourceField.getPath(), AuditStatus.WARN, null);
sourceValue = sourceField.getValue().toString();
}
List separatedValues = null;
StringDelimiter delimiter = StringDelimiter.fromName(mapping.getDelimiter());
if (delimiter != null) {
separatedValues = factory.getSeparateStrategy().separateValue(sourceValue, delimiter);
} else {
separatedValues = factory.getSeparateStrategy().separateValue(sourceValue);
}
if (separatedValues == null || separatedValues.isEmpty()) {
LOG.debug(String.format("Empty string for Separate mapping sourceField.path=%s", sourceField.getPath()));
} else {
for (String separatedValue : separatedValues) {
SimpleField simpleField = AtlasModelFactory.cloneFieldToSimpleField(sourceField);
simpleField.setValue(separatedValue);
simpleField.setFieldType(FieldType.STRING);
answer.add(simpleField);
}
}
return answer;
}
@Override
public void processValidation(AtlasSession userSession) throws AtlasException {
if (!(userSession instanceof DefaultAtlasSession)) {
throw new AtlasException(String.format("Unsupported session class '%s'", userSession.getClass().getName()));
}
if (!this.equals(userSession.getAtlasContext())) {
throw new AtlasException("Cannot execute AtlasSession created by the other AtlasContext");
}
DefaultAtlasSession session = (DefaultAtlasSession) userSession;
if (LOG.isDebugEnabled()) {
LOG.debug("Begin processValidation {}", session == null ? null : session.toString());
}
List validations = getContextFactory().getValidationService().validateMapping(session.getMapping());
if (validations != null && !validations.isEmpty()) {
session.getValidations().getValidation().addAll(validations);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Detected {} core validation notices", validations.size());
}
for (AtlasModule module : getSourceModules().values()) {
module.processPreValidation(session);
}
for (AtlasModule module : getTargetModules().values()) {
module.processPreValidation(session);
}
if (LOG.isDebugEnabled()) {
LOG.debug("End processValidation {}", session == null ? null : session.toString());
}
}
protected DefaultAtlasContextFactory getDefaultAtlasContextFactory() {
return this.factory;
}
@Override
public AtlasContextFactory getContextFactory() {
return this.factory;
}
public AtlasMapping getMapping() {
return mappingDefinition;
}
@Override
public AtlasSession createSession() throws AtlasException {
if (mappingDefinition == null && atlasMappingUri != null) {
init();
}
return doCreateSession();
}
public AtlasSession createSession(AtlasMapping mappingDefinition) throws AtlasException {
this.atlasMappingUri = null;
this.mappingDefinition = mappingDefinition;
init();
return doCreateSession();
}
private AtlasSession doCreateSession() {
AtlasSession session = new DefaultAtlasSession(mappingDefinition);
session.setAtlasContext(this);
session.setAudits(new Audits());
session.setValidations(new Validations());
setDefaultSessionProperties(session);
return session;
}
protected void setDefaultSessionProperties(AtlasSession session) {
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
df.setTimeZone(TimeZone.getDefault());
session.getProperties().put("Atlas.CreatedDateTimeTZ", df.format(date));
}
public Map getSourceModules() {
return sourceModules;
}
public void setSourceModules(Map sourceModules) {
this.sourceModules = sourceModules;
}
public Map getTargetModules() {
return targetModules;
}
public void setTargetModules(Map targetModules) {
this.targetModules = targetModules;
}
public Map getLookupTables() {
return lookupTables;
}
public void setLookupTables(Map lookupTables) {
this.lookupTables = lookupTables;
}
protected void setJmxObjectName(ObjectName jmxObjectName) {
this.jmxObjectName = jmxObjectName;
}
public ObjectName getJmxObjectName() {
return this.jmxObjectName;
}
@Override
public String getUuid() {
return (this.uuid != null ? this.uuid.toString() : null);
}
@Override
public String getVersion() {
return this.getClass().getPackage().getImplementationVersion();
}
@Override
public String getMappingName() {
return (mappingDefinition != null ? mappingDefinition.getName() : null);
}
protected void setMappingUri(URI atlasMappingUri) {
this.atlasMappingUri = atlasMappingUri;
}
@Override
public String getMappingUri() {
return (atlasMappingUri != null ? atlasMappingUri.toString() : null);
}
@Override
public String getClassName() {
return this.getClass().getSimpleName();
}
@Override
public String getThreadName() {
return Thread.currentThread().getName();
}
@Override
public String toString() {
return "DefaultAtlasContext [jmxObjectName=" + jmxObjectName + ", uuid=" + uuid + ", factory=" + factory
+ ", mappingName=" + getMappingName() + ", mappingUri=" + getMappingUri() + ", sourceModules="
+ sourceModules + ", targetModules=" + targetModules + "]";
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy