au.edu.anu.metadatastores.store.datacommons.DataCommonsService.java Source code

Java tutorial

Introduction

Here is the source code for au.edu.anu.metadatastores.store.datacommons.DataCommonsService.java

Source

/*******************************************************************************
 * Australian National University Metadata Stores
 * Copyright (C) 2013  The Australian National University
 * 
 * This file is part of Australian National University Metadata Stores.
 * 
 * Australian National University Metadata Stores is free software: you
 * can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package au.edu.anu.metadatastores.store.datacommons;

import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import au.edu.anu.metadatastores.datamodel.harvester.HarvestContent;
import au.edu.anu.metadatastores.datamodel.store.Item;
import au.edu.anu.metadatastores.datamodel.store.ItemAttribute;
import au.edu.anu.metadatastores.datamodel.store.ItemRelation;
import au.edu.anu.metadatastores.datamodel.store.ItemRelationId;
import au.edu.anu.metadatastores.datamodel.store.RelationMapping;
import au.edu.anu.metadatastores.datamodel.store.annotations.ItemTraitParser;
import au.edu.anu.metadatastores.datamodel.store.ext.StoreAttributes;
import au.edu.anu.metadatastores.harvester.HarvestContentService;
import au.edu.anu.metadatastores.services.store.StoreHibernateUtil;
import au.edu.anu.metadatastores.store.dublincore.DublinCoreItem;
import au.edu.anu.metadatastores.store.dublincore.DublinCoreService;
import au.edu.anu.metadatastores.store.dublincore.xml.DublinCore;
import au.edu.anu.metadatastores.store.misc.Mappings;
import au.edu.anu.metadatastores.store.properties.StoreProperties;

/**
 * <p>DataCommonsService<p>
 * 
 * <p>The Australian National University</p>
 * 
 * <p>Service to provide updates to Data Commons records</p>
 * 
 * @author Genevieve Turner
 *
 */
public class DataCommonsService extends DublinCoreService {
    static final Logger LOGGER = LoggerFactory.getLogger(DataCommonsService.class);

    private static DataCommonsService singleton_;
    private static final String extSystem = "DATA_COMMONS";
    HarvestContentService contentService_ = HarvestContentService.getSingleton();

    /**
     * Constructor class for the DataCommonsSevice
     */
    private DataCommonsService() {

    }

    /**
     * Returns a singleton instance for the DataCommonsservice
     * 
     * @return the DataCommonsService
     */
    public static DataCommonsService getSingleton() {
        if (singleton_ == null) {
            singleton_ = new DataCommonsService();
        }
        return singleton_;
    }

    /**
     * Process the content that has been harvested for data commons
     */
    public void processHarvestContent() {

        String datacommonsLocation = StoreProperties.getProperty("harvest.location.datacommons");

        HarvestContent content = contentService_.getNextHarvestContent(datacommonsLocation);
        while (content != null) {
            LOGGER.debug("ID: {}, Identifier: {}, Content: {}",
                    new Object[] { content.getHid(), content.getIdentifier(), content.getContent() });
            if ("deleted".equals(content.getContent())) {
                processDeleted(content);
            } else {
                processRecord(content);
            }
            contentService_.deleteHarvestContent(content);
            content = contentService_.getNextHarvestContent(datacommonsLocation);
        }
    }

    /**
     * Process records that have the deleted status from oai-pmh
     * 
     * @param content The harvested record to process
     */
    private void processDeleted(HarvestContent content) {
        Session session = StoreHibernateUtil.getSessionFactory().openSession();
        try {
            session.beginTransaction();

            Query query = session
                    .createQuery("FROM DataCommonsItem WHERE extSystem = :extSystem AND extId = :extId");
            query.setParameter("extSystem", extSystem);
            query.setParameter("extId", content.getIdentifier());

            DataCommonsItem item = (DataCommonsItem) query.uniqueResult();

            if (item != null) {
                item.setDeleted(Boolean.TRUE);
                session.merge(item);
            } else {
                LOGGER.debug("No record to be deleted: {}", content.getIdentifier());
            }
            session.getTransaction().commit();
        } finally {
            session.close();
        }
    }

    /**
     * Process a record that has not been deleted
     * 
     * @param content The harvested record to process
     */
    private void processRecord(HarvestContent content) {
        Session session = StoreHibernateUtil.getSessionFactory().openSession();
        try {
            session.beginTransaction();
            session.enableFilter("attributes");

            Query query = session
                    .createQuery("FROM DataCommonsItem WHERE extSystem = :extSystem AND extId = :extId");
            query.setParameter("extSystem", extSystem);
            query.setParameter("extId", content.getIdentifier());

            DataCommonsItem item = (DataCommonsItem) query.uniqueResult();
            if (item == null) {
                item = new DataCommonsItem();
                item.setExtId(content.getIdentifier());
                session.save(item);
            }

            try {
                JAXBContext context = JAXBContext.newInstance(DublinCore.class);
                Unmarshaller unmarshaller = context.createUnmarshaller();

                DublinCore dublinCore = (DublinCore) unmarshaller.unmarshal(new StringReader(content.getContent()));
                Date lastModified = new Date();
                super.processRecord((DublinCoreItem) item, dublinCore, session, lastModified);
            } catch (JAXBException e) {
                LOGGER.error("Exception transforming document", e);
            } catch (InvocationTargetException e) {
                LOGGER.error("Error invoking method", e);
            } catch (IllegalAccessException e) {
                LOGGER.error("Error accessing method", e);
            }

            session.merge(item);

            LOGGER.debug("Item Numbers: {}", item.getItemAttributes().size());

            session.getTransaction().commit();
        } finally {
            session.close();
        }
    }

    /**
     * Set split the relation into relation parts
     * 
     * @param relation The relation
     * @return The parts of the relation
     */
    private String[] getRelationParts(String relation) {
        String[] values = new String[2];
        int index = relation.indexOf("http");
        LOGGER.debug("Relation: {}, Index: {}", relation, index);
        if (index >= 0) {
            String relationItem = relation.substring(index).trim();
            String relationValue = relation.substring(0, index).trim();
            values[0] = relationValue;
            values[1] = relationItem;
        } else {
            values[1] = relation;
        }

        return values;
    }

    /**
     * Set the relationships
     * 
     * @param item The dublin core item to set the relation for
     * @param dublinCore the dublin core to set relations for
     * @param session The hibernate session
     */
    protected void setRelations(DublinCoreItem item, DublinCore dublinCore, Session session) {
        Iterator<ItemRelation> it = item.getItemRelationsForIid().iterator();

        List<ItemRelation> itemRelations = new ArrayList<ItemRelation>();

        List<RelationPart> relationParts = getRelationPartsList(dublinCore);
        setIdentifierRelations(item, relationParts, itemRelations, session);
        setNLAIdentifierRelations(item, relationParts, itemRelations, session);
        setARCIdentifierRelations(item, relationParts, itemRelations, session);
        setNHMRCIdentifierRelations(item, relationParts, itemRelations, session);

        boolean hasValue = false;
        while (it.hasNext()) {
            ItemRelation relation = it.next();

            for (ItemRelation itemRelation : itemRelations) {
                if (relation.getId().equals(itemRelation.getId())) {
                    if (Boolean.TRUE.equals(relation.getUserUpdated())) {
                        itemRelation.setUserUpdated(Boolean.TRUE);
                    }
                    hasValue = true;
                }
            }
            if (!hasValue && Boolean.TRUE.equals(relation.getUserUpdated())) {
                itemRelations.add(relation);
            } else if (!hasValue) {
                it.remove();
                session.delete(relation);
            }

            hasValue = false;
        }
        item.setItemRelationsForIid(new HashSet<ItemRelation>(itemRelations));
    }

    /**
     * Get a list of relationship parts from the relations
     * 
     * @param dublinCore The dublin core
     * @return The relationship parts
     */
    private List<RelationPart> getRelationPartsList(DublinCore dublinCore) {
        List<RelationPart> relationParts = new ArrayList<RelationPart>();

        RelationPart relationPart = null;
        for (String relation : dublinCore.getRelations()) {
            String[] relParts = getRelationParts(relation);
            relationPart = new RelationPart(relParts[1], relParts[0]);
            LOGGER.debug("Relation: {}, {}", relationPart.getValue(), relationPart.getType());
            relationParts.add(relationPart);
        }
        LOGGER.debug("Number of relations: {}", relationParts.size());

        return relationParts;
    }

    /**
     * Add relationships based on identifiers in the item
     * 
     * @param item The item to add relationships to
     * @param relationParts The relationship parts
     * @param itemRelations The existing relationships
     * @param session The session
     */
    private void setIdentifierRelations(Item item, List<RelationPart> relationParts,
            List<ItemRelation> itemRelations, Session session) {
        Query query = session.createQuery(
                "SELECT i FROM Item i join i.itemAttributes ia WHERE ia.attrType = :attrType AND ia.attrValue = :attrValue");
        query.setParameter("attrType", StoreAttributes.IDENTIFIER);

        for (RelationPart relationPart : relationParts) {
            query.setParameter("attrValue", relationPart.getValue());
            LOGGER.debug("Item: {}, Value: {}", relationPart.getValue(), relationPart.getType());

            @SuppressWarnings("unchecked")
            List<Item> relItems = query.list();

            String relationType = getRelationType(relationPart.getType());

            for (Item relItem : relItems) {
                ItemRelationId itemRelationId = new ItemRelationId(item.getIid(), relationType, relItem.getIid());
                ItemRelation itemRelation = new ItemRelation();
                itemRelation.setId(itemRelationId);
                itemRelations.add(itemRelation);
            }
        }
    }

    /**
     * Set the Australian Research Council relationships
     * 
     * @param item The item to add the relationship to
     * @param relationParts The relationship parts
     * @param itemRelations The existing relationships
     * @param session The session object
     */
    private void setARCIdentifierRelations(Item item, List<RelationPart> relationParts,
            List<ItemRelation> itemRelations, Session session) {
        String arcPrefix = StoreProperties.getProperty("arc.prefix");
        String arcTitle = StoreProperties.getProperty("arc.grant.title");

        setGrantIdentifierRelations(item, relationParts, itemRelations, session, arcPrefix, arcTitle);
    }

    /**
     * Set the National Health and Medical Research Council relationships
     * 
     * @param item The item to add the relationship to
     * @param relationParts The relationship parts
     * @param itemRelations The existing relationships
     * @param session The session object
     */
    private void setNHMRCIdentifierRelations(Item item, List<RelationPart> relationParts,
            List<ItemRelation> itemRelations, Session session) {
        String nhmrcPrefix = StoreProperties.getProperty("nhmrc.prefix");
        String nhmrcTitle = StoreProperties.getProperty("nhmrc.grant.title");

        setGrantIdentifierRelations(item, relationParts, itemRelations, session, nhmrcPrefix, nhmrcTitle);
    }

    /**
     * Set the grant identifier relationships
     * 
     * @param item The item to add relationships to
     * @param relationParts The relationship parts
     * @param itemRelations The existing item relations
     * @param session The session
     * @param fundsPrefix The prefix of the grant
     * @param fundsProvider The name of the funds provider
     */
    private void setGrantIdentifierRelations(Item item, List<RelationPart> relationParts,
            List<ItemRelation> itemRelations, Session session, String fundsPrefix, String fundsProvider) {
        Query query = session.createQuery(
                "SELECT gr from GrantItem gr join gr.itemAttributes fundProv join gr.itemAttributes refNum where fundProv.attrType = :fundType and fundProv.attrValue = :fundProvValue and refNum.attrType = :refType and refNum.attrValue = :refValue");
        query.setParameter("fundType", StoreAttributes.FUNDS_PROVIDER);
        query.setParameter("refType", StoreAttributes.REFERENCE_NUMBER);
        query.setParameter("fundProvValue", fundsProvider);

        int prefixLength = fundsPrefix.length();
        for (RelationPart relationPart : relationParts) {
            LOGGER.debug("Relation: {}, {}", relationPart.getValue(), relationPart.getType());
            if (relationPart.getValue().startsWith(fundsPrefix)) {
                LOGGER.debug("Is a Grant: {}", relationPart.getValue());
                String id = relationPart.getValue().substring(prefixLength);
                query.setParameter("refValue", id);
                @SuppressWarnings("unchecked")
                List<Item> grants = query.list();
                String relationType = getRelationType(relationPart.getType());
                for (Item grant : grants) {
                    LOGGER.debug("ID: {}, Title: {}", grant.getIid(), grant.getTitle());
                    ItemRelationId itemRelationId = new ItemRelationId(item.getIid(), relationType, grant.getIid());
                    ItemRelation itemRelation = new ItemRelation();
                    itemRelation.setId(itemRelationId);
                    itemRelations.add(itemRelation);
                }
            }
        }
    }

    /**
     * Set the National Library of Australia relationships
     * 
     * @param item The item to add the relationships to
     * @param relationParts The relationship parts
     * @param itemRelations The existing relationships
     * @param session The session object
     */
    private void setNLAIdentifierRelations(Item item, List<RelationPart> relationParts,
            List<ItemRelation> itemRelations, Session session) {
        String nlaPrefix = StoreProperties.getProperty("nla.prefix");

        Query query = session.createQuery(
                "SELECT p FROM PersonItem p join p.itemAttributes nlaId WHERE nlaId.attrType = :nlaType and nlaId.attrValue = :nlaValue");
        query.setParameter("nlaType", StoreAttributes.NLA_ID);

        for (RelationPart relationPart : relationParts) {
            LOGGER.debug("Relation: {}, {}", relationPart.getValue(), relationPart.getType());
            if (relationPart.getValue().startsWith(nlaPrefix)) {
                LOGGER.debug("Is a nla identifier: {}", relationPart.getValue());
                query.setParameter("nlaValue", relationPart.getValue());
                @SuppressWarnings("unchecked")
                List<Item> people = query.list();
                String relationType = getRelationType(relationPart.getType());
                for (Item person : people) {
                    LOGGER.debug("ID: {}, Title: {}", person.getIid(), person.getTitle());
                    ItemRelationId itemRelationId = new ItemRelationId(item.getIid(), relationType,
                            person.getIid());
                    ItemRelation itemRelation = new ItemRelation();
                    itemRelation.setId(itemRelationId);
                    itemRelations.add(itemRelation);
                }
            }
        }
        LOGGER.debug("Item Relation Size: {}", item.getItemRelationsForIid().size());
    }

    /**
     * Set the reverse relationships
     * 
     * @param item The dublin core item to set the relation for
     * @param dublinCore the dublin core to set relations for
     * @param session2 The hibernate session
     */
    protected void setReverseRelations(DublinCoreItem item, DublinCore dublinCore, Session session2) {
        Session session = StoreHibernateUtil.getSessionFactory().openSession();
        try {
            Query query = session
                    .createQuery("FROM ItemAttribute WHERE attrType = :attrType AND attrValue = :attrValue");
            query.setParameter("attrType", StoreAttributes.RELATION_VALUE);
            dublinCore.getIdentifiers();
            String identifier = null;
            for (String id : dublinCore.getIdentifiers()) {
                if (id.startsWith(StoreProperties.getProperty("relation.id.format.datacommons"))) {
                    identifier = id;
                    break;
                }
            }
            if (identifier != null) {
                query.setParameter("attrValue", identifier);
                @SuppressWarnings("unchecked")
                List<ItemAttribute> relatedAttributes = query.list();

                LOGGER.debug("Number of reverse relationships: {}", relatedAttributes.size());
                ItemRelationId id = null;
                for (ItemAttribute relatedAttribute : relatedAttributes) {
                    String relationText = relatedAttribute.getItemAttribute().getAttrValue();

                    String[] relationParts = getRelationParts(relationText);
                    String relationType = getRelationType(relationParts[0]);

                    id = new ItemRelationId(relatedAttribute.getItem().getIid(), relationType, item.getIid());
                    ItemRelation relation = (ItemRelation) session.get(ItemRelation.class, id);
                    if (relation == null) {
                        LOGGER.debug("Does not have relation");
                        ItemRelation newRelation = new ItemRelation();
                        newRelation.setId(id);
                        item.getItemRelationsForRelatedIid().add(newRelation);
                    } else {
                        LOGGER.debug("has relation");
                    }
                }
            }
        } finally {
            session.close();
        }
    }

    /**
     * Get the type of relationship
     * 
     * @param relation The relation to find the relationship type for
     * @return The relationship type
     */
    private String getRelationType(String relation) {
        String relationType = null;
        if (relation != null && relation.trim().length() > 0) {
            RelationMapping mapping = Mappings.getMappingByDescription(relation.trim());
            if (mapping == null) {
                relationType = relation.trim();
            } else {
                relationType = mapping.getCode();
            }
        }
        return relationType;
    }

    public DataCommonsObject getDataCommonsObject(String id) {
        Session session = StoreHibernateUtil.getSessionFactory().openSession();
        session.enableFilter("attributes");
        //DublinCore dataCommonsObject = null;
        try {
            Query query = session.createQuery("FROM DataCommonsItem WHERE extId = :extId");
            query.setParameter("extId", id);

            DataCommonsItem item = (DataCommonsItem) query.uniqueResult();
            DataCommonsObject dataCommonsObject = getDataCommonsObject(item);
            return dataCommonsObject;
        } finally {
            session.close();
        }
    }

    public DataCommonsObject getDataCommonsObject(DataCommonsItem item) {
        DataCommonsObject dataCommonsObject = null;

        ItemTraitParser traitParser = new ItemTraitParser();

        try {
            dataCommonsObject = (DataCommonsObject) traitParser.getItemObject(item, DataCommonsObject.class);
        } catch (Exception e) {
            LOGGER.error("Exception getting data commons object", e);
        }
        //TODO get relations?

        return dataCommonsObject;
    }
}