io.atlasmap.xml.core.XmlFieldReader 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.xml.core;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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.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.XmlDataSource;
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.getDocId(),
String.format("Cannot read field '%s' of document '%s', document is null",
field.getPath(), field.getDocId()),
field.getPath(), AuditStatus.ERROR, null);
return field;
}
if (field == null) {
throw new AtlasException(new IllegalArgumentException("Argument 'field' cannot be null"));
}
seedDocumentNamespaces(document);
XmlField xmlField = XmlField.class.cast(field);
if (LOG.isDebugEnabled()) {
LOG.debug("Reading source value for field: " + xmlField.getPath());
}
Optional xmlNamespaces = getSourceNamespaces(session, xmlField);
XmlSegmentContext lastSegment = null;
List parentNodes = Arrays.asList(document.getDocumentElement());
XmlPath path = new XmlPath(xmlField.getPath());
for (XmlSegmentContext sc : path.getXmlSegments(false)) {
lastSegment = sc;
if (LOG.isDebugEnabled()) {
LOG.debug("Now processing segment: " + sc.getName());
}
if (path.getParentSegmentOf(sc) == null || path.getParentSegmentOf(sc).isRoot()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping root segment: " + sc);
}
// processing root node part of path such as the "XOA" part of
// "/XOA/contact<>/firstName", skip.
continue;
}
parentNodes = extractSegment(parentNodes, sc, xmlNamespaces);
}
if (lastSegment != null) {
readValue(session, parentNodes, lastSegment, xmlField);
}
return session.head().getSourceField();
}
private List extractSegment(List parentNodes, XmlSegmentContext sc, Optional xmlNamespaces) throws AtlasException {
List answer = new LinkedList<>();
for (Element parentNode : parentNodes) {
if (LOG.isDebugEnabled()) {
LOG.debug("Parent element is currently: " + xmlHelper.writeDocumentToString(true, parentNode));
}
if (sc.isAttribute()) {
answer.add(parentNode);
continue;
}
String childrenElementName = sc.getName();
String namespaceAlias = sc.getNamespace();
Optional namespace = getNamespace(xmlNamespaces, namespaceAlias);
if (LOG.isDebugEnabled()) {
LOG.debug("Looking for children elements with name: " + childrenElementName);
}
List children = XmlIOHelper.getChildrenWithNameStripAlias(childrenElementName, namespace, parentNode);
if (children == null || children.isEmpty()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping source value set, couldn't find children with name '" + childrenElementName
+ "', for segment: " + sc);
}
continue;
}
if (sc.getCollectionType() != CollectionType.NONE) {
Integer index = sc.getCollectionIndex();
if (index == null) {
// TODO process collection
answer.addAll(children);
continue;
}
if (index >= children.size()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping source value set, children list can't fit index " + index
+ ", children list size: " + children.size());
}
continue;
}
answer.add(children.get(index));
} else {
answer.add(children.get(0));
}
}
return answer;
}
private void readValue(AtlasInternalSession session, List parentNodes, XmlSegmentContext sc, XmlField xmlField) {
if (xmlField.getFieldType() == null) {
xmlField.setFieldType(FieldType.STRING);
}
XmlPath path = new XmlPath(xmlField.getPath());
FieldGroup fieldGroup = null;
if (path.hasCollection() && !path.isIndexedCollection()) {
fieldGroup = AtlasModelFactory.createFieldGroupFrom(xmlField);
session.head().setSourceField(fieldGroup);
}
for (int i=0; i getSourceNamespaces(AtlasInternalSession session, XmlField xmlField) {
DataSource dataSource = null;
AtlasMapping mapping = session.getMapping();
// this is to simplify tests which uses mocks
if (mapping == null || mapping.getDataSource() == null || xmlField.getDocId() == null) {
return Optional.empty();
}
List dataSources = mapping.getDataSource();
for (DataSource source : dataSources) {
if (!source.getDataSourceType().equals(DataSourceType.SOURCE)) {
continue;
}
if (xmlField.getDocId().equals(source.getId())) {
dataSource = source;
break;
}
}
if (dataSource == null || !XmlDataSource.class.isInstance(dataSource)) {
return Optional.empty();
}
XmlDataSource xmlDataSource = XmlDataSource.class.cast(dataSource);
return Optional.of(xmlDataSource.getXmlNamespaces());
}
private Optional getNamespace(Optional xmlNamespaces, String namespaceAlias) {
Optional namespace = Optional.empty();
if (xmlNamespaces.isPresent()) {
for (XmlNamespace xmlNamespace : xmlNamespaces.get().getXmlNamespace()) {
if (xmlNamespace.getAlias().equals(namespaceAlias)) {
namespace = Optional.of(xmlNamespace.getUri());
break;
}
}
}
return namespace;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy