com.htm.taskinstance.jpa.TaskInstanceFactoryJPA.java Source code

Java tutorial

Introduction

Here is the source code for com.htm.taskinstance.jpa.TaskInstanceFactoryJPA.java

Source

/*
 * Copyright 2012 Bangkok Project Team, GRIDSOLUT GmbH + Co.KG, and
 * University of Stuttgart (Institute of Architecture of Application Systems)
 * All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.htm.taskinstance.jpa;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.List;
import java.util.Set;

import javax.xml.datatype.Duration;

import org.apache.log4j.Logger;

import com.htm.db.IDataAccessProvider;
import com.htm.entities.WrappableEntity;
import com.htm.entities.jpa.Assigneduser;
import com.htm.entities.jpa.Attachment;
import com.htm.entities.jpa.Callbackcorrelationproperty;
import com.htm.entities.jpa.Humantaskinstance;
import com.htm.exceptions.DatabaseException;
import com.htm.exceptions.HumanTaskManagerException;
import com.htm.exceptions.IllegalArgumentException;
import com.htm.exceptions.UserException;
import com.htm.query.IQuery;
import com.htm.query.IQueryEvaluator;
import com.htm.query.jxpath.XPathQueryImpl;
import com.htm.query.jxpath.XPathUtils;
import com.htm.taskinstance.IAssignedUser;
import com.htm.taskinstance.IAttachment;
import com.htm.taskinstance.ICorrelationProperty;
import com.htm.taskinstance.IFault;
import com.htm.taskinstance.ITaskInstance;
import com.htm.taskinstance.TaskInstanceFactory;
import com.htm.taskmodel.IPresentationModel;
import com.htm.taskmodel.ITaskModel;
import com.htm.utils.Utilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class TaskInstanceFactoryJPA extends TaskInstanceFactory {

    public static final short PRIORITY_DEFAULT = 0;

    public static final boolean SKIPABLE_DEFAULT = false;

    private IQueryEvaluator queryEval;

    private Logger log = Utilities.getLogger(this.getClass());

    @Autowired
    private IDataAccessProvider dataAccessProvider;

    public TaskInstanceFactoryJPA() {

    }

    @Override
    public ITaskInstance createTaskInstance(String taskModelName, String taskInstanceName, Object input,
            String taskParentId, Set<ICorrelationProperty> correlationProperties, Timestamp expirationTime)
            throws HumanTaskManagerException {

        /*
           * Naturally the underlying task model is required to instantiate the
           * task
           */
        ITaskModel taskModel = dataAccessProvider.getHumanTaskModel(taskModelName);

        if (taskModel == null) {
            String errorMsg = "No task model with the name '" + taskModelName + "' could be found.";
            log.error(errorMsg);
            throw new UserException(errorMsg);
        }

        /* Task instance is automatically set to the state CREATED */
        ITaskInstance taskInstance = new TaskInstanceWrapper(taskInstanceName);

        taskInstance.setTaskModel(taskModel);
        taskInstance.setName(taskInstanceName);

        /* Set the createdOn field with the current time */
        taskInstance.setCreatedOn(new Timestamp(Calendar.getInstance().getTimeInMillis()));

        taskInstance.setExpirationTime(expirationTime);

        /*
           * The order of setting the values is important since some queries base
           * on values of other properties. E.g. priority queries base on input
           * data thus input data have to be set before.
           */

        /* Input data passed by the task parent */
        taskInstance.setInputData(input);

        /* Set properties required for task parent callback */
        taskInstance.setTaskParentId(taskParentId);
        taskInstance.setCorrelationProperties(correlationProperties);

        /* The priority */
        taskInstance.setPriority(evaluatePriorityQuery(taskModel.getPriority(), taskInstance));

        /* Evaluate whether the task is skipable or not */
        taskInstance.setSkipable(evaluateSkipableQuery(taskModel.getSkipable(), taskInstance));

        evaluatePositionQueries(taskModel, taskInstance);

        evaluateDurationQueries(taskModel, taskInstance);

        /* Set and evaluate deadlines */
        Timestamp startBy = evaluateTimestampQuery(taskModel.getStartBy(), taskInstance);
        if (startBy != null) {
            log.debug("Result of StartBy query : " + startBy);
            taskInstance.setStartBy(startBy);
        }
        Timestamp completeBy = evaluateTimestampQuery(taskModel.getCompleteBy(), taskInstance);
        // TODO
        if (completeBy != null) {
            log.debug("Result of CompleteBy query : " + completeBy);
            taskInstance.setCompleteBy(completeBy);
        }

        /*
           * Set presentation properties (title, subject, description) TODO
           * Queries in presentation models have to be supported TODO Criteria
           * have to be added to select appropriate presentation model
           */
        IPresentationModel presentModel = taskModel.getPresentationModel();

        if (presentModel != null) {
            taskInstance.setPresentationTitle(presentModel.getTitle());
            taskInstance.setPresentationSubject(presentModel.getSubject());
            taskInstance.setPresentationDescription(presentModel.getDescription());
        }

        return taskInstance;
    }

    protected void evaluatePositionQueries(ITaskModel taskModel, ITaskInstance taskInstance) {
        /* The position X */
        try {
            log.debug("Evaluating position X");
            taskInstance.setPostionX(evaluateXPath(Double.class, taskModel.getPositionX(), taskInstance));

            /* The position Y */
            taskInstance.setPostionY(evaluateXPath(Double.class, taskModel.getPositionY(), taskInstance));
        } catch (IllegalArgumentException e) {
            // TODO default value from configuration
            log.error("Cannot evaluate position queries. Setting default value", e);
            taskInstance.setPostionX(null);
            taskInstance.setPostionY(null);
        }
    }

    protected void evaluateDurationQueries(ITaskModel taskModel, ITaskInstance taskInstance) {

        log.debug("Evaluating duration queries");

        /* Duration Min */
        Duration min;
        try {
            min = evaluateXPath(Duration.class, taskModel.getDurationMin(), taskInstance);

            if (min != null) {
                taskInstance.setDurationMin(min.getTimeInMillis(Calendar.getInstance()));
            }

        } catch (IllegalArgumentException e) {
            // TODO default value from configuration
            log.error("Cannot evaluate min duration. Setting default value", e);
        }

        /* Duration Avg */
        try {
            Duration avg = evaluateXPath(Duration.class, taskModel.getDurationAvg(), taskInstance);
            if (avg != null) {
                taskInstance.setDurationAvg(avg.getTimeInMillis(Calendar.getInstance()));
            }
        } catch (IllegalArgumentException e) {
            // TODO default value from configuration
            log.error("Cannot evaluate avg duration. Setting default value", e);
        }

        /* Duration Max */
        try {
            Duration max = evaluateXPath(Duration.class, taskModel.getDurationMax(), taskInstance);
            if (max != null) {
                taskInstance.setDurationMax(max.getTimeInMillis(Calendar.getInstance()));
            }
        } catch (IllegalArgumentException e) {
            // TODO default value from configuration
            log.error("Cannot evaluate max duration. Setting default value", e);
        }
    }

    protected int evaluatePriorityQuery(IQuery query, Object context)
            throws com.htm.exceptions.IllegalArgumentException {

        /* Query can be null since the priority query is optional */
        if (query != null) {
            // List<?> priority = evaluateXPath(query, context);
            //
            // /*
            // * Obviously exactly one value is expected for priority and it
            // must
            // * be a number represented as string.
            // */
            // if (priority.size() == 1 && priority.get(0) instanceof String) {
            // String priorityAsString = (String) priority.get(0);
            // log.debug("Evaluating priority query - Determined value is '"
            // + priorityAsString + "'. "
            // + "Try to create integer from this value.");
            // return Integer.valueOf(priorityAsString);
            // } else {
            // log.debug("Evaluating priority query -  No value could be determined during evaluation.");
            // }

            // XPATH Number by default is mapped to Double
            int priority;
            Double tmpPriority;
            try {
                tmpPriority = evaluateXPath(Double.class, query, context);
                if (tmpPriority != null) {
                    priority = tmpPriority.intValue();
                } else {
                    log.debug("priority is null - Default priority value '" + PRIORITY_DEFAULT + "' is used.");
                    priority = PRIORITY_DEFAULT;
                }

                log.debug("Evaluating priority query - Determined value is '" + priority + "'.");
            } catch (com.htm.exceptions.IllegalArgumentException e) {
                log.error("Cannot evaluate priority query - Default priority value '" + PRIORITY_DEFAULT
                        + "' is used.", e);
                priority = PRIORITY_DEFAULT;
            }
            return priority;
        } else {
            log.debug("Evaluating priority query - No priority query was specified");
        }

        log.debug("Evaluating priority query - Default priority value '" + PRIORITY_DEFAULT + "' is used.");
        /*
           * If the query has failed for some reason return the default value for
           * priority
           */
        return PRIORITY_DEFAULT;
    }

    protected boolean evaluateSkipableQuery(IQuery query, Object context)
            throws com.htm.exceptions.IllegalArgumentException {

        /* Query can be null since the skipable query is optional */
        if (query != null) {
            // List<?> skipable = evaluateXPath(query, context);

            // /*
            // * Obviously exactly one value is expected for priority and it
            // must
            // * be a boolean represented as string
            // */
            // if (skipable.size() == 1 && skipable.get(0) instanceof String) {
            // String skipableAsString = (String) skipable.get(0);
            // log.debug("Evaluating skipable query - Determined value is '"
            // + skipableAsString + "'. "
            // + "Try to create boolean from this value.");
            // return Boolean.valueOf(skipableAsString);
            // } else {
            // log.debug("Evaluating skipable query -  No value could be found.");
            // }

            Boolean skipable;
            try {

                skipable = evaluateXPath(Boolean.class, query, context);
                if (skipable == null) {
                    log.debug("skipable is null - Default priority value '" + SKIPABLE_DEFAULT + "' is used.");
                    skipable = SKIPABLE_DEFAULT;
                }
                log.debug("Evaluating skipable query - Determined value is '" + skipable + "'");
            } catch (com.htm.exceptions.IllegalArgumentException e) {
                log.error("Cannot evaluate skipable query - Default priority value '" + SKIPABLE_DEFAULT
                        + "' is used.", e);
                skipable = SKIPABLE_DEFAULT;
            }
            return skipable;

        } else {
            log.debug("Evaluating skipable query - No skipable query was specified");
        }

        log.debug("Evaluating skipable query - Default skipable value '" + SKIPABLE_DEFAULT + "' is used.");
        /*
           * If the query has failed for some reason return the default value for
           * skipable
           */
        return SKIPABLE_DEFAULT;
    }

    protected Timestamp evaluateTimestampQuery(IQuery query, Object context)
            throws com.htm.exceptions.IllegalArgumentException {
        /* Query can be null since all timestamp queries are optional */
        if (query != null) {
            // List<?> timestamp = evaluateXPath(query, context);
            //
            // /*
            // * Obviously exactly one value is expected for a timestamp. It
            // must
            // * be a long integer (the time in millis) which is always
            // * represented by a String
            // */
            // if (timestamp.size() == 1 && timestamp.get(0) instanceof String)
            // {
            // String longIntegerAsString = (String) timestamp.get(0);
            // log.debug("Evaluating timestamp query - Determined value is '"
            // + timestamp.get(0)
            // + "'. Try to create timestamp from this value.");
            //
            // return new Timestamp(new Long(longIntegerAsString));

            // } else {
            // log.debug("Evaluating timestamp query - "
            // + "No value could be found for creating a timestamp.");
            // }
            Timestamp timestamp;
            boolean durationQuery = false;
            XPathQueryImpl xpathQuery;
            try {
                if (query instanceof XPathQueryImpl) {
                    xpathQuery = (XPathQueryImpl) query;
                    durationQuery = xpathQuery.isDurationQuery();
                }
                if (durationQuery) {
                    log.debug("Determing timestamp from duration.");
                    Duration duration = evaluateXPath(Duration.class, query, context);
                    try {
                        timestamp = XPathUtils.getTimestampFromDuration(duration);
                    } catch (Exception e) {
                        log.error(
                                "Cannot evaluate timestamp query - Default priority value '" + null + "' is used.",
                                e);
                        timestamp = null;
                    }
                } else {
                    timestamp = evaluateXPath(Timestamp.class, query, context);
                }
                log.debug("Evaluating timestamp/duration query - Determined value is '" + timestamp + "'");
            } catch (com.htm.exceptions.IllegalArgumentException e) {
                log.error("Cannot evaluate timestamp query - Default priority value '" + null + "' is used.", e);
                timestamp = null;
            }
            return timestamp;
        } else {
            log.debug("Evaluating timestamp query - " + "No query was specified for creating a timestamp.");
        }
        return null;
    }

    protected List<?> evaluateXPath(IQuery query, Object context)
            throws com.htm.exceptions.IllegalArgumentException {

        /* Only instantiate the query evaluator once */
        if (this.queryEval == null) {
            this.queryEval = IQueryEvaluator.Factory.newInstance(query.getQueryLanguage(), (ITaskInstance) context);
        }

        return queryEval.evaluateQuery(query);

    }

    protected <T> T evaluateXPath(Class<T> resultClass, IQuery query, Object context)
            throws com.htm.exceptions.IllegalArgumentException {
        log.debug("evaluateXPath with defined ResultClass (" + resultClass + ")");
        if (query == null) {
            log.debug("Evaluating query - No query was specified");
            return null;
        }
        List<?> resultList = evaluateXPath(query, context);
        if (resultList.size() > 0) {
            try {
                return XPathUtils.getResultByType(resultClass, resultList.get(0));
            } catch (Exception e) {
                throw new com.htm.exceptions.IllegalArgumentException(e);
            }
        }
        return null;
    }

    @Override
    public ITaskInstance createTaskInstanceFromEntity(WrappableEntity taskInstanceObject) {

        return Utilities.createTaskInstanceFromEntity(taskInstanceObject);

    }

    @Override
    public IAssignedUser createAssignedUserFromEntity(WrappableEntity assignedUserObject) {

        return Utilities.createAssignedUserFromEntity(assignedUserObject);
    }

    @Override
    public IAttachment createAttachmentFromEntity(WrappableEntity attachmentObject) {
        return Utilities.createAttachmentFromEntity(attachmentObject);

    }

    @Override
    public ICorrelationProperty createCorrelationPropertyFromEntity(WrappableEntity correlationPropsObject) {
        return Utilities.createCorrelationPropertyFromEntity(correlationPropsObject);

    }

    @Override
    public IAttachment createAttachment(String name) {
        return new AttachmentWrapper(name);
    }

    @Override
    public IAssignedUser createAssignedUser(String userId) throws DatabaseException {
        /*
           * Since assigned users must be unique within the database it is checked
           * if the assigned user already exists within the database
           */
        IAssignedUser assignedUser = this.dataAccessProvider.getAssignedUser(userId);
        if (assignedUser != null) {
            return assignedUser;
        }
        /* Assigned user does not exist and is created */
        return new AssignedUserWrapper(userId);

    }

    @Override
    public ICorrelationProperty createCorrelationProperty(String name) {
        return new CorrelationPropertiesWrapper(name);
    }

    @Override
    public IFault createFault(String name, Object faultData) {
        return Utilities.createFault(name, faultData);

    }

    @Override
    public void evaluateQueryProperties(String tiid, String taskModelName) {
        log.debug("Evaluating query properties - tiid '" + tiid + "'");
        try {
            ITaskModel model = dataAccessProvider.getHumanTaskModel(taskModelName);
            ITaskInstance instance = dataAccessProvider.getTaskInstance(tiid);
            IQuery queryProperty1 = model.getQueryProperty1();
            if (queryProperty1 != null) {
                log.debug("Query Property 1: " + queryProperty1.getQuery());
                String queryProperty1String;
                try {
                    queryProperty1String = evaluateXPath(String.class, queryProperty1, instance);
                    log.debug("Evaluating query property 1 - Determined value is '" + queryProperty1String + "'.");
                    instance.setQueryProperty1(queryProperty1String);
                    instance.setQueryProperty1Name(model.getQueryProperty1Name());
                } catch (com.htm.exceptions.IllegalArgumentException e) {
                    log.error("Cannot evaluate query property 1 - Default value '" + null + "' is used.", e);

                }
            } else {
                log.debug("Evaluating query property 1 - No query was specified");
            }

            IQuery queryProperty2 = model.getQueryProperty2();
            if (queryProperty2 != null) {
                log.debug("Query Property 2: " + queryProperty2.getQuery());
                String queryProperty2String;
                try {
                    queryProperty2String = evaluateXPath(String.class, queryProperty2, instance);
                    log.debug("Evaluating query property 2 - Determined value is '" + queryProperty2String + "'.");
                    instance.setQueryProperty2(queryProperty2String);
                    instance.setQueryProperty2Name(model.getQueryProperty2Name());
                } catch (com.htm.exceptions.IllegalArgumentException e) {
                    log.error("Cannot evaluate query property 2 - Default value '" + null + "' is used.", e);

                }

            } else {
                log.debug("Evaluating query property 3 - No query was specified");
            }

            IQuery queryProperty3 = model.getQueryProperty3();
            if (queryProperty3 != null) {
                log.debug("Query Property 3: " + queryProperty3.getQuery());
                Double queryProperty3Double;
                try {
                    queryProperty3Double = evaluateXPath(Double.class, queryProperty3, instance);
                    log.debug("Evaluating query property 3 - Determined value is '" + queryProperty3Double + "'.");
                    instance.setQueryProperty3(queryProperty3Double);
                    instance.setQueryProperty3Name(model.getQueryProperty3Name());
                } catch (com.htm.exceptions.IllegalArgumentException e) {
                    log.error("Cannot evaluate query property 3 - Default value '" + null + "' is used.", e);

                }

            } else {
                log.debug("Evaluating query property 3 - No query was specified");
            }

            IQuery queryProperty4 = model.getQueryProperty4();
            if (queryProperty4 != null) {
                log.debug("Query Property 4: " + queryProperty4.getQuery());
                Double queryProperty4Double;
                try {
                    queryProperty4Double = evaluateXPath(Double.class, queryProperty4, instance);
                    log.debug("Evaluating query property 4 - Determined value is '" + queryProperty4Double + "'.");
                    instance.setQueryProperty4(queryProperty4Double);
                    instance.setQueryProperty4Name(model.getQueryProperty4Name());
                } catch (com.htm.exceptions.IllegalArgumentException e) {
                    log.error("Cannot evaluate query property 4 - Default value '" + null + "' is used.", e);

                }

            } else {
                log.debug("Evaluating query property 4 - No query was specified");
            }

        } catch (DatabaseException e) {
            log.error("Cannot fetch task model or instance (tiid='" + tiid + "')", e);
        }

    }

}