org.opentestsystem.authoring.testauth.persistence.ItemRepositoryImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.authoring.testauth.persistence.ItemRepositoryImpl.java

Source

/*******************************************************************************
 * 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);
    }
}