Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**********************************************************************
Copyright (c) 2011 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
2012 Chris Rued - patch for MapReduceCount and collection.count()
...
**********************************************************************/
package org.datanucleus.store.mongodb;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import com.mongodb.ReadPreference;
import org.bson.types.ObjectId;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ExecutionContext;
import org.datanucleus.FetchPlan;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.identity.IdentityUtils;
import org.datanucleus.identity.SCOID;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.ClassMetaData;
import org.datanucleus.metadata.ColumnMetaData;
import org.datanucleus.metadata.EmbeddedMetaData;
import org.datanucleus.metadata.FieldPersistenceModifier;
import org.datanucleus.metadata.FieldRole;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.metadata.MetaDataUtils;
import org.datanucleus.metadata.RelationType;
import org.datanucleus.metadata.VersionMetaData;
import org.datanucleus.state.DNStateManager;
import org.datanucleus.store.FieldValues;
import org.datanucleus.store.StoreData;
import org.datanucleus.store.StoreManager;
import org.datanucleus.store.connection.ManagedConnection;
import org.datanucleus.store.mongodb.fieldmanager.FetchFieldManager;
import org.datanucleus.store.mongodb.query.LazyLoadQueryResult;
import org.datanucleus.store.query.Query;
import org.datanucleus.store.schema.naming.ColumnType;
import org.datanucleus.store.schema.table.Column;
import org.datanucleus.store.schema.table.MemberColumnMapping;
import org.datanucleus.store.schema.table.SurrogateColumnType;
import org.datanucleus.store.schema.table.Table;
import org.datanucleus.store.types.SCO;
import org.datanucleus.store.types.SCOUtils;
import org.datanucleus.store.types.converters.EnumConversionHelper;
import org.datanucleus.store.types.converters.TypeConversionHelper;
import org.datanucleus.store.types.converters.TypeConverter;
import org.datanucleus.util.NucleusLogger;
import java.lang.reflect.Array;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Utilities for MongoDB.
*/
public class MongoDBUtils
{
private MongoDBUtils() {}
public static List performMongoCount(DB db, BasicDBObject filterObject, Class candidateClass, boolean subclasses, ExecutionContext ec)
throws MongoException
{
StoreManager storeMgr = ec.getStoreManager();
long count = 0;
for (AbstractClassMetaData cmd : MetaDataUtils.getMetaDataForCandidates(candidateClass, subclasses, ec))
{
Table table = storeMgr.getStoreDataForClass(cmd.getFullClassName()).getTable();
String collectionName = table.getName();
count += db.getCollection(collectionName).count(filterObject);
}
List results = new LinkedList<>();
results.add(count);
if (ec.getStatistics() != null)
{
// Add to statistics
ec.getStatistics().incrementNumReads();
}
return results;
}
public static boolean isMemberNested(AbstractMemberMetaData mmd)
{
boolean nested = true;
String nestedStr = mmd.getValueForExtension("nested");
if (nestedStr != null && nestedStr.equalsIgnoreCase("false"))
{
nested = false;
}
return nested;
}
/**
* Accessor for the default value specified for the provided member.
* If no defaultValue is provided on the column then returns null.
* @param mmd Metadata for the member
* @return The default value
*/
public static String getDefaultValueForMember(AbstractMemberMetaData mmd)
{
ColumnMetaData[] colmds = mmd.getColumnMetaData();
if (colmds == null || colmds.length < 1)
{
return null;
}
return colmds[0].getDefaultValue();
}
/**
* Accessor for the MongoDB field for the field of this embedded field.
* Uses the column name from the embedded definition (if present), otherwise falls back to
* the column name of the field in its own class definition, otherwise uses its field name.
* @param mmd Metadata for the owning member
* @param fieldNumber Member number of the embedded object
* @return The field name to use
*/
public static String getFieldName(AbstractMemberMetaData mmd, int fieldNumber)
{
String columnName = null;
// Try the first column if specified
EmbeddedMetaData embmd = mmd.getEmbeddedMetaData();
AbstractMemberMetaData embMmd = null;
if (embmd != null)
{
AbstractMemberMetaData[] embmmds = embmd.getMemberMetaData();
embMmd = embmmds[fieldNumber];
}
if (embMmd != null)
{
ColumnMetaData[] colmds = embMmd.getColumnMetaData();
if (colmds != null && colmds.length > 0)
{
columnName = colmds[0].getName();
}
if (columnName == null)
{
// Fallback to the field/property name
columnName = embMmd.getName();
}
if (columnName == null)
{
columnName = embMmd.getName();
}
}
return columnName;
}
/**
* Convenience method that tries to find the object with the specified identity from all DBCollection objects
* from the rootCmd and subclasses. Returns the class name of the object with this identity (or null if not found).
* @param id The identity
* @param rootCmd ClassMetaData for the root class in the inheritance tree
* @param ec ExecutionContext
* @param clr ClassLoader resolver
* @return The class name of the object with this id
*/
public static String getClassNameForIdentity(Object id, AbstractClassMetaData rootCmd, ExecutionContext ec, ClassLoaderResolver clr)
{
Map> classNamesByTableName = new HashMap<>();
Map tableByTableName = new HashMap<>();
StoreManager storeMgr = ec.getStoreManager();
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
try
{
DB db = (DB)mconn.getConnection();
StoreData sd = storeMgr.getStoreDataForClass(rootCmd.getFullClassName());
if (sd == null)
{
// Make sure schema exists, using this connection
((MongoDBStoreManager)storeMgr).manageClasses(new String[] {rootCmd.getFullClassName()}, ec.getClassLoaderResolver(), db);
sd = storeMgr.getStoreDataForClass(rootCmd.getFullClassName());
}
Set rootClassNames = new HashSet();
rootClassNames.add(rootCmd.getFullClassName());
if (sd != null)
{
Table tbl = sd.getTable();
classNamesByTableName.put(tbl.getName(), rootClassNames);
tableByTableName.put(tbl.getName(), tbl);
}
Collection subclassNames = storeMgr.getSubClassesForClass(rootCmd.getFullClassName(), true, clr);
if (subclassNames != null && !subclassNames.isEmpty())
{
for (String subclassName : subclassNames)
{
AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(subclassName, clr);
sd = storeMgr.getStoreDataForClass(cmd.getFullClassName());
if (sd == null)
{
// Make sure schema exists, using this connection
((MongoDBStoreManager)storeMgr).manageClasses(new String[] {rootCmd.getFullClassName()}, ec.getClassLoaderResolver(), db);
sd = storeMgr.getStoreDataForClass(rootCmd.getFullClassName());
}
if (sd != null)
{
Table subTable = sd.getTable();
String subTableName = subTable.getName();
Set classNames = classNamesByTableName.get(subTableName);
if (classNames == null)
{
classNames = new HashSet();
classNamesByTableName.put(subTableName, classNames);
}
classNames.add(cmd.getFullClassName());
if (!tableByTableName.containsKey(subTableName))
{
tableByTableName.put(subTableName, subTable);
}
}
}
}
for (Map.Entry> dbCollEntry : classNamesByTableName.entrySet())
{
// Check each DBCollection for the id PK field(s)
String tableName = dbCollEntry.getKey();
Set classNames = dbCollEntry.getValue();
Table table = tableByTableName.get(tableName);
DBCollection dbColl = db.getCollection(tableName);
BasicDBObject query = new BasicDBObject();
if (rootCmd.getIdentityType() == IdentityType.DATASTORE)
{
Object key = IdentityUtils.getTargetKeyForDatastoreIdentity(id);
if (storeMgr.isValueGenerationStrategyDatastoreAttributed(rootCmd, -1))
{
query.put("_id", new ObjectId((String)key));
}
else
{
query.put(table.getSurrogateColumn(SurrogateColumnType.DATASTORE_ID).getName(), key);
}
}
else if (rootCmd.getIdentityType() == IdentityType.APPLICATION)
{
if (IdentityUtils.isSingleFieldIdentity(id))
{
Object key = IdentityUtils.getTargetKeyForSingleFieldIdentity(id);
int[] pkNums = rootCmd.getPKMemberPositions();
AbstractMemberMetaData pkMmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[0]);
String pkPropName = table.getMemberColumnMappingForMember(pkMmd).getColumn(0).getName();
query.put(pkPropName, key);
}
else
{
int[] pkNums = rootCmd.getPKMemberPositions();
for (int i=0;i embMmds = new ArrayList();
embMmds.add(pkMmd);
DNStateManager embSM = ec.findStateManager(fieldVal);
AbstractClassMetaData embCmd = embSM.getClassMetaData();
int[] memberPositions = embCmd.getAllMemberPositions();
String embOwnerCol = null;
if (MongoDBUtils.isMemberNested(pkMmd))
{
MemberColumnMapping mapping = table.getMemberColumnMappingForMember(pkMmd);
embOwnerCol = mapping.getColumn(0).getName();
}
for (int j=0;j options)
{
return getObjectsOfCandidateType(q, db, filterObject, null, options, null, null);
}
/**
* Convenience method to return all objects of the candidate type (optionally allowing subclasses).
* @param q Query
* @param db Mongo DB
* @param filterObject Optional filter object
* @param orderingObject Optional ordering object
* @param options Set of options for controlling this query
* @param skip Number of records to skip
* @param limit Max number of records to return
* @return List of all candidate objects (implements QueryResult)
*/
public static List getObjectsOfCandidateType(Query q, DB db, BasicDBObject filterObject, BasicDBObject orderingObject, Map options, Integer skip, Integer limit)
{
LazyLoadQueryResult qr = new LazyLoadQueryResult(q);
// Find the DBCollections we need to query
ExecutionContext ec = q.getExecutionContext();
StoreManager storeMgr = ec.getStoreManager();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
List cmds = MetaDataUtils.getMetaDataForCandidates(q.getCandidateClass(), q.isSubclasses(), ec);
Map> classesByCollectionName = new HashMap<>();
for (AbstractClassMetaData cmd : cmds)
{
if (cmd instanceof ClassMetaData && ((ClassMetaData)cmd).isAbstract())
{
// Omit any classes that are not instantiable (e.g abstract)
}
else
{
StoreData sd = storeMgr.getStoreDataForClass(cmd.getFullClassName());
if (sd == null)
{
// Make sure schema exists, using this connection
((MongoDBStoreManager)storeMgr).manageClasses(new String[] {cmd.getFullClassName()}, ec.getClassLoaderResolver(), db);
sd = storeMgr.getStoreDataForClass(cmd.getFullClassName());
}
Table table = sd.getTable();
String collectionName = table.getName();
List cmdsForCollection = classesByCollectionName.get(collectionName);
if (cmdsForCollection == null)
{
cmdsForCollection = new ArrayList<>();
classesByCollectionName.put(collectionName, cmdsForCollection);
}
cmdsForCollection.add(cmd);
}
}
// Add a query for each DBCollection we need
Iterator>> iter = classesByCollectionName.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry> entry = iter.next();
String collectionName = entry.getKey();
List cmdsForCollection = entry.getValue();
AbstractClassMetaData rootCmd = cmdsForCollection.get(0);
Table rootTable = storeMgr.getStoreDataForClass(rootCmd.getFullClassName()).getTable();
int[] fpMembers = q.getFetchPlan().getFetchPlanForClass(rootCmd).getMemberNumbers();
BasicDBObject fieldsSelection = new BasicDBObject();
if (fpMembers != null && fpMembers.length > 0)
{
fieldsSelection = new BasicDBObject();
for (int i=0;i> filterEntryIter = filterObject.entrySet().iterator();
while (filterEntryIter.hasNext())
{
Map.Entry filterEntry = filterEntryIter.next();
query.put(filterEntry.getKey(), filterEntry.getValue());
}
}
if (rootCmd.hasDiscriminatorStrategy() && cmdsForCollection.size() == 1)
{
// TODO Add this restriction on *all* possible cmds for this DBCollection
// Discriminator present : Add restriction on the discriminator value for this class
query.put(rootTable.getSurrogateColumn(SurrogateColumnType.DISCRIMINATOR).getName(), rootCmd.getDiscriminatorValue());
}
Column multitenancyCol = rootTable.getSurrogateColumn(SurrogateColumnType.MULTITENANCY);
if (multitenancyCol != null)
{
String value = ec.getTenantId();
if (value != null)
{
// Multitenancy discriminator present : Add restriction for this tenant
String fieldName = multitenancyCol.getName();
query.put(fieldName, value);
}
}
Column softDeleteCol = rootTable.getSurrogateColumn(SurrogateColumnType.SOFTDELETE);
if (softDeleteCol != null)
{
// Soft-delete flag
query.put(softDeleteCol.getName(), Boolean.FALSE);
}
DBCollection dbColl = db.getCollection(collectionName);
Object val = (options != null ? options.get("slave-ok") : Boolean.FALSE);
if (val == Boolean.TRUE)
{
dbColl.setReadPreference(ReadPreference.secondaryPreferred());
}
if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled())
{
NucleusLogger.DATASTORE_NATIVE.debug("Performing find() using query on collection " + collectionName +
" for fields=" + fieldsSelection + " with filter=" + query + " and ordering=" + orderingObject);
}
DBCursor curs = dbColl.find(query, fieldsSelection);
if (ec.getStatistics() != null)
{
// Add to statistics
ec.getStatistics().incrementNumReads();
}
if (classesByCollectionName.size() == 1)
{
if (orderingObject != null)
{
curs = curs.sort(orderingObject);
qr.setOrderProcessed(true);
}
// We have a single DBCursor so apply the range specification directly to this DBCursor
if (skip != null && skip > 0)
{
curs = curs.skip(skip);
qr.setRangeProcessed(true);
}
if (limit != null && limit > 0)
{
curs = curs.limit(limit);
qr.setRangeProcessed(true);
}
}
if (curs.hasNext())
{
// Contains result(s) so add it to our QueryResult
qr.addCandidateResult(rootCmd, curs, fpMembers);
}
}
return qr;
}
/**
* Convenience method that takes the provided DBObject and the details of the candidate that it is an instance of, and converts it into the associated POJO.
* @param dbObject The DBObject
* @param ec ExecutionContext
* @param cmd Metadata for the candidate class
* @param fpMembers FetchPlan members for the class that are provided
* @param ignoreCache Whether to ignore the cache
* @return The Pojo object
*/
public static Object getPojoForDBObjectForCandidate(DBObject dbObject, ExecutionContext ec, AbstractClassMetaData cmd, int[] fpMembers, boolean ignoreCache)
{
Table table = ec.getStoreManager().getStoreDataForClass(cmd.getFullClassName()).getTable();
if (cmd.hasDiscriminatorStrategy())
{
// Determine the class from the discriminator property
String disPropName = table.getSurrogateColumn(SurrogateColumnType.DISCRIMINATOR).getName();
String discValue = (String)dbObject.get(disPropName);
String clsName = ec.getMetaDataManager().getClassNameFromDiscriminatorValue(discValue, cmd.getDiscriminatorMetaData());
if (!cmd.getFullClassName().equals(clsName) && clsName != null)
{
cmd = ec.getMetaDataManager().getMetaDataForClass(clsName, ec.getClassLoaderResolver());
}
}
Object pojo = null;
if (cmd.getIdentityType() == IdentityType.APPLICATION)
{
pojo = MongoDBUtils.getObjectUsingApplicationIdForDBObject(dbObject, cmd, ec, ignoreCache, fpMembers);
}
else if (cmd.getIdentityType() == IdentityType.DATASTORE)
{
pojo = MongoDBUtils.getObjectUsingDatastoreIdForDBObject(dbObject, cmd, ec, ignoreCache, fpMembers);
}
else
{
pojo = MongoDBUtils.getObjectUsingNondurableIdForDBObject(dbObject, cmd, ec, ignoreCache, fpMembers);
}
return pojo;
}
protected static void selectAllFieldsOfEmbeddedObject(AbstractMemberMetaData mmd, BasicDBObject fieldsSelection, ExecutionContext ec, ClassLoaderResolver clr)
{
EmbeddedMetaData embmd = mmd.getEmbeddedMetaData();
AbstractMemberMetaData[] embmmds = embmd.getMemberMetaData();
for (int i=0;i entryIter = rawMap.entrySet().iterator();
while (entryIter.hasNext())
{
Map.Entry entry = entryIter.next();
BasicDBObject entryObj = new BasicDBObject();
Object storeKey = getStoredValueForField(ec, mmd, mapping, entry.getKey(), FieldRole.ROLE_MAP_KEY);
entryObj.put("key", storeKey);
Object storeValue = getStoredValueForField(ec, mmd, mapping, entry.getValue(), FieldRole.ROLE_MAP_VALUE);
entryObj.put("value", storeValue);
coll.add(entryObj);
}
return coll;
}
else if (fieldRole == FieldRole.ROLE_MAP_KEY)
{
TypeConverter keyConv = mapping.getTypeConverterForComponent(fieldRole);
if (keyConv != null)
{
return keyConv.toDatastoreType(value);
}
}
else if (fieldRole == FieldRole.ROLE_MAP_VALUE)
{
TypeConverter valConv = mapping.getTypeConverterForComponent(fieldRole);
if (valConv != null)
{
return valConv.toDatastoreType(value);
}
}
}
}
Class type = value.getClass();
if (mmd != null)
{
if (optional)
{
type = ec.getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
}
else
{
if (mmd.hasCollection() && fieldRole == FieldRole.ROLE_COLLECTION_ELEMENT)
{
type = ec.getClassLoaderResolver().classForName(mmd.getCollection().getElementType());
}
else if (mmd.hasArray() && fieldRole == FieldRole.ROLE_ARRAY_ELEMENT)
{
type = ec.getClassLoaderResolver().classForName(mmd.getArray().getElementType());
}
else if (mmd.hasMap() && fieldRole == FieldRole.ROLE_MAP_KEY)
{
type = ec.getClassLoaderResolver().classForName(mmd.getMap().getKeyType());
}
else if (mmd.hasMap() && fieldRole == FieldRole.ROLE_MAP_VALUE)
{
type = ec.getClassLoaderResolver().classForName(mmd.getMap().getValueType());
}
}
}
if (Long.class.isAssignableFrom(type) ||
Integer.class.isAssignableFrom(type) ||
Short.class.isAssignableFrom(type) ||
String.class.isAssignableFrom(type) ||
Byte.class.isAssignableFrom(type) ||
Boolean.class.isAssignableFrom(type))
{
return value;
}
else if (Enum.class.isAssignableFrom(type))
{
return EnumConversionHelper.getStoredValueFromEnum(mmd, fieldRole, (Enum)value);
}
else if (type == Date.class)
{
return value;
}
else if (Date.class.isAssignableFrom(type))
{
// Convert to java.util.Date since MongoDB doesn't support java.sql
return new java.util.Date(((Date)value).getTime());
}
else if (Calendar.class.isAssignableFrom(type))
{
ColumnMetaData colmd = null;
if (mmd != null && mmd.getColumnMetaData() != null && mmd.getColumnMetaData().length > 0)
{
colmd = mmd.getColumnMetaData()[0];
}
if (!MetaDataUtils.persistColumnAsString(colmd))
{
// Persisted as Date
return ((Calendar)value).getTime();
}
}
else if (Character.class.isAssignableFrom(type) || char.class.isAssignableFrom(type))
{
// store as String
return "" + value;
}
// Fallback to built-in type converters
// TODO Make use of default TypeConverter for a type before falling back to String/Long
TypeConverter strConv = ec.getTypeManager().getTypeConverterForType(type, String.class);
TypeConverter longConv = ec.getTypeManager().getTypeConverterForType(type, Long.class);
if (strConv != null)
{
// store as a String
return strConv.toDatastoreType(value);
}
else if (longConv != null)
{
// store as a Long
return longConv.toDatastoreType(value);
}
// store as the raw value
return value;
}
/**
* Convenience method to convert the stored value for an object field into the value that will be held
* in the object. Note that this does not cater for relation fields, just basic fields.
* @param ec ExecutionContext
* @param mmd Metadata for the field holding this value (if available)
* @param mapping Member column mapping (if available)
* @param value The stored value for the field
* @param fieldRole The role of this value for the field
* @return The value to put in the field
*/
public static Object getFieldValueFromStored(ExecutionContext ec, AbstractMemberMetaData mmd, MemberColumnMapping mapping, Object value, FieldRole fieldRole)
{
if (value == null)
{
return null;
}
boolean optional = (mmd != null ? Optional.class.isAssignableFrom(mmd.getType()) : false);
if (mmd != null)
{
if (mmd.hasCollection() && !optional)
{
if (fieldRole == FieldRole.ROLE_FIELD)
{
Collection