package cz.cuni.mff.d3s.been.objectrepository.mongo; import java.util.Set; import java.util.regex.Pattern; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBObject; import cz.cuni.mff.d3s.been.core.persistence.EntityID; import cz.cuni.mff.d3s.been.persistence.DAOException; import cz.cuni.mff.d3s.been.persistence.QueryRedactor; import cz.cuni.mff.d3s.been.storage.QueryExecutor; /** * A skeletal redactor for mongo queries. Takes care of filter construction. * Query construction itself is left to subclasses to handle. * * @author darklight */ abstract class MongoQueryRedactor implements QueryRedactor { private static final String NEQ_OPERATOR = "$ne"; private static final String ABOVE_OPERATOR = "$gte"; private static final String BELOW_OPERATOR = "$lt"; /** * A projection that ensures the <code>_id</code> attribute generated by * MongoDB is not propagated to query results */ private static final DBObject NO_DBID_MAPPING; static { NO_DBID_MAPPING = new BasicDBObject("_id", 0); } private final DBObject filter; private final DBObject mapping; private final EntityID entityID; /** * Creates new MongoQueryRedactor * * @param entityID * target's EntityID */ MongoQueryRedactor(EntityID entityID) { this.entityID = entityID; this.filter = new BasicDBObject(); this.mapping = new BasicDBObject(); } @Override public void equalitySelector(String attributeName, Object value) { filter.put(attributeName, value); } @Override public void inequalitySelector(String attributeName, Object value) { final DBObject neq = new BasicDBObject(); neq.put(NEQ_OPERATOR, value); filter.put(attributeName, neq); } @Override public void patternSelector(String attributeName, String pattern) { filter.put(attributeName, Pattern.compile(pattern)); } @Override public void aboveSelector(String attributeName, Object lowBound) { final DBObject ge = new BasicDBObject(); ge.put(ABOVE_OPERATOR, lowBound); filter.put(attributeName, ge); } @Override public void belowSelector(String attributeName, Object highBound) { final DBObject lt = new BasicDBObject(); lt.put(BELOW_OPERATOR, highBound); filter.put(attributeName, lt); } @Override public void intervalSelector(String attributeName, Object lowBound, Object highBound) { final DBObject between = new BasicDBObject(); between.put(ABOVE_OPERATOR, lowBound); between.put(BELOW_OPERATOR, highBound); filter.put(attributeName, between); } /** * Return the filter to subclasses for query-specific handling * * @return The filter */ protected DBObject getFilter() { return filter; } /** * Return the attribute mapping to subclasses for query-specific handling * * @return The attribute mapping */ protected DBObject getMapping() { mapping.putAll(NO_DBID_MAPPING); return mapping; } /** * Return the path to the objects targeted by the query. * * @return The Entity ID (serves as path) */ protected EntityID getPath() { return entityID; } /** * Factory method for {@link QueryExecutor} instances, with inferred * {@link DB} instance * * @param db * Database to use for querying * * @return The {@link QueryExecutor} * * @throws DAOException * When a query cannot be constructed from provided information */ public abstract QueryExecutor createExecutor(DB db) throws DAOException; @Override public void map(Set<String> attributes) { for (String attribute : attributes) { mapping.put(attribute, 1); } } }