Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.atlasmap.xml.core.XmlFieldReader Maven / Gradle / Ivy
package io.atlasmap.xml.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import io.atlasmap.api.AtlasConversionException;
import io.atlasmap.api.AtlasException;
import io.atlasmap.core.AtlasPath;
import io.atlasmap.core.AtlasPath.SegmentContext;
import io.atlasmap.core.AtlasUtil;
import io.atlasmap.spi.AtlasConversionService;
import io.atlasmap.spi.AtlasFieldReader;
import io.atlasmap.spi.AtlasInternalSession;
import io.atlasmap.v2.AtlasMapping;
import io.atlasmap.v2.AtlasModelFactory;
import io.atlasmap.v2.AuditStatus;
import io.atlasmap.v2.CollectionType;
import io.atlasmap.v2.DataSource;
import io.atlasmap.v2.DataSourceType;
import io.atlasmap.v2.Field;
import io.atlasmap.v2.FieldGroup;
import io.atlasmap.v2.FieldType;
import io.atlasmap.xml.core.XmlPath.XmlSegmentContext;
import io.atlasmap.xml.v2.AtlasXmlModelFactory;
import io.atlasmap.xml.v2.XmlDataSource;
import io.atlasmap.xml.v2.XmlEnumField;
import io.atlasmap.xml.v2.XmlField;
import io.atlasmap.xml.v2.XmlNamespace;
import io.atlasmap.xml.v2.XmlNamespaces;
public class XmlFieldReader extends XmlFieldTransformer implements AtlasFieldReader {
private static final Logger LOG = LoggerFactory.getLogger(XmlFieldReader.class);
private AtlasConversionService conversionService;
private Document document;
public XmlFieldReader (ClassLoader cl, AtlasConversionService conversionService) {
super (cl);
this .conversionService = conversionService;
}
public XmlFieldReader (ClassLoader cl, AtlasConversionService conversionService, Map namespaces) {
super (cl, namespaces);
this .conversionService = conversionService;
}
public Field read (AtlasInternalSession session) throws AtlasException {
Field field = session.head().getSourceField();
if (document == null ) {
AtlasUtil.addAudit(session, field,
String.format("Cannot read field '%s' of document '%s', document is null" ,
field.getPath(), field.getDocId()),
AuditStatus.ERROR, null );
return field;
}
if (field == null ) {
throw new AtlasException(new IllegalArgumentException("Argument 'field' cannot be null" ));
}
if (!(field instanceof XmlField) && !(field instanceof FieldGroup)
&& !(field instanceof XmlEnumField)) {
throw new AtlasException(String.format("Unsupported field type '%s'" , field.getClass()));
}
seedDocumentNamespaces(document);
if (LOG.isDebugEnabled()) {
LOG.debug("Reading source value for field: " + field.getPath());
}
Optional xmlNamespaces = getSourceNamespaces(session, field);
XmlPath path = new XmlPath(field.getPath());
List fields = getFieldsForPath(session, xmlNamespaces, document.getDocumentElement(), field, path, 0 );
if (path.hasCollection() && !path.isIndexedCollection()) {
FieldGroup fieldGroup = AtlasModelFactory.createFieldGroupFrom(field, true );
fieldGroup.getField().addAll(fields);
session.head().setSourceField(fieldGroup);
return fieldGroup;
} else if (fields.size() == 1 ) {
field.setValue(fields.get(0 ).getValue());
return field;
} else {
return field;
}
}
private List getFieldsForPath (AtlasInternalSession session, Optional xmlNamespaces,
Element node, Field field, XmlPath path, int depth) throws AtlasException {
List fields = new ArrayList<>();
List segments = path.getXmlSegments(false );
if (segments.size() < depth) {
throw new AtlasException(String.format("depth '%s' exceeds segment size '%s'" , depth, segments.size()));
}
if (segments.size() == depth) {
if (!(field instanceof XmlEnumField) && field.getFieldType() == FieldType.COMPLEX) {
FieldGroup group = (FieldGroup) field;
populateChildFields(session, xmlNamespaces, node, group, path);
fields.add(group);
} else {
XmlField xmlField = new XmlField();
AtlasXmlModelFactory.copyField(field, xmlField, true );
if (field instanceof XmlEnumField && xmlField.getFieldType() == FieldType.COMPLEX) {
xmlField.setFieldType(FieldType.STRING);
}
copyValue(session, xmlNamespaces, segments.get(depth - 1 ), node, xmlField);
xmlField.setIndex(null );
fields.add(xmlField);
}
return fields;
}
XmlSegmentContext segment = segments.get(depth);
if (LOG.isDebugEnabled()) {
LOG.debug("Now processing segment: " + segment.getName());
}
if (depth == 0 ) {
if (segment.getName().startsWith(XmlIOHelper.getNodeNameWithoutNamespaceAlias(node))) {
Optional rootNamespace = Optional.empty();
if (segment.getNamespace() != null ) {
rootNamespace = getNamespace(xmlNamespaces, segment.getNamespace());
}
if (!rootNamespace.isPresent() || rootNamespace.get().equals(node.getNamespaceURI())) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping root segment: " + segment);
}
if (segments.size() > 1 ) {
depth = 1 ;
segment = segments.get(depth);
}
}
}
}
if (segment.isAttribute() && segments.size() == depth + 1 ) {
List attrFields = getFieldsForPath(session, xmlNamespaces, node, field, path, depth + 1 );
fields.addAll(attrFields);
return fields;
}
String fieldName = segment.getName();
String fieldNamespace = segment.getNamespace();
Optional namespace = getNamespace(xmlNamespaces, fieldNamespace);
List children = XmlIOHelper.getChildrenWithNameStripAlias(fieldName, namespace, node);
if (children == null || children.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping source value set, couldn't find children with name '" + fieldName
+ "', for segment: " + segment);
}
return fields;
}
if (segment.getCollectionType() == CollectionType.NONE) {
List childFields = getFieldsForPath(session, xmlNamespaces, children.get(0 ), field, path, depth + 1 );
fields.addAll(childFields);
return fields;
}
Integer index = segment.getCollectionIndex();
if (index != null ) {
if (index < children.size()) {
List arrayFields = getFieldsForPath(session, xmlNamespaces, children.get(index), field, path,
depth + 1 );
fields.addAll(arrayFields);
} else if (LOG.isDebugEnabled()) {
LOG.debug("Skipping source value set, children list can't fit index " + index + ", children list size: "
+ children.size());
}
} else {
for (int i=0 ; i arrayFields = getFieldsForPath(
session, xmlNamespaces, children.get(i), itemField, new XmlPath(itemField.getPath()), depth + 1 );
fields.addAll(arrayFields);
}
}
return fields;
}
private void populateChildFields (AtlasInternalSession session, Optional xmlNamespaces,
Element node, FieldGroup fieldGroup, AtlasPath path) throws AtlasException {
List newChildren = new ArrayList<>();
for (Field child : fieldGroup.getField()) {
XmlPath childPath = new XmlPath(child.getPath());
String fieldNamespace = childPath.getLastSegment().getNamespace();
Optional namespace = getNamespace(xmlNamespaces, fieldNamespace);
List children = XmlIOHelper.getChildrenWithNameStripAlias(childPath.getLastSegment().getName(), namespace, node);
if (childPath.getLastSegment().getCollectionType() != CollectionType.NONE) {
FieldGroup childGroup = populateCollectionItems(session, xmlNamespaces, children, child);
newChildren.add(childGroup);
} else {
if (child instanceof FieldGroup) {
populateChildFields(session, xmlNamespaces, children.get(0 ), (FieldGroup)child, childPath);
} else {
copyValue(session, xmlNamespaces, childPath.getLastSegment(), children.get(0 ), (XmlField)child);
}
newChildren.add(child);
}
}
fieldGroup.getField().clear();
fieldGroup.getField().addAll(newChildren);
}
private FieldGroup populateCollectionItems (AtlasInternalSession session, Optional xmlNamespaces,
List elements, Field field) throws AtlasException {
FieldGroup group = field instanceof FieldGroup ?
(FieldGroup)field : AtlasModelFactory.createFieldGroupFrom(field, true );
for (int i=0 ; i segments = itemPath.getSegments(true );
itemPath.setCollectionIndex(segments.size() - 1 , i);
if (field instanceof FieldGroup) {
FieldGroup itemGroup = AtlasXmlModelFactory.cloneFieldGroup((FieldGroup)field);
AtlasPath.setCollectionIndexRecursively(itemGroup, segments.size(), i);
populateChildFields(session, xmlNamespaces, elements.get(i), itemGroup, itemPath);
group.getField().add(itemGroup);
} else {
XmlField itemField = (XmlField) AtlasXmlModelFactory.cloneField((XmlField)field, false );
itemField.setPath(itemPath.toString());
copyValue(session, xmlNamespaces, itemPath.getLastSegment(), elements.get(i), itemField);
group.getField().add(itemField);
}
}
return group;
}
private void copyValue (AtlasInternalSession session, Optional xmlNamespaces,
XmlSegmentContext sc, Element node, XmlField xmlField) {
if (xmlField.getFieldType() == null ) {
xmlField.setFieldType(FieldType.STRING);
}
String value;
if (sc.isAttribute()) {
if (sc.getNamespace() != null && !sc.getNamespace().isEmpty()) {
if (getNamespace(xmlNamespaces, sc.getNamespace()).isPresent()) {
value = node.getAttributeNS(
getNamespace(xmlNamespaces, sc.getNamespace()).get(), sc.getName());
} else {
String attributeName = sc.getQName();
value = node.getAttribute(attributeName);
}
} else {
value = node.getAttribute(sc.getName());
}
} else {
value = node.getTextContent();
}
if (value == null ) {
return ;
}
if (xmlField.getFieldType() == FieldType.STRING) {
xmlField.setValue(value);
} else {
Object convertedValue;
try {
convertedValue = conversionService.convertType(value, xmlField.getFormat(),
xmlField.getFieldType(), null );
xmlField.setValue(convertedValue);
} catch (AtlasConversionException e) {
AtlasUtil.addAudit(session, xmlField,
String.format("Failed to convert field value '%s' into type '%s'" , value,
xmlField.getFieldType()),
AuditStatus.ERROR, value);
}
}
}
public void setDocument (Document document) throws AtlasException {
this .document = document;
}
private Optional getSourceNamespaces (AtlasInternalSession session, Field field) {
DataSource dataSource = null ;
AtlasMapping mapping = session.getMapping();
if (mapping == null || mapping.getDataSource() == null || field.getDocId() == null ) {
return Optional.empty();
}
List dataSources = mapping.getDataSource();
for (DataSource source : dataSources) {
if (!source.getDataSourceType().equals(DataSourceType.SOURCE)) {
continue ;
}
if (field.getDocId().equals(source.getId())) {
dataSource = source;
break ;
}
}
if (dataSource == null || !XmlDataSource.class.isInstance(dataSource)) {
return Optional.empty();
}
XmlDataSource xmlDataSource = XmlDataSource.class.cast(dataSource);
return xmlDataSource.getXmlNamespaces() != null ? Optional.of(xmlDataSource.getXmlNamespaces()) : Optional.empty();
}
private Optional getNamespace (Optional xmlNamespaces, String namespaceAlias) {
Optional namespace = Optional.empty();
if (xmlNamespaces.isPresent()) {
for (XmlNamespace xmlNamespace : xmlNamespaces.get().getXmlNamespace()) {
if ((xmlNamespace.getAlias() == null && namespaceAlias == null )
|| xmlNamespace.getAlias().equals(namespaceAlias)) {
namespace = Optional.of(xmlNamespace.getUri());
break ;
}
}
}
return namespace;
}
}