METAMODEL-183: Fixed Fixes #86
Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/365fae3a Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/365fae3a Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/365fae3a Branch: refs/heads/5.x Commit: 365fae3a336bfd7f32ef4b34a8e3b0d50848bc09 Parents: 8e2df82 Author: Xiaomeng Zhao <[email protected]> Authored: Sat Jan 23 17:38:58 2016 +0100 Committer: Kasper Sørensen <[email protected]> Committed: Sat Jan 23 17:38:58 2016 +0100 ---------------------------------------------------------------------- full/pom.xml | 7 +- .../apache/metamodel/DataContextFactory.java | 13 +- mongodb/common/pom.xml | 67 ++ .../metamodel/mongodb/common/MongoDBUtils.java | 93 +++ .../mongodb/common/MongoDbTableDef.java | 46 ++ mongodb/mongo2/pom.xml | 70 ++ .../mongo2/DefaultWriteConcernAdvisor.java | 32 + .../mongodb/mongo2/MongoDbDataContext.java | 528 +++++++++++++++ .../mongodb/mongo2/MongoDbDataSet.java | 84 +++ .../mongodb/mongo2/MongoDbDeleteBuilder.java | 56 ++ .../mongodb/mongo2/MongoDbDropTableBuilder.java | 43 ++ .../mongodb/mongo2/MongoDbInsertionBuilder.java | 64 ++ .../mongo2/MongoDbTableCreationBuilder.java | 57 ++ .../mongodb/mongo2/MongoDbUpdateCallback.java | 115 ++++ .../mongo2/SimpleWriteConcernAdvisor.java | 50 ++ .../mongodb/mongo2/WriteConcernAdvisor.java | 35 + .../metamodel/mongodb/mongo2/package-info.java | 23 + .../mongodb/mongo2/MongoDbDataContextTest.java | 635 ++++++++++++++++++ .../mongodb/mongo2/MongoDbDataCopyer.java | 124 ++++ .../mongodb/mongo2/MongoDbTestCase.java | 111 ++++ mongodb/mongo3/pom.xml | 70 ++ .../mongo3/DefaultWriteConcernAdvisor.java | 32 + .../mongodb/mongo3/MongoDbDataContext.java | 556 ++++++++++++++++ .../mongodb/mongo3/MongoDbDataSet.java | 84 +++ .../mongodb/mongo3/MongoDbDeleteBuilder.java | 53 ++ .../mongodb/mongo3/MongoDbDropTableBuilder.java | 43 ++ .../mongodb/mongo3/MongoDbInsertionBuilder.java | 63 ++ .../mongo3/MongoDbTableCreationBuilder.java | 57 ++ .../mongodb/mongo3/MongoDbUpdateCallback.java | 119 ++++ .../mongo3/SimpleWriteConcernAdvisor.java | 51 ++ .../mongodb/mongo3/WriteConcernAdvisor.java | 36 ++ .../metamodel/mongodb/mongo3/package-info.java | 23 + .../mongodb/mongo3/MongoDbDataContextTest.java | 613 ++++++++++++++++++ .../mongodb/mongo3/MongoDbDataCopyer.java | 127 ++++ .../mongodb/mongo3/MongoDbTestCase.java | 111 ++++ mongodb/pom.xml | 43 +- .../mongodb/DefaultWriteConcernAdvisor.java | 32 - .../apache/metamodel/mongodb/MongoDBUtils.java | 77 --- .../metamodel/mongodb/MongoDbDataContext.java | 526 --------------- .../metamodel/mongodb/MongoDbDataSet.java | 83 --- .../metamodel/mongodb/MongoDbDeleteBuilder.java | 56 -- .../mongodb/MongoDbDropTableBuilder.java | 43 -- .../mongodb/MongoDbInsertionBuilder.java | 64 -- .../mongodb/MongoDbTableCreationBuilder.java | 57 -- .../metamodel/mongodb/MongoDbTableDef.java | 46 -- .../mongodb/MongoDbUpdateCallback.java | 115 ---- .../mongodb/SimpleWriteConcernAdvisor.java | 50 -- .../metamodel/mongodb/WriteConcernAdvisor.java | 35 - .../apache/metamodel/mongodb/package-info.java | 23 - .../mongodb/MongoDbDataContextTest.java | 636 ------------------- .../metamodel/mongodb/MongoDbDataCopyer.java | 124 ---- .../metamodel/mongodb/MongoDbTestCase.java | 111 ---- .../MongoDbDataContextFactoryBeanDelegate.java | 2 +- 53 files changed, 4292 insertions(+), 2122 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/full/pom.xml ---------------------------------------------------------------------- diff --git a/full/pom.xml b/full/pom.xml index 4738093..3602e45 100644 --- a/full/pom.xml +++ b/full/pom.xml @@ -181,8 +181,13 @@ under the License. <version>${project.version}</version> </dependency> <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-mongodb-mongo3</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.apache.metamodel</groupId> - <artifactId>MetaModel-mongodb</artifactId> + <artifactId>MetaModel-mongodb-mongo2</artifactId> <version>${project.version}</version> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/full/src/main/java/org/apache/metamodel/DataContextFactory.java ---------------------------------------------------------------------- diff --git a/full/src/main/java/org/apache/metamodel/DataContextFactory.java b/full/src/main/java/org/apache/metamodel/DataContextFactory.java index 37776e9..2b3dae2 100644 --- a/full/src/main/java/org/apache/metamodel/DataContextFactory.java +++ b/full/src/main/java/org/apache/metamodel/DataContextFactory.java @@ -39,7 +39,7 @@ import org.apache.metamodel.fixedwidth.FixedWidthConfiguration; import org.apache.metamodel.fixedwidth.FixedWidthDataContext; import org.apache.metamodel.jdbc.JdbcDataContext; import org.apache.metamodel.json.JsonDataContext; -import org.apache.metamodel.mongodb.MongoDbDataContext; +import org.apache.metamodel.mongodb.mongo3.MongoDbDataContext; import org.apache.metamodel.openoffice.OpenOfficeDataContext; import org.apache.metamodel.salesforce.SalesforceDataContext; import org.apache.metamodel.schema.TableType; @@ -53,10 +53,10 @@ import org.xml.sax.InputSource; import com.datastax.driver.core.Cluster; import com.google.common.base.Strings; -import com.mongodb.DB; import com.mongodb.MongoClient; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; +import com.mongodb.client.MongoDatabase; import io.searchbox.client.JestClient; @@ -547,14 +547,15 @@ public class DataContextFactory { } else { serverAddress = new ServerAddress(hostname, port); } - - final DB mongoDb; + MongoClient mongoClient = null; + final MongoDatabase mongoDb; if (Strings.isNullOrEmpty(username)) { - mongoDb = new MongoClient(serverAddress).getDB(databaseName); + mongoClient = new MongoClient(serverAddress); } else { final MongoCredential credential = MongoCredential.createCredential(username, databaseName, password); - mongoDb = new MongoClient(serverAddress, Arrays.asList(credential)).getDB(databaseName); + mongoClient = new MongoClient(serverAddress, Arrays.asList(credential)); } + mongoDb = mongoClient.getDatabase(databaseName); if (tableDefs == null || tableDefs.length == 0) { return new MongoDbDataContext(mongoDb); http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/common/pom.xml ---------------------------------------------------------------------- diff --git a/mongodb/common/pom.xml b/mongodb/common/pom.xml new file mode 100644 index 0000000..2ef9d14 --- /dev/null +++ b/mongodb/common/pom.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>MetaModel-mongodb</artifactId> + <groupId>org.apache.metamodel</groupId> + <version>4.5.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>MetaModel-mongodb-common</artifactId> + <name>MetaModel module for MongoDB commons</name> + + <dependencies> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + + <!-- Test dependencies --> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-jdbc</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.derby</groupId> + <artifactId>derby</artifactId> + <version>10.8.1.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-nop</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDBUtils.java ---------------------------------------------------------------------- diff --git a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDBUtils.java b/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDBUtils.java new file mode 100644 index 0000000..f7a5729 --- /dev/null +++ b/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDBUtils.java @@ -0,0 +1,93 @@ +/** + * 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.mongodb.common; + +import java.util.List; +import java.util.Map; + +import org.apache.metamodel.data.DataSetHeader; +import org.apache.metamodel.data.DefaultRow; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.query.SelectItem; +import org.apache.metamodel.schema.Column; +import org.apache.metamodel.util.CollectionUtils; + +import com.mongodb.DBObject; + +/** + * A utility class for MongoDB module. + */ +public class MongoDBUtils { + + /** + * Converts a MongoDB data object {@link DBObject} into MetaModel + * {@link Row}. + * + * @param dbObject + * a MongoDB object storing data. + * @param header + * a header describing the columns of the data stored. + * @return the MetaModel {@link Row} result object. + */ + public static Row toRow(DBObject dbObject, DataSetHeader header) { + if (dbObject == null) { + return null; + } + + final Map<?,?> map = dbObject.toMap(); + return toRow(map, header); + } + + /** + * Converts a map into MetaModel. This map stores data of a MongoDB document. + * + * @param dbObject + * a map object storing data of a MongoDB document. + * @param header + * a header describing the columns of the data stored. + * @return the MetaModel {@link Row} result object. + */ + public static Row toRow(Map<?,?> map, DataSetHeader header) { + if (map == null) { + return null; + } + + final int size = header.size(); + final Object[] values = new Object[size]; + for (int i = 0; i < values.length; i++) { + final SelectItem selectItem = header.getSelectItem(i); + final String key = selectItem.getColumn().getName(); + final Object value = CollectionUtils.find(map, key); + values[i] = toValue(selectItem.getColumn(), value); + } + return new DefaultRow(header, values); + } + + private static Object toValue(Column column, Object value) { + if (value instanceof List) { + return value; + } + if (value instanceof DBObject) { + DBObject basicDBObject = (DBObject) value; + return basicDBObject.toMap(); + } + return value; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java ---------------------------------------------------------------------- diff --git a/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java b/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java new file mode 100644 index 0000000..9bb6174 --- /dev/null +++ b/mongodb/common/src/main/java/org/apache/metamodel/mongodb/common/MongoDbTableDef.java @@ -0,0 +1,46 @@ +/** + * 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.mongodb.common; + +import java.io.Serializable; + +import org.apache.metamodel.schema.ColumnType; +import org.apache.metamodel.util.SimpleTableDef; + +/** + * Defines a table layout for {@link MongoDbDataContext} tables. This class can + * be used as an instruction set for the {@link MongoDbDataContext} to specify + * which collections, which columns (and their types) should be included in the + * schema structure of a Mongo DB database. + * + * @deprecated use {@link SimpleTableDef} instead. + */ +@Deprecated +public final class MongoDbTableDef extends SimpleTableDef implements Serializable { + + private static final long serialVersionUID = 1L; + + public MongoDbTableDef(String name, String[] columnNames, ColumnType[] columnTypes) { + super(name, columnNames, columnTypes); + } + + public MongoDbTableDef(String name, String[] columnNames) { + super(name, columnNames); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/pom.xml ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/pom.xml b/mongodb/mongo2/pom.xml new file mode 100644 index 0000000..24b1bca --- /dev/null +++ b/mongodb/mongo2/pom.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- +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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>MetaModel-mongodb</artifactId> + <groupId>org.apache.metamodel</groupId> + <version>4.5.1-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>MetaModel-mongodb-mongo2</artifactId> + <name>MetaModel module for MongoDB databases under version 3</name> + <dependencies> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-mongodb-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.mongodb</groupId> + <artifactId>mongo-java-driver</artifactId> + <version>2.14.0</version> + </dependency> + + <!-- Test dependencies --> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-jdbc</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.derby</groupId> + <artifactId>derby</artifactId> + <version>10.8.1.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-nop</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/DefaultWriteConcernAdvisor.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/DefaultWriteConcernAdvisor.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/DefaultWriteConcernAdvisor.java new file mode 100644 index 0000000..4f87a34 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/DefaultWriteConcernAdvisor.java @@ -0,0 +1,32 @@ +/** + * 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.mongodb.mongo2; + +import com.mongodb.WriteConcern; + +/** + * Default {@link WriteConcernAdvisor}. Always returns + * {@link WriteConcern#NORMAL}. + */ +public class DefaultWriteConcernAdvisor extends SimpleWriteConcernAdvisor { + + public DefaultWriteConcernAdvisor() { + super(WriteConcern.NORMAL); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java new file mode 100644 index 0000000..cfeb836 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataContext.java @@ -0,0 +1,528 @@ +/** + * 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.mongodb.mongo2; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.regex.Pattern; + +import org.apache.metamodel.DataContext; +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.QueryPostprocessDataContext; +import org.apache.metamodel.UpdateScript; +import org.apache.metamodel.UpdateableDataContext; +import org.apache.metamodel.data.DataSet; +import org.apache.metamodel.data.DataSetHeader; +import org.apache.metamodel.data.InMemoryDataSet; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.data.SimpleDataSetHeader; +import org.apache.metamodel.mongodb.common.MongoDBUtils; +import org.apache.metamodel.mongodb.common.MongoDbTableDef; +import org.apache.metamodel.query.FilterItem; +import org.apache.metamodel.query.FromItem; +import org.apache.metamodel.query.OperatorType; +import org.apache.metamodel.query.Query; +import org.apache.metamodel.query.SelectItem; +import org.apache.metamodel.schema.Column; +import org.apache.metamodel.schema.ColumnType; +import org.apache.metamodel.schema.ColumnTypeImpl; +import org.apache.metamodel.schema.MutableColumn; +import org.apache.metamodel.schema.MutableSchema; +import org.apache.metamodel.schema.MutableTable; +import org.apache.metamodel.schema.Schema; +import org.apache.metamodel.schema.Table; +import org.apache.metamodel.util.SimpleTableDef; +import org.bson.types.ObjectId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.BasicDBList; +import com.mongodb.BasicDBObject; +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.DBObject; +import com.mongodb.WriteConcern; + +/** + * DataContext implementation for MongoDB. + * + * Since MongoDB has no schema, a virtual schema will be used in this + * DataContext. This implementation supports either automatic discovery of a + * schema or manual specification of a schema, through the + * {@link MongoDbTableDef} class. + */ +public class MongoDbDataContext extends QueryPostprocessDataContext implements UpdateableDataContext { + + private static final Logger logger = LoggerFactory.getLogger(MongoDbDataSet.class); + + private final DB _mongoDb; + private final SimpleTableDef[] _tableDefs; + private WriteConcernAdvisor _writeConcernAdvisor; + private Schema _schema; + + /** + * Constructor available for backwards compatibility + * + * @deprecated use {@link #MongoDbDataContext(DB, SimpleTableDef...)} + * instead + */ + @Deprecated + public MongoDbDataContext(DB mongoDb, MongoDbTableDef... tableDefs) { + this(mongoDb, (SimpleTableDef[]) tableDefs); + } + + /** + * Constructs a {@link MongoDbDataContext}. This constructor accepts a + * custom array of {@link MongoDbTableDef}s which allows the user to define + * his own view on the collections in the database. + * + * @param mongoDb + * the mongo db connection + * @param tableDefs + * an array of {@link MongoDbTableDef}s, which define the table + * and column model of the mongo db collections. (consider using + * {@link #detectSchema(DB)} or {@link #detectTable(DB, String)} + * ). + */ + public MongoDbDataContext(DB mongoDb, SimpleTableDef... tableDefs) { + _mongoDb = mongoDb; + _tableDefs = tableDefs; + _schema = null; + } + + /** + * Constructs a {@link MongoDbDataContext} and automatically detects the + * schema structure/view on all collections (see {@link #detectSchema(DB)}). + * + * @param mongoDb + * the mongo db connection + */ + public MongoDbDataContext(DB mongoDb) { + this(mongoDb, detectSchema(mongoDb)); + } + + /** + * Performs an analysis of the available collections in a Mongo {@link DB} + * instance and tries to detect the table's structure based on the first + * 1000 documents in each collection. + * + * @param db + * the mongo db to inspect + * @return a mutable schema instance, useful for further fine tuning by the + * user. + * @see #detectTable(DB, String) + */ + public static SimpleTableDef[] detectSchema(DB db) { + Set<String> collectionNames = db.getCollectionNames(); + SimpleTableDef[] result = new SimpleTableDef[collectionNames.size()]; + int i = 0; + for (String collectionName : collectionNames) { + SimpleTableDef table = detectTable(db, collectionName); + result[i] = table; + i++; + } + return result; + } + + /** + * Performs an analysis of an available collection in a Mongo {@link DB} + * instance and tries to detect the table structure based on the first 1000 + * documents in the collection. + * + * @param db + * the mongo DB + * @param collectionName + * the name of the collection + * @return a table definition for mongo db. + */ + public static SimpleTableDef detectTable(DB db, String collectionName) { + final DBCollection collection = db.getCollection(collectionName); + final DBCursor cursor = collection.find().limit(1000); + + final SortedMap<String, Set<Class<?>>> columnsAndTypes = new TreeMap<String, Set<Class<?>>>(); + while (cursor.hasNext()) { + DBObject object = cursor.next(); + Set<String> keysInObject = object.keySet(); + for (String key : keysInObject) { + Set<Class<?>> types = columnsAndTypes.get(key); + if (types == null) { + types = new HashSet<Class<?>>(); + columnsAndTypes.put(key, types); + } + Object value = object.get(key); + if (value != null) { + types.add(value.getClass()); + } + } + } + cursor.close(); + + final String[] columnNames = new String[columnsAndTypes.size()]; + final ColumnType[] columnTypes = new ColumnType[columnsAndTypes.size()]; + + int i = 0; + for (Entry<String, Set<Class<?>>> columnAndTypes : columnsAndTypes.entrySet()) { + final String columnName = columnAndTypes.getKey(); + final Set<Class<?>> columnTypeSet = columnAndTypes.getValue(); + final Class<?> columnType; + if (columnTypeSet.size() == 1) { + columnType = columnTypeSet.iterator().next(); + } else { + columnType = Object.class; + } + columnNames[i] = columnName; + if (columnType == ObjectId.class) { + columnTypes[i] = ColumnType.ROWID; + } else { + columnTypes[i] = ColumnTypeImpl.convertColumnType(columnType); + } + i++; + } + + return new SimpleTableDef(collectionName, columnNames, columnTypes); + } + + @Override + protected Schema getMainSchema() throws MetaModelException { + if (_schema == null) { + MutableSchema schema = new MutableSchema(getMainSchemaName()); + for (SimpleTableDef tableDef : _tableDefs) { + + MutableTable table = tableDef.toTable().setSchema(schema); + Column[] rowIdColumns = table.getColumnsOfType(ColumnType.ROWID); + for (Column column : rowIdColumns) { + if (column instanceof MutableColumn) { + ((MutableColumn) column).setPrimaryKey(true); + } + } + + schema.addTable(table); + } + + _schema = schema; + } + return _schema; + } + + @Override + protected String getMainSchemaName() throws MetaModelException { + return _mongoDb.getName(); + } + + @Override + protected Number executeCountQuery(Table table, List<FilterItem> whereItems, boolean functionApproximationAllowed) { + final DBCollection collection = _mongoDb.getCollection(table.getName()); + + final DBObject query = createMongoDbQuery(table, whereItems); + + logger.info("Executing MongoDB 'count' query: {}", query); + final long count = collection.count(query); + + return count; + } + + @Override + protected Row executePrimaryKeyLookupQuery(Table table, List<SelectItem> selectItems, Column primaryKeyColumn, + Object keyValue) { + final DBCollection collection = _mongoDb.getCollection(table.getName()); + + List<FilterItem> whereItems = new ArrayList<FilterItem>(); + SelectItem selectItem = new SelectItem(primaryKeyColumn); + FilterItem primaryKeyWhereItem = new FilterItem(selectItem, OperatorType.EQUALS_TO, keyValue); + whereItems.add(primaryKeyWhereItem); + final DBObject query = createMongoDbQuery(table, whereItems); + final DBObject resultDBObject = collection.findOne(query); + + DataSetHeader header = new SimpleDataSetHeader(selectItems); + + Row row = MongoDBUtils.toRow(resultDBObject, header); + + return row; + } + + @Override + public DataSet executeQuery(Query query) { + // Check for queries containing only simple selects and where clauses, + // or if it is a COUNT(*) query. + + // if from clause only contains a main schema table + List<FromItem> fromItems = query.getFromClause().getItems(); + if (fromItems.size() == 1 && fromItems.get(0).getTable() != null + && fromItems.get(0).getTable().getSchema() == _schema) { + final Table table = fromItems.get(0).getTable(); + + // if GROUP BY, HAVING and ORDER BY clauses are not specified + if (query.getGroupByClause().isEmpty() && query.getHavingClause().isEmpty() + && query.getOrderByClause().isEmpty()) { + + final List<FilterItem> whereItems = query.getWhereClause().getItems(); + + // if all of the select items are "pure" column selection + boolean allSelectItemsAreColumns = true; + List<SelectItem> selectItems = query.getSelectClause().getItems(); + + // if it is a + // "SELECT [columns] FROM [table] WHERE [conditions]" + // query. + for (SelectItem selectItem : selectItems) { + if (selectItem.getFunction() != null || selectItem.getColumn() == null) { + allSelectItemsAreColumns = false; + break; + } + } + + if (allSelectItemsAreColumns) { + logger.debug("Query can be expressed in full MongoDB, no post processing needed."); + + // prepare for a non-post-processed query + Column[] columns = new Column[selectItems.size()]; + for (int i = 0; i < columns.length; i++) { + columns[i] = selectItems.get(i).getColumn(); + } + + // checking if the query is a primary key lookup query + if (whereItems.size() == 1) { + final FilterItem whereItem = whereItems.get(0); + final SelectItem selectItem = whereItem.getSelectItem(); + if (!whereItem.isCompoundFilter() && selectItem != null && selectItem.getColumn() != null) { + final Column column = selectItem.getColumn(); + if (column.isPrimaryKey() && OperatorType.EQUALS_TO.equals(whereItem.getOperator())) { + logger.debug("Query is a primary key lookup query. Trying executePrimaryKeyLookupQuery(...)"); + final Object operand = whereItem.getOperand(); + final Row row = executePrimaryKeyLookupQuery(table, selectItems, column, operand); + if (row == null) { + logger.debug("DataContext did not return any primary key lookup query results. Proceeding " + + "with manual lookup."); + } else { + final DataSetHeader header = new SimpleDataSetHeader(selectItems); + return new InMemoryDataSet(header, row); + } + } + } + } + + int firstRow = (query.getFirstRow() == null ? 1 : query.getFirstRow()); + int maxRows = (query.getMaxRows() == null ? -1 : query.getMaxRows()); + + final DataSet dataSet = materializeMainSchemaTableInternal(table, columns, whereItems, firstRow, + maxRows, false); + return dataSet; + } + } + } + + logger.debug("Query will be simplified for MongoDB and post processed."); + return super.executeQuery(query); + } + + private DataSet materializeMainSchemaTableInternal(Table table, Column[] columns, List<FilterItem> whereItems, + int firstRow, int maxRows, boolean queryPostProcessed) { + final DBCollection collection = _mongoDb.getCollection(table.getName()); + + final DBObject query = createMongoDbQuery(table, whereItems); + + logger.info("Executing MongoDB 'find' query: {}", query); + DBCursor cursor = collection.find(query); + + if (maxRows > 0) { + cursor = cursor.limit(maxRows); + } + if (firstRow > 1) { + final int skip = firstRow - 1; + cursor = cursor.skip(skip); + } + + return new MongoDbDataSet(cursor, columns, queryPostProcessed); + } + + protected BasicDBObject createMongoDbQuery(Table table, List<FilterItem> whereItems) { + assert _schema == table.getSchema(); + + final BasicDBObject query = new BasicDBObject(); + if (whereItems != null && !whereItems.isEmpty()) { + for (FilterItem item : whereItems) { + convertToCursorObject(query, item); + } + } + + return query; + } + + private void convertToCursorObject(BasicDBObject query, FilterItem item) { + if (item.isCompoundFilter()) { + + BasicDBList orList = new BasicDBList(); + + final FilterItem[] childItems = item.getChildItems(); + for (FilterItem childItem : childItems) { + BasicDBObject childObject = new BasicDBObject(); + convertToCursorObject(childObject, childItem); + orList.add(childObject); + } + + query.put("$or", orList); + + } else { + + final Column column = item.getSelectItem().getColumn(); + final String columnName = column.getName(); + final String operatorName = getOperatorName(item); + + Object operand = item.getOperand(); + if (ObjectId.isValid(String.valueOf(operand))) { + operand = new ObjectId(String.valueOf(operand)); + } + + final BasicDBObject existingFilterObject = (BasicDBObject) query.get(columnName); + if (existingFilterObject == null) { + if (operatorName == null) { + if (OperatorType.LIKE.equals(item.getOperator())) { + query.put(columnName, turnOperandIntoRegExp(operand)); + } else { + query.put(columnName, operand); + } + } else { + query.put(columnName, new BasicDBObject(operatorName, operand)); + } + } else { + if (operatorName == null) { + throw new IllegalStateException("Cannot retrieve records for a column with two EQUALS_TO operators"); + } else { + existingFilterObject.append(operatorName, operand); + } + } + } + } + + private String getOperatorName(FilterItem item) { + final OperatorType operator = item.getOperator(); + + if (OperatorType.EQUALS_TO.equals(operator)) { + return null; + } + if (OperatorType.LIKE.equals(operator)) { + return null; + } + if (OperatorType.LESS_THAN.equals(operator)) { + return "$lt"; + } + if (OperatorType.LESS_THAN_OR_EQUAL.equals(operator)) { + return "$lte"; + } + if (OperatorType.GREATER_THAN.equals(operator)) { + return "$gt"; + } + if (OperatorType.GREATER_THAN_OR_EQUAL.equals(operator)) { + return "$gte"; + } + if (OperatorType.DIFFERENT_FROM.equals(operator)) { + return "$ne"; + } + if (OperatorType.IN.equals(operator)) { + return "$in"; + } + + throw new IllegalStateException("Unsupported operator type: " + operator); + } + + private Pattern turnOperandIntoRegExp(Object operand) { + StringBuilder operandAsRegExp = new StringBuilder(replaceWildCardLikeChars(operand.toString())); + operandAsRegExp.insert(0, "^").append("$"); + return Pattern.compile(operandAsRegExp.toString(), Pattern.CASE_INSENSITIVE); + } + + private String replaceWildCardLikeChars(String operand) { + return operand.replaceAll("%", ".*"); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows) { + return materializeMainSchemaTableInternal(table, columns, null, 1, maxRows, true); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int firstRow, int maxRows) { + return materializeMainSchemaTableInternal(table, columns, null, firstRow, maxRows, true); + } + + /** + * Executes an update with a specific {@link WriteConcernAdvisor}. + */ + public void executeUpdate(UpdateScript update, WriteConcernAdvisor writeConcernAdvisor) { + MongoDbUpdateCallback callback = new MongoDbUpdateCallback(this, writeConcernAdvisor); + try { + update.run(callback); + } finally { + callback.close(); + } + } + + /** + * Executes an update with a specific {@link WriteConcern}. + */ + public void executeUpdate(UpdateScript update, WriteConcern writeConcern) { + executeUpdate(update, new SimpleWriteConcernAdvisor(writeConcern)); + } + + @Override + public void executeUpdate(UpdateScript update) { + executeUpdate(update, getWriteConcernAdvisor()); + } + + /** + * Gets the {@link WriteConcernAdvisor} to use on + * {@link #executeUpdate(UpdateScript)} calls. + */ + public WriteConcernAdvisor getWriteConcernAdvisor() { + if (_writeConcernAdvisor == null) { + return new DefaultWriteConcernAdvisor(); + } + return _writeConcernAdvisor; + } + + /** + * Sets a global {@link WriteConcern} advisor to use on + * {@link #executeUpdate(UpdateScript)}. + */ + public void setWriteConcernAdvisor(WriteConcernAdvisor writeConcernAdvisor) { + _writeConcernAdvisor = writeConcernAdvisor; + } + + /** + * Gets the {@link DB} instance that this {@link DataContext} is backed by. + */ + public DB getMongoDb() { + return _mongoDb; + } + + protected void addTable(MutableTable table) { + if (_schema instanceof MutableSchema) { + MutableSchema mutableSchema = (MutableSchema) _schema; + mutableSchema.addTable(table); + } else { + throw new UnsupportedOperationException("Schema is not mutable"); + } + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataSet.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataSet.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataSet.java new file mode 100644 index 0000000..8c2a107 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDataSet.java @@ -0,0 +1,84 @@ +/** + * 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.mongodb.mongo2; + +import org.apache.metamodel.data.AbstractDataSet; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.mongodb.common.MongoDBUtils; +import org.apache.metamodel.schema.Column; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.DBCursor; +import com.mongodb.DBObject; + +final class MongoDbDataSet extends AbstractDataSet { + + private static final Logger logger = LoggerFactory.getLogger(MongoDbDataSet.class); + + private final DBCursor _cursor; + private final boolean _queryPostProcessed; + + private boolean _closed; + private volatile DBObject _dbObject; + + public MongoDbDataSet(DBCursor cursor, Column[] columns, boolean queryPostProcessed) { + super(columns); + _cursor = cursor; + _queryPostProcessed = queryPostProcessed; + _closed = false; + } + + public boolean isQueryPostProcessed() { + return _queryPostProcessed; + } + + @Override + public void close() { + super.close(); + _cursor.close(); + _closed = true; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (!_closed) { + logger.warn("finalize() invoked, but DataSet is not closed. Invoking close() on {}", this); + close(); + } + } + + @Override + public boolean next() { + if (_cursor.hasNext()) { + _dbObject = _cursor.next(); + return true; + } else { + _dbObject = null; + return false; + } + } + + @Override + public Row getRow() { + return MongoDBUtils.toRow(_dbObject, getHeader()); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDeleteBuilder.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDeleteBuilder.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDeleteBuilder.java new file mode 100644 index 0000000..2ee1977 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDeleteBuilder.java @@ -0,0 +1,56 @@ +/** + * 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.mongodb.mongo2; + +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.delete.AbstractRowDeletionBuilder; +import org.apache.metamodel.schema.Table; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.WriteConcern; +import com.mongodb.WriteResult; + +final class MongoDbDeleteBuilder extends AbstractRowDeletionBuilder { + + private static final Logger logger = LoggerFactory.getLogger(MongoDbDeleteBuilder.class); + + private final MongoDbUpdateCallback _updateCallback; + + public MongoDbDeleteBuilder(MongoDbUpdateCallback updateCallback, Table table) { + super(table); + _updateCallback = updateCallback; + } + + @Override + public void execute() throws MetaModelException { + final DBCollection collection = _updateCallback.getCollection(getTable().getName()); + + final MongoDbDataContext dataContext = _updateCallback.getDataContext(); + final BasicDBObject query = dataContext.createMongoDbQuery(getTable(), getWhereItems()); + + WriteConcern writeConcern = _updateCallback.getWriteConcernAdvisor().adviceDeleteQuery(collection, query); + + final WriteResult writeResult = collection.remove(query, writeConcern); + logger.info("Remove returned result: {}", writeResult); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDropTableBuilder.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDropTableBuilder.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDropTableBuilder.java new file mode 100644 index 0000000..a9f8d0c --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbDropTableBuilder.java @@ -0,0 +1,43 @@ +/** + * 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.mongodb.mongo2; + +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.drop.AbstractTableDropBuilder; +import org.apache.metamodel.schema.MutableSchema; +import org.apache.metamodel.schema.Table; + +final class MongoDbDropTableBuilder extends AbstractTableDropBuilder { + + private final MongoDbUpdateCallback _updateCallback; + + public MongoDbDropTableBuilder(MongoDbUpdateCallback updateCallback, Table table) { + super(table); + _updateCallback = updateCallback; + } + + @Override + public void execute() throws MetaModelException { + Table table = getTable(); + _updateCallback.removeCollection(table.getName()); + MutableSchema schema = (MutableSchema) table.getSchema(); + schema.removeTable(table); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbInsertionBuilder.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbInsertionBuilder.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbInsertionBuilder.java new file mode 100644 index 0000000..d9cd583 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbInsertionBuilder.java @@ -0,0 +1,64 @@ +/** + * 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.mongodb.mongo2; + +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.insert.AbstractRowInsertionBuilder; +import org.apache.metamodel.insert.RowInsertionBuilder; +import org.apache.metamodel.schema.Column; +import org.apache.metamodel.schema.Table; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.WriteConcern; +import com.mongodb.WriteResult; + +final class MongoDbInsertionBuilder extends AbstractRowInsertionBuilder<MongoDbUpdateCallback> implements RowInsertionBuilder { + + private static final Logger logger = LoggerFactory.getLogger(MongoDbInsertionBuilder.class); + + public MongoDbInsertionBuilder(MongoDbUpdateCallback updateCallback, Table table) { + super(updateCallback, table); + } + + @Override + public void execute() throws MetaModelException { + final Column[] columns = getColumns(); + final Object[] values = getValues(); + + final BasicDBObject doc = new BasicDBObject(); + + for (int i = 0; i < values.length; i++) { + Object value = values[i]; + if (value != null) { + doc.put(columns[i].getName(), value); + } + } + + final MongoDbUpdateCallback updateCallback = getUpdateCallback(); + final DBCollection collection = updateCallback.getCollection(getTable().getName()); + + final WriteConcern writeConcern = updateCallback.getWriteConcernAdvisor().adviceInsert(collection, doc); + + final WriteResult writeResult = collection.insert(doc, writeConcern); + logger.info("Insert returned result: {}", writeResult); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbTableCreationBuilder.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbTableCreationBuilder.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbTableCreationBuilder.java new file mode 100644 index 0000000..c93acf1 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbTableCreationBuilder.java @@ -0,0 +1,57 @@ +/** + * 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.mongodb.mongo2; + +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.create.AbstractTableCreationBuilder; +import org.apache.metamodel.create.TableCreationBuilder; +import org.apache.metamodel.schema.ColumnType; +import org.apache.metamodel.schema.ImmutableColumn; +import org.apache.metamodel.schema.MutableTable; +import org.apache.metamodel.schema.Schema; +import org.apache.metamodel.schema.Table; + +final class MongoDbTableCreationBuilder extends + AbstractTableCreationBuilder<MongoDbUpdateCallback> implements + TableCreationBuilder { + + public MongoDbTableCreationBuilder(MongoDbUpdateCallback updateCallback, + Schema schema, String name) { + super(updateCallback, schema, name); + } + + @Override + public Table execute() throws MetaModelException { + final MongoDbDataContext dataContext = getUpdateCallback() + .getDataContext(); + final Schema schema = dataContext.getDefaultSchema(); + final MutableTable table = getTable(); + if (table.getColumnByName("_id") == null) { + // all mongo db collections have an _id field as the first field. + ImmutableColumn idColumn = new ImmutableColumn("_id", + ColumnType.ROWID, table, table.getColumnCount(), null, + null, null, null, true, null, true); + table.addColumn(idColumn); + } + table.setSchema(schema); + getUpdateCallback().createCollection(table.getName()); + dataContext.addTable(table); + return table; + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbUpdateCallback.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbUpdateCallback.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbUpdateCallback.java new file mode 100644 index 0000000..046f20c --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/MongoDbUpdateCallback.java @@ -0,0 +1,115 @@ +/** + * 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.mongodb.mongo2; + +import java.io.Closeable; +import java.util.HashMap; +import java.util.Map; + +import org.apache.metamodel.AbstractUpdateCallback; +import org.apache.metamodel.UpdateCallback; +import org.apache.metamodel.create.TableCreationBuilder; +import org.apache.metamodel.delete.RowDeletionBuilder; +import org.apache.metamodel.drop.TableDropBuilder; +import org.apache.metamodel.insert.RowInsertionBuilder; +import org.apache.metamodel.schema.Schema; +import org.apache.metamodel.schema.Table; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; + +final class MongoDbUpdateCallback extends AbstractUpdateCallback implements UpdateCallback, Closeable { + + private final MongoDbDataContext _dataContext; + private final Map<String, DBCollection> _collections; + private final WriteConcernAdvisor _writeConcernAdvisor; + + public MongoDbUpdateCallback(MongoDbDataContext dataContext, WriteConcernAdvisor writeConcernAdvisor) { + super(dataContext); + _dataContext = dataContext; + _writeConcernAdvisor = writeConcernAdvisor; + _collections = new HashMap<String, DBCollection>(); + } + + @Override + public MongoDbDataContext getDataContext() { + return _dataContext; + } + + public WriteConcernAdvisor getWriteConcernAdvisor() { + return _writeConcernAdvisor; + } + + @Override + public TableCreationBuilder createTable(Schema schema, String name) throws IllegalArgumentException, + IllegalStateException { + return new MongoDbTableCreationBuilder(this, schema, name); + } + + @Override + public RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException { + return new MongoDbInsertionBuilder(this, table); + } + + protected void createCollection(String name) { + DBCollection collection = _dataContext.getMongoDb().createCollection(name, new BasicDBObject()); + _collections.put(name, collection); + } + + protected void removeCollection(String name) { + DBCollection collection = getCollection(name); + _collections.remove(name); + collection.drop(); + } + + protected DBCollection getCollection(String name) { + DBCollection collection = _collections.get(name); + if (collection == null) { + collection = _dataContext.getMongoDb().getCollection(name); + _collections.put(name, collection); + } + return collection; + } + + @Override + public void close() { + _collections.clear(); + } + + @Override + public boolean isDropTableSupported() { + return true; + } + + @Override + public TableDropBuilder dropTable(Table table) throws UnsupportedOperationException { + return new MongoDbDropTableBuilder(this, table); + } + + @Override + public boolean isDeleteSupported() { + return true; + } + + @Override + public RowDeletionBuilder deleteFrom(Table table) throws IllegalArgumentException, IllegalStateException, + UnsupportedOperationException { + return new MongoDbDeleteBuilder(this, table); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/SimpleWriteConcernAdvisor.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/SimpleWriteConcernAdvisor.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/SimpleWriteConcernAdvisor.java new file mode 100644 index 0000000..2854615 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/SimpleWriteConcernAdvisor.java @@ -0,0 +1,50 @@ +/** + * 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.mongodb.mongo2; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.WriteConcern; + +/** + * A simple {@link WriteConcernAdvisor} that always returns the same write + * concern. + */ +public class SimpleWriteConcernAdvisor implements WriteConcernAdvisor { + + private final WriteConcern _writeConcern; + + public SimpleWriteConcernAdvisor(WriteConcern writeConcern) { + if (writeConcern == null) { + throw new IllegalArgumentException("WriteConcern cannot be null"); + } + _writeConcern = writeConcern; + } + + @Override + public WriteConcern adviceDeleteQuery(DBCollection collection, BasicDBObject query) { + return _writeConcern; + } + + @Override + public WriteConcern adviceInsert(DBCollection collection, BasicDBObject document) { + return _writeConcern; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/WriteConcernAdvisor.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/WriteConcernAdvisor.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/WriteConcernAdvisor.java new file mode 100644 index 0000000..a9a89e9 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/WriteConcernAdvisor.java @@ -0,0 +1,35 @@ +/** + * 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.mongodb.mongo2; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.WriteConcern; + +/** + * Interface for component that advices MetaModel on which {@link WriteConcern} + * to apply to given operations + */ +public interface WriteConcernAdvisor { + + public WriteConcern adviceDeleteQuery(DBCollection collection, BasicDBObject query); + + public WriteConcern adviceInsert(DBCollection collection, BasicDBObject document); + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/365fae3a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/package-info.java ---------------------------------------------------------------------- diff --git a/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/package-info.java b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/package-info.java new file mode 100644 index 0000000..b6ffb14 --- /dev/null +++ b/mongodb/mongo2/src/main/java/org/apache/metamodel/mongodb/mongo2/package-info.java @@ -0,0 +1,23 @@ +/** + * 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. + */ +/** + * Module package for MongoDB support + */ +package org.apache.metamodel.mongodb.mongo2; +
