Repository: metamodel-membrane
Updated Branches:
  refs/heads/METAMODEL-1159-composite-query [created] 45ea4d543


METAMODEL-1159: Added a federated datasource type scoped to the tenant

Project: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/metamodel-membrane/commit/4185f5e7
Tree: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/tree/4185f5e7
Diff: http://git-wip-us.apache.org/repos/asf/metamodel-membrane/diff/4185f5e7

Branch: refs/heads/METAMODEL-1159-composite-query
Commit: 4185f5e75d97642433e1826a5f9dbfab5937e4c9
Parents: 7bb21b7
Author: Kasper Sørensen <i.am.kasper.soren...@gmail.com>
Authored: Wed Nov 7 21:53:49 2018 -0800
Committer: Kasper Sørensen <i.am.kasper.soren...@gmail.com>
Committed: Wed Nov 7 21:54:48 2018 -0800

----------------------------------------------------------------------
 .../membrane/app/DataContextSupplier.java       | 48 ----------
 .../federation/FederatedDataContextFactory.java | 92 ++++++++++++++++++++
 .../registry/AbstractDataSourceRegistry.java    | 45 ++++++++++
 .../app/registry/DataContextSupplier.java       | 74 ++++++++++++++++
 .../file/FileBasedDataSourceRegistry.java       | 17 ++--
 .../registry/file/FileBasedTenantContext.java   |  3 +-
 .../memory/InMemoryDataSourceRegistry.java      | 16 ++--
 .../registry/memory/InMemoryTenantContext.java  |  2 +-
 8 files changed, 227 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java 
b/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java
deleted file mode 100644
index 7ce0cc0..0000000
--- 
a/core/src/main/java/org/apache/metamodel/membrane/app/DataContextSupplier.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * 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.membrane.app;
-
-import java.util.function.Supplier;
-
-import org.apache.metamodel.DataContext;
-import org.apache.metamodel.factory.DataContextFactoryRegistryImpl;
-import org.apache.metamodel.factory.DataContextProperties;
-
-public class DataContextSupplier implements Supplier<DataContext> {
-
-    private final String dataSourceName;
-    private final DataContextProperties dataContextProperties;
-
-    public DataContextSupplier(String dataSourceName, DataContextProperties 
dataContextProperties) {
-        this.dataSourceName = dataSourceName;
-        this.dataContextProperties = dataContextProperties;
-    }
-
-    @Override
-    public DataContext get() {
-        final DataContext dataContext = 
DataContextFactoryRegistryImpl.getDefaultInstance().createDataContext(
-                dataContextProperties);
-        return dataContext;
-    }
-
-    @Override
-    public String toString() {
-        return "DataContextSupplier[" + dataSourceName + "]";
-    }
-}

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
new file mode 100644
index 0000000..db70942
--- /dev/null
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/federation/FederatedDataContextFactory.java
@@ -0,0 +1,92 @@
+/**
+ * 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.membrane.app.federation;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.metamodel.CompositeDataContext;
+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.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
+
+public class FederatedDataContextFactory implements DataContextFactory {
+
+    public static final String DATA_CONTEXT_TYPE = "federated";
+    public static final String PROPERTY_DATA_SOURCES = "datasources";
+
+    private final TenantContext tenant;
+
+    public FederatedDataContextFactory(TenantContext tenant) {
+        this.tenant = tenant;
+    }
+
+    @Override
+    public boolean accepts(DataContextProperties properties, 
ResourceFactoryRegistry resourceFactoryRegistry) {
+        return DATA_CONTEXT_TYPE.equals(properties.getDataContextType());
+    }
+
+    @Override
+    public DataContext create(DataContextProperties properties, 
ResourceFactoryRegistry resourceFactoryRegistry)
+            throws UnsupportedDataContextPropertiesException, 
ConnectionException {
+
+        final Object dataSourcesPropertyValue = 
properties.toMap().get(PROPERTY_DATA_SOURCES);
+        final Collection<String> dataSourceNames = 
toDataSourceNames(dataSourcesPropertyValue);
+        final DataSourceRegistry dataSourceRegistry = 
tenant.getDataSourceRegistry();
+        final List<DataContext> dataContexts =
+                
dataSourceNames.stream().map(dataSourceRegistry::openDataContext).collect(Collectors.toList());
+        return new CompositeDataContext(dataContexts);
+    }
+
+    @SuppressWarnings("unchecked")
+    private Collection<String> toDataSourceNames(Object 
dataSourcesPropertyValue) {
+        if (dataSourcesPropertyValue == null) {
+            return Collections.emptyList();
+        }
+        if ("*".equals(dataSourcesPropertyValue)) {
+            return tenant.getDataSourceRegistry().getDataSourceNames();
+        }
+        if (dataSourcesPropertyValue instanceof String) {
+            final String str = (String) dataSourcesPropertyValue;
+            return Collections.singleton(str);
+        }
+        if (dataSourcesPropertyValue instanceof Collection) {
+            return new HashSet<>((Collection<String>)dataSourcesPropertyValue);
+        }
+        if (dataSourcesPropertyValue.getClass().isArray()) {
+            final Set<String> result = new HashSet<>();
+            final Object[] arr = (Object[]) dataSourcesPropertyValue;
+            for (Object item : arr) {
+                result.addAll(toDataSourceNames(item));
+            }
+            return result;
+        }
+        throw new IllegalArgumentException("Bad '" + PROPERTY_DATA_SOURCES + 
"' value: " + dataSourcesPropertyValue);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
new file mode 100644
index 0000000..b83a509
--- /dev/null
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/AbstractDataSourceRegistry.java
@@ -0,0 +1,45 @@
+/**
+ * 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.membrane.app.registry;
+
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.factory.DataContextProperties;
+
+public abstract class AbstractDataSourceRegistry implements DataSourceRegistry 
{
+
+    private final TenantContext tenantContext;
+
+    public AbstractDataSourceRegistry(TenantContext tenantContext) {
+        this.tenantContext = tenantContext;
+    }
+
+    protected DataContextSupplier createDataContextSupplier(String name, 
DataContextProperties properties) {
+        final DataContextSupplier supplier = new 
DataContextSupplier(tenantContext, name, properties);
+        return supplier;
+    }
+
+    @Override
+    public DataContext openDataContext(DataContextProperties properties) {
+        return createDataContextSupplier(null, properties).get();
+    }
+
+    protected TenantContext getTenantContext() {
+        return tenantContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
new file mode 100644
index 0000000..2297dca
--- /dev/null
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/DataContextSupplier.java
@@ -0,0 +1,74 @@
+/**
+ * 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.membrane.app.registry;
+
+import java.util.Collection;
+import java.util.function.Supplier;
+
+import org.apache.metamodel.DataContext;
+import org.apache.metamodel.factory.DataContextFactory;
+import org.apache.metamodel.factory.DataContextFactoryRegistry;
+import org.apache.metamodel.factory.DataContextFactoryRegistryImpl;
+import org.apache.metamodel.factory.DataContextProperties;
+import org.apache.metamodel.factory.ResourceFactoryRegistry;
+import org.apache.metamodel.factory.ResourceFactoryRegistryImpl;
+import 
org.apache.metamodel.membrane.app.federation.FederatedDataContextFactory;
+
+public class DataContextSupplier implements Supplier<DataContext> {
+
+    private final String dataSourceName;
+    private final DataContextProperties dataContextProperties;
+    private final TenantContext tenantContext;
+
+    public DataContextSupplier(TenantContext tenantContext, String 
dataSourceName,
+            DataContextProperties dataContextProperties) {
+        this.tenantContext = tenantContext;
+        this.dataSourceName = dataSourceName;
+        this.dataContextProperties = dataContextProperties;
+    }
+
+    @Override
+    public DataContext get() {
+        final DataContextFactoryRegistry registry = getRegistryForTenant();
+        final DataContext dataContext = 
registry.createDataContext(dataContextProperties);
+        return dataContext;
+    }
+
+    private DataContextFactoryRegistry getRegistryForTenant() {
+        final ResourceFactoryRegistry resourceFactoryRegistry = 
ResourceFactoryRegistryImpl.getDefaultInstance();
+        final DataContextFactoryRegistry registry = new 
DataContextFactoryRegistryImpl(resourceFactoryRegistry);
+
+        // Add default/standard factories. This is pretty cumbersome. New 
constructor/cloning options in MetaModel
+        // should make this easier: 
https://github.com/apache/metamodel/pull/192
+        final DataContextFactoryRegistry defaultRegistry = 
DataContextFactoryRegistryImpl.getDefaultInstance();
+        final Collection<DataContextFactory> defaultFactories = 
defaultRegistry.getFactories();
+        for (DataContextFactory factory : defaultFactories) {
+            registry.addFactory(factory);
+        }
+
+        // add tenant-specific factories
+        registry.addFactory(new FederatedDataContextFactory(tenantContext));
+        return registry;
+    }
+
+    @Override
+    public String toString() {
+        return "DataContextSupplier[" + dataSourceName + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
index 60c77ae..b7a2d31 100644
--- 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedDataSourceRegistry.java
@@ -28,17 +28,18 @@ import java.util.stream.Collectors;
 
 import org.apache.metamodel.DataContext;
 import org.apache.metamodel.factory.DataContextProperties;
-import org.apache.metamodel.membrane.app.DataContextSupplier;
 import org.apache.metamodel.membrane.app.config.JacksonConfig;
 import 
org.apache.metamodel.membrane.app.exceptions.DataSourceAlreadyExistException;
 import org.apache.metamodel.membrane.app.exceptions.NoSuchDataSourceException;
-import org.apache.metamodel.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.AbstractDataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.DataContextSupplier;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
 import 
org.apache.metamodel.membrane.controllers.model.RestDataSourceDefinition;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Strings;
 
-public class FileBasedDataSourceRegistry implements DataSourceRegistry {
+public class FileBasedDataSourceRegistry extends AbstractDataSourceRegistry {
 
     private static final ObjectMapper OBJECT_MAPPER = 
JacksonConfig.getObjectMapper();
     private static final String DATASOURCE_FILE_SUFFIX = ".json";
@@ -46,7 +47,8 @@ public class FileBasedDataSourceRegistry implements 
DataSourceRegistry {
 
     private final File directory;
 
-    public FileBasedDataSourceRegistry(File directory) {
+    public FileBasedDataSourceRegistry(TenantContext tenantContext, File 
directory) {
+        super(tenantContext);
         this.directory = directory;
     }
 
@@ -115,7 +117,7 @@ public class FileBasedDataSourceRegistry implements 
DataSourceRegistry {
         }
 
         final DataContextSupplier supplier =
-                new DataContextSupplier(dataSourceName, 
dataSource.toDataContextProperties());
+                createDataContextSupplier(dataSourceName, 
dataSource.toDataContextProperties());
         return supplier.get();
     }
 
@@ -134,9 +136,4 @@ public class FileBasedDataSourceRegistry implements 
DataSourceRegistry {
             throw new UncheckedIOException(new IOException("Unable to delete 
file: " + file));
         }
     }
-
-    public DataContext openDataContext(DataContextProperties properties) {
-        final DataContextSupplier supplier = new DataContextSupplier(null, 
properties);
-        return supplier.get();
-    }
 }

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
index d830125..7e64d3d 100644
--- 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/file/FileBasedTenantContext.java
@@ -31,7 +31,8 @@ class FileBasedTenantContext implements TenantContext {
 
     public FileBasedTenantContext(File directory) {
         this.directory = directory;
-        this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new 
FileBasedDataSourceRegistry(directory));
+        this.dataContextRegistry =
+                new CachedDataSourceRegistryWrapper(new 
FileBasedDataSourceRegistry(this, directory));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
index a457ec0..bff3a73 100644
--- 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryDataSourceRegistry.java
@@ -26,16 +26,17 @@ import java.util.stream.Collectors;
 
 import org.apache.metamodel.DataContext;
 import org.apache.metamodel.factory.DataContextProperties;
-import org.apache.metamodel.membrane.app.DataContextSupplier;
 import 
org.apache.metamodel.membrane.app.exceptions.DataSourceAlreadyExistException;
 import org.apache.metamodel.membrane.app.exceptions.NoSuchDataSourceException;
-import org.apache.metamodel.membrane.app.registry.DataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.AbstractDataSourceRegistry;
+import org.apache.metamodel.membrane.app.registry.TenantContext;
 
-public class InMemoryDataSourceRegistry implements DataSourceRegistry {
+public class InMemoryDataSourceRegistry extends AbstractDataSourceRegistry {
 
     private final Map<String, Supplier<DataContext>> dataSources;
 
-    public InMemoryDataSourceRegistry() {
+    public InMemoryDataSourceRegistry(final TenantContext tenantContext) {
+        super(tenantContext);
         dataSources = new LinkedHashMap<>();
     }
 
@@ -46,7 +47,7 @@ public class InMemoryDataSourceRegistry implements 
DataSourceRegistry {
             throw new DataSourceAlreadyExistException(name);
         }
 
-        dataSources.put(name, new DataContextSupplier(name, 
dataContextProperties));
+        dataSources.put(name, createDataContextSupplier(name, 
dataContextProperties));
         return name;
     }
 
@@ -71,9 +72,4 @@ public class InMemoryDataSourceRegistry implements 
DataSourceRegistry {
         }
         dataSources.remove(dataSourceName);
     }
-
-    public DataContext openDataContext(DataContextProperties properties) {
-        final DataContextSupplier supplier = new DataContextSupplier(null, 
properties);
-        return supplier.get();
-    }
 }

http://git-wip-us.apache.org/repos/asf/metamodel-membrane/blob/4185f5e7/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
index 08b2fa9..330f3b4 100644
--- 
a/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
+++ 
b/core/src/main/java/org/apache/metamodel/membrane/app/registry/memory/InMemoryTenantContext.java
@@ -29,7 +29,7 @@ public class InMemoryTenantContext implements TenantContext {
 
     public InMemoryTenantContext(String tenantIdentifier) {
         this.tenantIdentifier = tenantIdentifier;
-        this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new 
InMemoryDataSourceRegistry());
+        this.dataContextRegistry = new CachedDataSourceRegistryWrapper(new 
InMemoryDataSourceRegistry(this));
     }
 
     @Override

Reply via email to