eu.delving.services.core.MetaRepoImpl.java Source code

Java tutorial

Introduction

Here is the source code for eu.delving.services.core.MetaRepoImpl.java

Source

/*
 * Copyright 2010 DELVING BV
 *
 * Licensed under the EUPL, Version 1.1 or as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * you may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://ec.europa.eu/idabc/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */

package eu.delving.services.core;

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import eu.delving.core.util.MongoFactory;
import eu.delving.metadata.MetadataModel;
import eu.delving.services.core.impl.ImplFactory;
import eu.delving.services.exceptions.*;
import eu.delving.sip.AccessKey;
import eu.delving.sip.DataSetState;
import eu.europeana.sip.core.GroovyCodeResource;
import eu.europeana.sip.core.MappingException;
import org.apache.log4j.Logger;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;

import java.util.*;

import static eu.delving.core.util.MongoObject.mob;

/**
 * Wrap the mongo database so that what goes in and comes out is managed.
 *
 * @author Gerald de Jong <geralddejong@gmail.com>
 */

public class MetaRepoImpl implements MetaRepo {
    private Logger log = Logger.getLogger(getClass());
    private ImplFactory implFactory;
    private DB mongoDatabase;

    @Autowired
    private MetaConfig metaRepoConfig;

    @Autowired
    private AccessKey accessKey;

    @Qualifier("mongoDb")
    @Autowired
    private MongoFactory mongoFactory;

    @Autowired
    private MetadataModel metadataModel;

    @Autowired
    private GroovyCodeResource groovyCodeResource;

    @Value("#{launchProperties['services.mongo.dbName']}")
    private String mongoDatabaseName;

    public void setMongoDatabaseName(String mongoDatabaseName) {
        this.mongoDatabaseName = mongoDatabaseName;
    }

    public void setResponseListSize(int responseListSize) {
        factory().setResponseListSize(responseListSize);
    }

    public void setHarvestStepSecondsToLive(int harvestStepSecondsToLive) {
        factory().setHarvestStepSecondsToLive(harvestStepSecondsToLive);
    }

    private ImplFactory factory() {
        if (implFactory == null) {
            implFactory = new ImplFactory(this, db(), metadataModel, groovyCodeResource, accessKey);
        }
        return implFactory;
    }

    private synchronized DB db() {
        if (mongoDatabase == null) {
            mongoDatabase = mongoFactory.getMongo().getDB(mongoDatabaseName);
        }
        return mongoDatabase;
    }

    @Override
    public DataSet createDataSet(String spec) {
        DataSet dataSet = factory()
                .createDataSet(mob(DataSet.SPEC, spec, DataSet.DATA_SET_STATE, DataSetState.INCOMPLETE.toString()));
        dataSet.save();
        return dataSet;
    }

    @Override
    public synchronized Collection<? extends DataSet> getDataSets() {
        List<DataSet> sets = new ArrayList<DataSet>();
        DBCollection collection = db().getCollection(DATASETS_COLLECTION);
        DBCursor cursor = collection.find();
        while (cursor.hasNext()) {
            DBObject object = cursor.next();
            DataSet dataSet = factory().createDataSet(object);
            if (!dataSet.hasDetails())
                continue; // todo: add to query
            sets.add(dataSet);
        }
        return sets;
    }

    @Override
    public DataSet getDataSet(String spec) {
        DBCollection collection = db().getCollection(DATASETS_COLLECTION);
        DBObject object = collection.findOne(mob(DataSet.SPEC, spec));
        if (object == null) {
            return null;
        }
        return factory().createDataSet(object);
    }

    @Override
    public DataSet getDataSetForIndexing(int maxSimultaneous) {
        DBCollection collection = db().getCollection(DATASETS_COLLECTION);
        int indexingCount = collection.find(mob(DataSet.DATA_SET_STATE, DataSetState.INDEXING.toString())).count();
        if (indexingCount < maxSimultaneous) {
            DBObject object = collection.findOne(mob(DataSet.DATA_SET_STATE, DataSetState.QUEUED.toString()));
            if (object != null)
                return factory().createDataSet(object);
        }
        return null;
    }

    @Override
    public Set<MetadataFormat> getMetadataFormats() {
        Set<MetadataFormat> set = new TreeSet<MetadataFormat>();
        for (DataSet dataSet : getDataSets()) {
            set.add(dataSet.getDetails().getMetadataFormat());
            for (Mapping mapping : dataSet.mappings().values()) {
                set.add(mapping.getMetadataFormat());
            }
        }
        return set;
    }

    @Override
    public Set<MetadataFormat> getMetadataFormats(String id, String accessKey)
            throws MappingNotFoundException, AccessKeyException, MappingException {
        Set<MetadataFormat> set = new TreeSet<MetadataFormat>();
        ObjectId objectId = new ObjectId(id);
        for (DataSet dataSet : getDataSets()) {
            Record record = dataSet.getRecord(objectId, dataSet.getDetails().getMetadataFormat().getPrefix(),
                    accessKey);
            if (record != null) {
                set.add(dataSet.getDetails().getMetadataFormat());
                for (Mapping mapping : dataSet.mappings().values()) {
                    set.add(mapping.getMetadataFormat());
                }
            }
        }
        return set;
    }

    @Override
    public HarvestStep getFirstHarvestStep(PmhVerb verb, String set, Date from, Date until, String metadataPrefix,
            String accessKey) throws DataSetNotFoundException, MappingNotFoundException, AccessKeyException {
        DataSet dataSet = getDataSet(set);
        if (dataSet == null) {
            String errorMessage = String.format("Cannot find set [%s]", set);
            log.error(errorMessage);
            throw new DataSetNotFoundException(errorMessage);
        }
        // sort by expiration date and get first One
        DBObject step = mob(HarvestStep.PMH_REQUEST,
                mob(PmhRequest.VERB, verb.toString(), PmhRequest.SET, set, PmhRequest.FROM, from, PmhRequest.UNTIL,
                        until, PmhRequest.PREFIX, metadataPrefix),
                HarvestStep.LIST_SIZE, dataSet.getRecordCount(), HarvestStep.NAMESPACES, dataSet.getNamespaces(),
                HarvestStep.EXPIRATION, null, HarvestStep.CURSOR, 0);
        final DBCursor dbCursor = factory().harvestSteps().find(step).sort(mob(MetaRepo.MONGO_ID, 1)).limit(1);
        if (dbCursor.count() == 1) {
            return factory().createHarvestStep(dbCursor.next(), accessKey);
        } else {
            return factory().createHarvestStep(step, accessKey);
        }
    }

    @Override
    public HarvestStep getHarvestStep(String resumptionToken, String accessKey)
            throws ResumptionTokenNotFoundException, DataSetNotFoundException, MappingNotFoundException,
            AccessKeyException {
        ObjectId objectId = new ObjectId(resumptionToken);
        DBObject step = factory().harvestSteps().findOne(mob(MONGO_ID, objectId));
        if (step == null) {
            throw new ResumptionTokenNotFoundException("Unable to find resumptionToken: " + resumptionToken);
        }
        return factory().createHarvestStep(step, accessKey);
    }

    @Override
    public void removeExpiredHarvestSteps() {
        db().getCollection(HARVEST_STEPS_COLLECTION).remove(mob(HarvestStep.EXPIRATION, mob("$lt", new Date())));
    }

    @Override
    public Record getRecord(String identifier, String metadataPrefix, String accessKey) throws BadArgumentException,
            DataSetNotFoundException, MappingNotFoundException, AccessKeyException, MappingException {
        RecordIdentifier recordIdentifier = createIdentifier(identifier);
        return fetch(recordIdentifier, metadataPrefix, accessKey);
    }

    public Record fetch(RecordIdentifier identifier, String metadataPrefix, String accessKey)
            throws DataSetNotFoundException, MappingNotFoundException, AccessKeyException, MappingException {
        DataSet dataSet = getDataSet(identifier.collectionId);
        if (dataSet == null) {
            throw new DataSetNotFoundException(
                    String.format("Do data set for identifier [%s]", identifier.collectionId));
        }
        return dataSet.getRecord(identifier.objectId, metadataPrefix, accessKey);
    }

    @Override
    public MetaConfig getMetaRepoConfig() {
        return metaRepoConfig;
    }

    private RecordIdentifier createIdentifier(String delimitedString) throws BadArgumentException {
        String[] parts = delimitedString.split(":");
        if (parts.length != 2) {
            throw new BadArgumentException("Identifier must have format <collection-id>:<object-id>");
        }
        try {
            String collectionId = parts[0];
            ObjectId objectId = new ObjectId(parts[1]);
            return new RecordIdentifier(collectionId, objectId);
        } catch (IllegalArgumentException e) {
            log.warn("Bad object id", e);
            throw new BadArgumentException("Bad object id " + parts[1]);
        } catch (Exception e) {
            throw new BadArgumentException(String.format("Unable to create identifier from [%s]", delimitedString));
        }
    }

    private static class RecordIdentifier {
        private String collectionId;
        private ObjectId objectId;

        private RecordIdentifier(String collectionId, ObjectId objectId) {
            this.collectionId = collectionId;
            this.objectId = objectId;
        }

        public String toString() {
            return collectionId + ":" + objectId.toString();
        }
    }
}