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

Java tutorial

Introduction

Here is the source code for com.klistret.cmdb.dao.ElementDAOImpl.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.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.StaleStateException;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

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

/**
 * 
 * @author Matthew Young
 * 
 */
public class ElementDAOImpl extends BaseImpl implements ElementDAO {

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

    /**
     * Necessary to use the Projections to limit the selected columns to only
     * those defined to the Element tables (otherwise the returned columns
     * contains all columns for all associations).
     * 
     * @see com.klistret.cmdb.dao.ElementDAO.findByCriteria
     * @return Collection
     */
    public List<Element> find(List<String> expressions, int start, int limit) {
        try {
            logger.debug("Finding elements by expression from start position [{}] with limit [{}] for session [{}]",
                    new Object[] { start, limit, getSession().hashCode() });

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

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

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

            criteria.addOrder(Order.asc("name"));

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

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

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

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

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

                elements.add(element);
            }

            results = null;

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

    /**
     * Does a projection on the result set for the passed criteria.
     * 
     */
    public String aggregate(String projection, List<String> expressions) {
        try {
            logger.debug("Aggregating elements by expression [session: {}]", getSession().hashCode());

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

            XPathCriteria xpc = new XPathCriteria(expressions, getSession());
            Criteria criteria = xpc.getCriteria();

            Projection aggregation = xpc.aggregate(projection);
            criteria.setProjection(aggregation);

            List<?> results = criteria.list();

            if (results.size() == 0)
                return null;

            if (results.get(0) == null)
                return null;

            return results.get(0).toString();
        } catch (StaleStateException e) {
            throw new ApplicationException(
                    "Element(s) aggregated are stale which means newer version exists (Hibernate).");
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Unique get off of XPath expressions
     * 
     */
    public Element unique(List<String> expressions) {
        try {
            logger.debug("Query unique over XPath expressions (session: {})", getSession().hashCode());

            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<Element> results = find(expressions, 0, 1);
            Element element = results.get(0);

            logger.debug("Returning unique element [id: {}, name: {}, version: {}, session: {}]", new Object[] {
                    element.getId(), element.getName(), element.getVersion(), getSession().hashCode() });
            return element;
        } catch (StaleStateException e) {
            throw new ApplicationException("Unique element 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 [session: {}]", getSession().hashCode());

            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(
                    "Element(s) counted are stale which means newer version exists (Hibernate).");
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }
    }

    /**
     * Another proxy (shallow copy of the object) is returned to avoid Hibernate
     * lazy exceptions in the RestEasy layer. A generic approach to transferring
     * properties would be better/safer to mapping/POJO changes.
     * 
     * @param id
     * @return Element
     */
    public Element get(Long id) {
        try {
            logger.debug("Getting element [id: {}] by id [session: {}]", id, getSession().hashCode());

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

            Element element = (Element) criteria.uniqueResult();

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

            logger.debug("Returning element by id [id: {}, name: {}, version: {}, session: {}]", new Object[] {
                    element.getId(), element.getName(), element.getVersion(), getSession().hashCode() });

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

    /**
     * Set is a save/update call to Hibernate which only looks at the ID to
     * determine if the object is currently persisted or not.
     * 
     * @param Element
     * @return Element
     */
    public Element set(Element element) {
        /**
         * Validate length of name field
         */
        if (element.getName().length() > 100)
            throw new ApplicationException(
                    String.format("Element name [%s] greater than 100 characters [length: %d]", element.getName(),
                            element.getName().length()));

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

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

        try {
            logger.debug("Setting element [id: {}, name: {}, version: {}, session: {}]", new Object[] {
                    element.getId(), element.getName(), element.getVersion(), getSession().hashCode() });

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

        logger.info("Saved/updated element [id: {}, name: {}, session: {}]",
                new Object[] { element.getId(), element.getName(), getSession().hashCode() });
        return element;
    }

    /**
     * Delete an element by setting the ToTimeStamp attribute to the current
     * date.
     */
    public Element delete(Long id) {
        Element element = get(id);

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

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

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

        try {
            logger.debug("Deleting element [id: {}, name: {}, version: {}, session: {}]", new Object[] {
                    element.getId(), element.getName(), element.getVersion(), getSession().hashCode() });

            element = (Element) getSession().merge("Element", element);
        } catch (StaleStateException e) {
            throw new ApplicationException(String.format(
                    "Deleted element [id: %s, name: %s, version: %s] is stale which means newer version exists (Hibernate).",
                    element.getId(), element.getName(), element.getVersion()), e);
        } catch (HibernateException e) {
            throw new InfrastructureException(e.getMessage(), e);
        }

        logger.info("Deleted element [id: {}, name: {}, session: {}]",
                new Object[] { element.getId(), element.getName(), getSession().hashCode() });
        return element;
    }
}