Java tutorial
/******************************************************************************* * Educational Online Test Delivery System * Copyright (c) 2013 American Institutes for Research * * Distributed under the AIR Open Source License, Version 1.0 * See accompanying file AIR-License-1_0.txt or at * http://www.smarterapp.org/documents/American_Institutes_for_Research_Open_Source_Software_License.pdf ******************************************************************************/ package org.opentestsystem.authoring.testauth.persistence; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang.StringUtils; import org.opentestsystem.authoring.testauth.domain.Item; import org.opentestsystem.authoring.testauth.domain.search.ItemSearchRequest; import org.opentestsystem.shared.search.domain.SearchResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedSet; /** * Interface for Item mongoDb repository. */ public class ItemRepositoryImpl implements ItemRepositoryCustom { private static final Map<String, String> REGEX_REPLACE_MAP = ImmutableMap.of("\\|", "\\\\|"); private static final PageRequest ITEM_SEARCH_PAGE_REQUEST = new PageRequest(0, 400, Direction.ASC, "tibIdentifier"); private static final Comparator<Item> ITEM_METADATA_ID_COMPARATOR = new Comparator<Item>() { @Override public int compare(final Item o1, final Item o2) { return o1.getTibIdentifier().compareTo(o2.getTibIdentifier()); } }; @Autowired private transient MongoOperations mongoOperations; @Override public long findCountByAssessmentId(final String assessmentId) { final Query query = new Query(); query.addCriteria(Criteria.where("assessmentId").is(assessmentId)); return this.mongoOperations.count(query, Item.class); } private static final int NON_MAGIC_20 = 20; @Override public List<Item> findFirst20DistinctItemsByAssessmentIdAndSearchVal(final String assessmentId, final String searchVal) { final Query query = new Query(); // search for items within the given assessment query.addCriteria(Criteria.where("assessmentId").is(assessmentId)); // if searchVal provided, filter items by tibIdentifier/description if (StringUtils.isNotBlank(searchVal)) { final String escapedVal = escapeString(searchVal); final Criteria searchValCriteria = new Criteria() .orOperator(Criteria.where("tibIdentifier").regex(escapedVal, "i")); query.addCriteria(searchValCriteria); } // find first 400 results and then filter down to 20 distinct results // this is necessary because mongo does not allow you to query for distinct results AND limit your result set // https://jira.mongodb.org/browse/SERVER-2130 query.with(ITEM_SEARCH_PAGE_REQUEST); final List<Item> results = this.mongoOperations.find(query, Item.class); // remove duplicates and return first 20 final List<Item> uniqueResults = ImmutableSortedSet.copyOf(ITEM_METADATA_ID_COMPARATOR, results).asList(); return uniqueResults.subList(0, uniqueResults.size() > NON_MAGIC_20 ? NON_MAGIC_20 : uniqueResults.size()); } @Override public List<Item> findAllBySegmentId(final String segmentId) { final Query query = new Query( Criteria.where("itemLocation").elemMatch(Criteria.where("segmentId").is(segmentId))); return this.mongoOperations.find(query, Item.class); } @Override public List<Item> findAllByFormPartitionId(final String formPartitionId) { final Query query = new Query( Criteria.where("itemLocation").elemMatch(Criteria.where("formPartitionId").is(formPartitionId))); return this.mongoOperations.find(query, Item.class); } @Override public List<Item> findAllByAffinityGroupId(final String affinityGroupId) { final Query query = new Query( Criteria.where("itemLocation").elemMatch(Criteria.where("affinityGroupId").is(affinityGroupId))); return this.mongoOperations.find(query, Item.class); } @Override public SearchResponse<Item> search(final ItemSearchRequest itemSearchRequest) { final Query q = itemSearchRequest.buildQuery(); final List<Criteria> locatorCriteriaList = new ArrayList<Criteria>(); addItemLocatorQueryCriteria(locatorCriteriaList, "itemGroupId", itemSearchRequest.getItemGroupId()); addItemLocatorQueryCriteria(locatorCriteriaList, "segmentId", itemSearchRequest.getSegmentId()); addItemLocatorQueryCriteria(locatorCriteriaList, "formPartitionId", itemSearchRequest.getFormPartitionId()); addItemLocatorQueryCriteria(locatorCriteriaList, "affinityGroupId", itemSearchRequest.getAffinityGroupId()); addItemLocatorQueryCriteria(locatorCriteriaList, "fieldTestItem", itemSearchRequest.getFieldTestItem() == null ? null : Boolean.valueOf(itemSearchRequest.getFieldTestItem())); addItemLocatorQueryCriteria(locatorCriteriaList, "associatedItem", itemSearchRequest.getAssociatedItem() == null ? null : Boolean.valueOf(itemSearchRequest.getAssociatedItem())); if (locatorCriteriaList.size() > 0) { final Criteria itemLocElementMatcher = new Criteria(); itemLocElementMatcher.andOperator(locatorCriteriaList.toArray(new Criteria[] {})); q.addCriteria(Criteria.where("itemLocation").elemMatch(itemLocElementMatcher)); } final long total = this.mongoOperations.count(q, Item.class); final List<Item> results = this.mongoOperations.find(q, Item.class); return new SearchResponse<Item>(results, itemSearchRequest, total); } private void addItemLocatorQueryCriteria(final List<Criteria> currentCriteria, final String fieldName, final Object value) { if (value != null) { currentCriteria.add(Criteria.where(fieldName).is(value)); } } @Override public List<Item> findAllByItemGroupId(final String itemGroupId) { final Query query = new Query( Criteria.where("itemLocation").elemMatch(Criteria.where("itemGroupId").is(itemGroupId))); return this.mongoOperations.find(query, Item.class); } private String escapeString(final String val) { String rVal = val; for (final Entry<String, String> entry : REGEX_REPLACE_MAP.entrySet()) { rVal = rVal.replaceAll(entry.getKey(), entry.getValue()); } return rVal; } @Override public long searchForItemCounts(final ItemSearchRequest itemSearchRequest) { final Query query = itemSearchRequest.buildQuery(); final List<Criteria> locatorCriteriaList = new ArrayList<Criteria>(); addItemLocatorQueryCriteria(locatorCriteriaList, "itemGroupId", itemSearchRequest.getItemGroupId()); addItemLocatorQueryCriteria(locatorCriteriaList, "segmentId", itemSearchRequest.getSegmentId()); addItemLocatorQueryCriteria(locatorCriteriaList, "formPartitionId", itemSearchRequest.getFormPartitionId()); addItemLocatorQueryCriteria(locatorCriteriaList, "affinityGroupId", itemSearchRequest.getAffinityGroupId()); addItemLocatorQueryCriteria(locatorCriteriaList, "fieldTestItem", itemSearchRequest.getFieldTestItem() == null ? null : Boolean.valueOf(itemSearchRequest.getFieldTestItem())); addItemLocatorQueryCriteria(locatorCriteriaList, "associatedItem", itemSearchRequest.getAssociatedItem() == null ? null : Boolean.valueOf(itemSearchRequest.getAssociatedItem())); if (locatorCriteriaList.size() > 0) { final Criteria itemLocElementMatcher = new Criteria(); itemLocElementMatcher.andOperator(locatorCriteriaList.toArray(new Criteria[] {})); query.addCriteria(Criteria.where("itemLocation").elemMatch(itemLocElementMatcher)); } return this.mongoOperations.count(query, Item.class); } }