com.klistret.cmdb.dao.RelationDAOImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.klistret.cmdb.dao.RelationDAOImpl.java

Source

/**
 ** This file is part of Klistret. Klistret 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.
    
 ** Klistret 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 Klistret. If not,
 ** see <http://www.gnu.org/licenses/>
 */

package com.klistret.cmdb.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;

import javax.xml.namespace.QName;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.StaleStateException;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;

import com.klistret.cmdb.ci.pojo.Element;
import com.klistret.cmdb.ci.pojo.Relation;
import com.klistret.cmdb.ci.pojo.RelationType;
import com.klistret.cmdb.exception.ApplicationException;
import com.klistret.cmdb.exception.InfrastructureException;
import com.klistret.cmdb.exception.NonUniqueObjectException;
import com.klistret.cmdb.utility.hibernate.XPathCriteria;
import com.klistret.cmdb.utility.jaxb.CIContext;

/**
 * 
 * @author Matthew Young
 * 
 */
public class RelationDAOImpl extends BaseImpl implements RelationDAO {

    private static final Logger logger = LoggerFactory.getLogger(RelationDAOImpl.class);

    /**
     * Finds relations based on XPath expressions
     * 
     */
    public List<Relation> find(List<String> expressions, int start, int limit) {
        try {
            logger.debug("Finding relations by expression from start position [{}] with limit [{}]", start, limit);

            if (expressions == null)
                throw new ApplicationException("Expressions parameter is null", new IllegalArgumentException());

            Criteria criteria = new XPathCriteria(expressions, getSession()).getCriteria();
            String alias = criteria.getAlias();

            criteria.setProjection(Projections.projectionList().add(Projections.property(alias + ".id"))
                    .add(Projections.property(alias + ".type")).add(Projections.property(alias + ".source"))
                    .add(Projections.property(alias + ".destination"))
                    .add(Projections.property(alias + ".fromTimeStamp"))
                    .add(Projections.property(alias + ".toTimeStamp"))
                    .add(Projections.property(alias + ".createId"))
                    .add(Projections.property(alias + ".createTimeStamp"))
                    .add(Projections.property(alias + ".updateTimeStamp"))
                    .add(Projections.property(alias + ".version"))
                    .add(Projections.property(alias + ".configuration")));

            criteria.setFirstResult(start);
            criteria.setMaxResults(limit);
            criteria.setFetchSize(limit);

            Object[] results = criteria.list().toArray();

            List<Relation> relations = new ArrayList<Relation>(results.length);
            logger.debug("Results length [{}]", results.length);

            for (int index = 0; index < results.length; index++) {
                Object[] row = (Object[]) results[index];

                Relation relation = new Relation();
                relation.setId((Long) row[0]);
                relation.setType((RelationType) row[1]);
                relation.setSource((Element) row[2]);
                relation.setDestination((Element) row[3]);
                relation.setFromTimeStamp((Date) row[4]);
                relation.setToTimeStamp((Date) row[5]);
                relation.setCreateId((String) row[6]);
                relation.setCreateTimeStamp((Date) row[7]);
                relation.setUpdateTimeStamp((Date) row[8]);
                relation.setVersion((Long) row[9]);
                relation.setConfiguration((com.klistret.cmdb.ci.commons.Relation) row[10]);

                relations.add(relation);
            }

            results = null;

            return relations;
        } catch (StaleStateException e) {
            throw new ApplicationException(
                    "Relation(s) found are stale which means newer version exists (Hibernate).");
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Query unique over XPath expressions
     */
    public Relation unique(List<String> expressions) {
        try {
            logger.debug("Query unique over XPath expressions");

            if (expressions == null)
                throw new ApplicationException("Expressions parameter is null", new IllegalArgumentException());

            Integer count = count(expressions);
            if (count == 0)
                return null;

            if (count > 1)
                throw new NonUniqueObjectException(String.format("Expressions criteria was not unique: %d", count),
                        expressions);

            List<Relation> results = find(expressions, 0, 1);
            Relation relation = results.get(0);

            logger.debug("Returning unique relation [id: {},  version: {}]",
                    new Object[] { relation.getId(), relation.getVersion() });
            return relation;
        } catch (StaleStateException e) {
            throw new ApplicationException("Unique relation stale which means newer version exists (Hibernate).");
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Query count of XPath expressions
     */
    public Integer count(List<String> expressions) {
        try {
            logger.debug("Query count of XPath expressions");

            if (expressions == null)
                throw new ApplicationException("Expressions parameter is null", new IllegalArgumentException());

            Criteria hcriteria = new XPathCriteria(expressions, getSession()).getCriteria();
            hcriteria.setProjection(Projections.rowCount());

            return ((Long) hcriteria.list().get(0)).intValue();
        } catch (StaleStateException e) {
            throw new ApplicationException(
                    "Relation(s) counted are stale which means newer version exists (Hibernate).");
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Get relation by unique ID
     * 
     * @param id
     * @return Relation
     */
    public Relation get(Long id) {
        try {
            logger.debug("Getting relation [id: {}] by id ", id);

            Criteria criteria = getSession().createCriteria(Relation.class);
            criteria.add(Restrictions.idEq(id));

            Relation relation = (Relation) criteria.uniqueResult();

            if (relation == null)
                throw new ApplicationException(String.format("Relation [id: %s] not found", id),
                        new NoSuchElementException());

            logger.debug("Returning element by id [id: {},  version: {}]",
                    new Object[] { relation.getId(), relation.getVersion() });

            return relation;
        } catch (StaleStateException e) {
            throw new ApplicationException(String
                    .format("Got relation [id: %s] is stale which means newer version exists (Hibernate).", id));
        } catch (HibernateOptimisticLockingFailureException e) {
            throw new ApplicationException(
                    String.format("Got relation [id: %s] is stale which means newer version exists (Spring).", id));
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Update/save relation
     * 
     */
    public Relation set(Relation relation) {
        /**
         * pojo type matches the configuration qname
         */
        String typeClassName = CIContext.getCIContext().getBean(QName.valueOf(relation.getType().getName()))
                .getJavaClass().getName();
        if (!typeClassName.equals(relation.getConfiguration().getClass().getName()))
            throw new ApplicationException(
                    String.format("Pojo element type [%s] does not match the configuration type [%s]",
                            typeClassName, relation.getConfiguration().getClass().getName()));

        /**
         * Change update date time
         */
        relation.setUpdateTimeStamp(new java.util.Date());

        try {
            logger.debug("Setting relation [id: {}, version: {}]",
                    new Object[] { relation.getId(), relation.getVersion() });

            if (relation.getId() != null)
                relation = (Relation) getSession().merge("Relation", relation);
            else
                getSession().saveOrUpdate("Relation", relation);
        } catch (StaleStateException e) {
            throw new ApplicationException(String.format(
                    "Set relation [id: %s] is stale which means newer version exists.", relation.getId()), e);
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }

        logger.info("Saved/updated relation [id: {}]", new Object[] { relation.getId() });

        return relation;
    }

    /**
     * Delete a relation by setting the ToTimeStamp attribute to the current
     * date
     */
    public Relation delete(Long id) {
        Relation relation = get(id);

        if (relation == null)
            throw new ApplicationException(String.format("Relation [id: %s] not found", id),
                    new NoSuchElementException());

        if (relation.getToTimeStamp() != null)
            throw new ApplicationException(String.format("Relation [id: %d] has already been deleted", id),
                    new NoSuchElementException());

        relation.setToTimeStamp(new java.util.Date());
        relation.setUpdateTimeStamp(new java.util.Date());

        try {
            logger.debug("Deleting relation [id: {}, version: {}]",
                    new Object[] { relation.getId(), relation.getVersion() });

            relation = (Relation) getSession().merge("Relation", relation);
        } catch (StaleStateException e) {
            throw new ApplicationException(String.format(
                    "Deletion stale relation [id: %s] which means newer version exists.", relation.getId()), e);
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }

        logger.info("Deleted relation [id: {}]", new Object[] { relation.getId() });
        return relation;
    }

    /**
     * Deletion of an element's relations (both source and destination).
     * DML-style operation written directly in HQL quickens the update process.
     * 
     * @param id
     */
    public int cascade(Long id) {
        return cascade(id, true, true);
    }

    /**
     * Deletion of an element's relations
     * 
     * @param id
     * @param source
     * @param destination
     * @return
     */
    public int cascade(Long id, boolean source, boolean destination) {
        int count = 0;

        try {
            if (source) {
                int results = getSession().createQuery(
                        "update Relation r set r.toTimeStamp = current_timestamp() where r.source.id = :sourceId and r.toTimeStamp is null")
                        .setLong("sourceId", id).executeUpdate();

                count = count + results;
                logger.info("Deleted {}  relations with source [id: {}]", results, id);
            }

            if (destination) {
                int results = getSession().createQuery(
                        "update Relation r set r.toTimeStamp = current_timestamp() where r.destination.id = :destinationId and r.toTimeStamp is null")
                        .setLong("destinationId", id).executeUpdate();

                count = count + results;
                logger.info("Deleted {} relations with destination [id: {}]", results, id);
            }
        } catch (StaleStateException e) {
            throw new ApplicationException("Cascade deletion of stale entities which means newer version exists.",
                    e);
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }

        return count;
    }
}