METAMODEL-1151: Added DataContextFactories for XML files Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/7b91f36e Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/7b91f36e Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/7b91f36e
Branch: refs/heads/master Commit: 7b91f36e23da09fde0f59bd1810e400f438484fd Parents: 7b1edb9 Author: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Authored: Tue Aug 8 20:45:34 2017 -0700 Committer: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Committed: Tue Aug 8 20:45:34 2017 -0700 ---------------------------------------------------------------------- .../metamodel/xml/XmlDomDataContextFactory.java | 49 +++++++ .../apache/metamodel/xml/XmlSaxDataContext.java | 18 ++- .../metamodel/xml/XmlSaxDataContextFactory.java | 134 +++++++++++++++++++ .../apache/metamodel/xml/XmlSaxTableDef.java | 9 +- ....apache.metamodel.factory.DataContextFactory | 2 + 5 files changed, 206 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/7b91f36e/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContextFactory.java ---------------------------------------------------------------------- diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContextFactory.java b/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContextFactory.java new file mode 100644 index 0000000..d64163e --- /dev/null +++ b/xml/src/main/java/org/apache/metamodel/xml/XmlDomDataContextFactory.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.metamodel.xml; + +import org.apache.metamodel.ConnectionException; +import org.apache.metamodel.DataContext; +import org.apache.metamodel.factory.DataContextFactory; +import org.apache.metamodel.factory.DataContextProperties; +import org.apache.metamodel.factory.ResourceFactoryRegistry; +import org.apache.metamodel.factory.UnsupportedDataContextPropertiesException; +import org.apache.metamodel.util.BooleanComparator; +import org.apache.metamodel.util.Resource; + +public class XmlDomDataContextFactory implements DataContextFactory { + + @Override + public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) { + return "xml".equals(properties.getDataContextType()) && !properties.toMap().containsKey("table-defs"); + } + + @Override + public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) + throws UnsupportedDataContextPropertiesException, ConnectionException { + final Resource resource = resourceFactoryRegistry.createResource(properties.getResourceProperties()); + + boolean autoFlattenTables = true; + if (properties.toMap().get("auto-flatten-tables") != null) { + autoFlattenTables = BooleanComparator.toBoolean(properties.toMap().get("auto-flatten-tables")); + } + + return new XmlDomDataContext(resource, autoFlattenTables); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/7b91f36e/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java ---------------------------------------------------------------------- diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java index 217503c..ac0a699 100644 --- a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java +++ b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContext.java @@ -20,6 +20,8 @@ package org.apache.metamodel.xml; import java.io.File; import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -71,8 +73,8 @@ public class XmlSaxDataContext extends QueryPostprocessDataContext { private final Supplier<InputSource> _inputSourceRef; private final Map<XmlSaxTableDef, Map<String, String>> _valueXpaths; private String _schemaName; - private XmlSaxTableDef[] _tableDefs; - + private Collection<XmlSaxTableDef> _tableDefs; + /** * Constructs an XML DataContext based on SAX parsing. * @@ -80,12 +82,12 @@ public class XmlSaxDataContext extends QueryPostprocessDataContext { * a factory reference for the input source to read the XML from. * The ref will be repeatedly called for each access to the file! * @param tableDefs - * an array of table definitions, which provide instructions as + * a collection of table definitions, which provide instructions as * to the xpaths to apply to the document. * * @see XmlSaxTableDef */ - public XmlSaxDataContext(Supplier<InputSource> inputSourceRef, XmlSaxTableDef... tableDefs) { + public XmlSaxDataContext(Supplier<InputSource> inputSourceRef, Collection<XmlSaxTableDef> tableDefs) { _inputSourceRef = inputSourceRef; _tableDefs = tableDefs; _valueXpaths = new HashMap<XmlSaxTableDef, Map<String, String>>(); @@ -100,8 +102,16 @@ public class XmlSaxDataContext extends QueryPostprocessDataContext { } } } + + public XmlSaxDataContext(Supplier<InputSource> inputSourceRef, XmlSaxTableDef... tableDefs) { + this(inputSourceRef, Arrays.asList(tableDefs)); + } public XmlSaxDataContext(final Resource resource, XmlSaxTableDef... tableDefs) { + this(resource, Arrays.asList(tableDefs)); + } + + public XmlSaxDataContext(final Resource resource, Collection<XmlSaxTableDef> tableDefs) { this(createInputSourceRef(resource), tableDefs); } http://git-wip-us.apache.org/repos/asf/metamodel/blob/7b91f36e/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContextFactory.java ---------------------------------------------------------------------- diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContextFactory.java b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContextFactory.java new file mode 100644 index 0000000..8b2acb5 --- /dev/null +++ b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxDataContextFactory.java @@ -0,0 +1,134 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.metamodel.xml; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.metamodel.ConnectionException; +import org.apache.metamodel.DataContext; +import org.apache.metamodel.factory.DataContextFactory; +import org.apache.metamodel.factory.DataContextProperties; +import org.apache.metamodel.factory.ResourceFactoryRegistry; +import org.apache.metamodel.factory.UnsupportedDataContextPropertiesException; +import org.apache.metamodel.util.Resource; +import org.apache.metamodel.util.SimpleTableDef; + +/** + * A {@link DataContextFactory} for XML files where a "table-defs" or "xml-sax-table-defs" element has been configured + * and represents the tables and their XPaths as defined by {@link XmlSaxDataContext}. + * + * If "table-defs" is specified, it will first be interpreted as a {@link SimpleTableDef} which is then mapped to a + * {@link XmlSaxTableDef}. + * + * Alternatively, if "xml-sax-table-defs" is specified, it may either be a List, like this (JSON representation of lists + * and maps): + * + * <pre> + * [ + * { + * "row-x-path": "/path/to/entity1" + * "value-x-paths": [ + * "/path/to/entity1/var1", + * "/path/to/entity1/var2" + * ] + * }, + * { + * "row-x-path": "/path/to/model2" + * "value-x-paths": [ + * "/path/to/model2/field3", + * "/path/to/model2/field4" + * ] + * } + * ] + * </pre> + * + * Or a key/value map, like this: + * + * <pre> + * { + * "/path/to/entity1": [ + * "/path/to/entity1/var1", + * "/path/to/entity1/var2" + * ], + * "/path/to/model2": [ + * "/path/to/model2/field3", + * "/path/to/model2/field4" + * ] + * } + * </pre> + */ +public class XmlSaxDataContextFactory implements DataContextFactory { + + @Override + public boolean accepts(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) { + final boolean hasTableDefs = + properties.getTableDefs() != null || properties.toMap().containsKey("xml-sax-table-defs"); + return "xml".equals(properties.getDataContextType()) && hasTableDefs; + } + + @Override + public DataContext create(DataContextProperties properties, ResourceFactoryRegistry resourceFactoryRegistry) + throws UnsupportedDataContextPropertiesException, ConnectionException { + + final List<XmlSaxTableDef> tableDefs; + final SimpleTableDef[] simpleTableDefs = properties.getTableDefs(); + if (simpleTableDefs == null) { + tableDefs = createTableDefFromProperties(properties.toMap().get("xml-sax-table-defs")); + } else { + tableDefs = Arrays.stream(simpleTableDefs).map(tableDef -> { + return new XmlSaxTableDef(tableDef.getName(), tableDef.getColumnNames()); + }).collect(Collectors.toList()); + } + + final Resource resource = resourceFactoryRegistry.createResource(properties.getResourceProperties()); + return new XmlSaxDataContext(resource, tableDefs); + } + + @SuppressWarnings("unchecked") + private List<XmlSaxTableDef> createTableDefFromProperties(Object configuredTableDefs) { + final List<XmlSaxTableDef> tableDefs = new ArrayList<>(); + + if (configuredTableDefs instanceof List) { + final List<Map<String, Object>> list = (List<Map<String, Object>>) configuredTableDefs; + list.forEach(tableDef -> { + final String rowXpath = (String) tableDef.get("row-x-path"); + final Collection<String> valueXpaths = (Collection<String>) tableDef.get("value-x-paths"); + tableDefs.add(new XmlSaxTableDef(rowXpath, valueXpaths)); + }); + } else if (configuredTableDefs instanceof Map) { + final Map<String, Collection<String>> map = (Map<String, Collection<String>>) configuredTableDefs; + map.forEach((k, v) -> { + final String rowXpath = k; + final Collection<String> valueXpaths = v; + tableDefs.add(new XmlSaxTableDef(rowXpath, valueXpaths)); + }); + } else { + throw new IllegalArgumentException( + "Unsupported value type for property 'xml-sax-table-defs'. Map or List expected, but got: " + + configuredTableDefs); + } + + return tableDefs; + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/7b91f36e/xml/src/main/java/org/apache/metamodel/xml/XmlSaxTableDef.java ---------------------------------------------------------------------- diff --git a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxTableDef.java b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxTableDef.java index 2a6353f..3ef14c4 100644 --- a/xml/src/main/java/org/apache/metamodel/xml/XmlSaxTableDef.java +++ b/xml/src/main/java/org/apache/metamodel/xml/XmlSaxTableDef.java @@ -20,6 +20,7 @@ package org.apache.metamodel.xml; import java.io.Serializable; import java.util.Arrays; +import java.util.Collection; import org.apache.metamodel.schema.Table; @@ -103,8 +104,12 @@ public final class XmlSaxTableDef implements Serializable { * /companies/company/employee/gender, index(/companies/company)] */ public XmlSaxTableDef(String rowXpath, String[] valueXpaths) { - _rowXpath = rowXpath; - _valueXpaths = valueXpaths; + _rowXpath = rowXpath; + _valueXpaths = valueXpaths; + } + + public XmlSaxTableDef(String rowXpath, Collection<String> valueXpaths) { + this(rowXpath, valueXpaths.toArray(new String[valueXpaths.size()])); } public String getRowXpath() { http://git-wip-us.apache.org/repos/asf/metamodel/blob/7b91f36e/xml/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory ---------------------------------------------------------------------- diff --git a/xml/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory b/xml/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory new file mode 100644 index 0000000..560e023 --- /dev/null +++ b/xml/src/main/resources/META-INF/services/org.apache.metamodel.factory.DataContextFactory @@ -0,0 +1,2 @@ +org.apache.metamodel.xml.XmlSaxDataContextFactory +org.apache.metamodel.xml.XmlDomDataContextFactory \ No newline at end of file