METAMODEL-63: Added UnionDataSet
authorKasper Sørensen <i.am.kasper.sorensen@gmail.com>
Thu, 8 Jun 2017 04:12:27 +0000 (21:12 -0700)
committerKasper Sørensen <i.am.kasper.sorensen@gmail.com>
Thu, 8 Jun 2017 04:12:27 +0000 (21:12 -0700)
CHANGES.md
core/src/main/java/org/apache/metamodel/MetaModelHelper.java
core/src/main/java/org/apache/metamodel/data/UnionDataSet.java [new file with mode: 0644]
core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java [new file with mode: 0644]

index 0c5b76c..1da125a 100644 (file)
@@ -1,6 +1,7 @@
 ### Apache MetaModel 5.0
 
  * [METAMODEL-6] - Added update summary containing information about changes on returning UpdateableDataContext.executeUpdate(..)
+ * [METAMODEL-63] - Added UnionDataSet, a general purpose utility for doing client-side unions.
  * [METAMODEL-222] - Added support for Java 8 lambdas, removed support for Java 7.
  * [METAMODEL-1087] - Removed deprecated APIs from MetaModel's codebase.
  * [METAMODEL-1139] - Employed Java 8 functional types (java.util.function) in favor of (now deprecated) Ref, Action, Func. 
index ab38a96..09d47bc 100644 (file)
@@ -19,7 +19,6 @@
 package org.apache.metamodel;
 
 import java.util.ArrayList;
-
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -46,7 +45,6 @@ import org.apache.metamodel.data.SimpleDataSetHeader;
 import org.apache.metamodel.data.SubSelectionDataSet;
 import org.apache.metamodel.query.FilterItem;
 import org.apache.metamodel.query.FromItem;
-import org.apache.metamodel.query.FunctionType;
 import org.apache.metamodel.query.GroupByItem;
 import org.apache.metamodel.query.OrderByItem;
 import org.apache.metamodel.query.Query;
diff --git a/core/src/main/java/org/apache/metamodel/data/UnionDataSet.java b/core/src/main/java/org/apache/metamodel/data/UnionDataSet.java
new file mode 100644 (file)
index 0000000..1391428
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * 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.data;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import org.apache.metamodel.util.ImmutableRef;
+
+/**
+ * A {@link DataSet} that represents the union of two or more other data sets
+ */
+public class UnionDataSet extends AbstractDataSet {
+
+    private final Iterable<Supplier<DataSet>> _dataSetProviders;
+    private Iterator<Supplier<DataSet>> _iterator;
+    private DataSet _currentDataSet;
+
+    public UnionDataSet(DataSetHeader header, Collection<DataSet> dataSets) {
+        this(header, dataSets.stream().map(ds -> ImmutableRef.of(ds)).collect(Collectors.toList()));
+    }
+
+    public UnionDataSet(DataSetHeader header, Iterable<Supplier<DataSet>> dataSetProviders) {
+        super(header);
+        Objects.nonNull(dataSetProviders);
+        _dataSetProviders = dataSetProviders;
+    }
+
+    @Override
+    public boolean next() {
+        if (_iterator == null) {
+            _iterator = _dataSetProviders.iterator();
+        }
+
+        while (_currentDataSet == null || !_currentDataSet.next()) {
+            if (!_iterator.hasNext()) {
+                _currentDataSet = null;
+                return false;
+            }
+            _currentDataSet = _iterator.next().get();
+            assert getHeader().size() == _currentDataSet.getSelectItems().length;
+        }
+        return true;
+    }
+
+    @Override
+    public Row getRow() {
+        if (_currentDataSet == null) {
+            return null;
+        }
+        return _currentDataSet.getRow();
+    }
+
+}
diff --git a/core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java b/core/src/test/java/org/apache/metamodel/data/UnionDataSetTest.java
new file mode 100644 (file)
index 0000000..7ca4bf9
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * 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.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+
+import org.apache.metamodel.schema.Column;
+import org.apache.metamodel.schema.MutableColumn;
+import org.junit.Test;
+
+public class UnionDataSetTest {
+
+    @Test
+    public void testVanillaUnion() {
+        // data set 1
+        final DataSetHeader header1 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo1"), new MutableColumn("bar1") });
+        final Row row1 = new DefaultRow(header1, new Object[] { "1", "2" });
+        final Row row2 = new DefaultRow(header1, new Object[] { "3", "4" });
+        final DataSet ds1 = new InMemoryDataSet(header1, row1, row2);
+
+        // data set 2
+        final DataSetHeader header2 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo2"), new MutableColumn("bar2") });
+        final Row row3 = new DefaultRow(header2, new Object[] { "5", "6" });
+        final DataSet ds2 = new InMemoryDataSet(header2, row3);
+
+        // data set 3
+        final DataSetHeader header3 =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("foo3"), new MutableColumn("bar3") });
+        final Row row4 = new DefaultRow(header2, new Object[] { "7", "8" });
+        final DataSet ds3 = new InMemoryDataSet(header3, row4);
+
+        final DataSetHeader unionHeader =
+                new SimpleDataSetHeader(new Column[] { new MutableColumn("fooUnion"), new MutableColumn("barUnion") });
+        final DataSet unionDataSet = new UnionDataSet(unionHeader, Arrays.asList(ds1, ds2, ds3));
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[1, 2]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[3, 4]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[5, 6]]", unionDataSet.getRow().toString());
+        assertTrue(unionDataSet.next());
+        assertEquals("Row[values=[7, 8]]", unionDataSet.getRow().toString());
+        assertFalse(unionDataSet.next());
+        unionDataSet.close();
+    }
+}