cz.muni.fi.mir.scheduling.CanonicalizationTask.java Source code

Java tutorial

Introduction

Here is the source code for cz.muni.fi.mir.scheduling.CanonicalizationTask.java

Source

/* 
 * Copyright 2014 MIR@MU.
 *
 * 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 cz.muni.fi.mir.scheduling;

import cz.muni.fi.mir.db.domain.Annotation;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;

import cz.muni.fi.mir.db.domain.ApplicationRun;
import cz.muni.fi.mir.db.domain.CanonicOutput;
import cz.muni.fi.mir.db.domain.Formula;
import cz.muni.fi.mir.db.service.AnnotationService;
import cz.muni.fi.mir.db.service.ApplicationRunService;
import cz.muni.fi.mir.db.service.CanonicOutputService;
import cz.muni.fi.mir.db.service.FormulaService;
import cz.muni.fi.mir.db.service.UserService;
import cz.muni.fi.mir.scheduling.TaskStatus.TaskType;
import cz.muni.fi.mir.services.MailService;
import cz.muni.fi.mir.tools.Tools;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Value;

/**
 * TODO SIMALIRITY FORM CONVERSION
 * TODO BETTER EXCEPTION AND ERROR STATE HANDLING.
 * 
 * @author Dominik Szalai
 * @since 1.0
 * @version 1.0
 */
public class CanonicalizationTask extends ApplicationTask {

    private List<Formula> formulas;
    private ApplicationRun applicationRun;
    private Class mainClass;

    @Value("${annotation.sameoutput}")
    private String sameOutputAnnotation;

    @Autowired
    private CanonicOutputService canonicOutputService;
    @Autowired
    private FormulaService formulaService;
    @Autowired
    private ApplicationRunService applicationRunService;
    @Autowired
    private AnnotationService annotationService;
    @Autowired
    private UserService userService;
    @Autowired
    private MailService mailService;

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

    /**
     * Method setups data dependencies used for CanonicalizationTask.
     *
     * @param formulas List of formulas to be Canonicalized
     * @param applicationRun ApplicationRun under which canonicalization runs
     * @param mainClass Target class of canonicalizer, either local or remote
     * from jar file.
     * @throws IllegalArgumentException if any of input parameter is null, has
     * null id, or List of formulas is empty.
     */
    public void setDependencies(List<Formula> formulas, ApplicationRun applicationRun, Class mainClass)
            throws IllegalArgumentException {
        if (Tools.getInstance().isEmpty(formulas)) {
            throw new IllegalArgumentException("List of formulas is null or contains no formulas.");
        }
        if (applicationRun == null) {
            throw new IllegalArgumentException("ApplicationRun is null");
        }
        if (applicationRun.getId() == null) {
            throw new IllegalArgumentException("ApplicationRun does not have set its id.");
        }
        if (mainClass == null) {
            throw new IllegalArgumentException("Main class is not set. Current value is null.");
        }

        this.formulas = formulas;
        this.applicationRun = applicationRun;
        this.mainClass = mainClass;

        setStatus(new TaskStatus());
        getStatus().setTaskType(TaskType.CANONICALIZATION);
    }

    @Override
    public TaskStatus call() throws IllegalStateException {
        String message = "";
        message += "formulas isSet? [" + (formulas != null) + "], ";
        message += "applicationrun isSet? [" + (applicationRun != null) + "], ";
        message += "mainClass isSet? [" + (mainClass != null) + "].";

        logger.info(message);
        logger.info(applicationRun);
        if (formulas == null || formulas.isEmpty() || applicationRun == null || mainClass == null) {
            throw new IllegalStateException(message);
        } else {
            Constructor constructor = null;
            Method canonicalize = null;
            Object canonicalizer = null;
            getStatus().setTotal(formulas.size());
            getStatus().setCurrent(0);
            getStatus().setUser(applicationRun.getUser());
            getStatus().setNote(String.valueOf(applicationRun.getId()));
            try {
                constructor = this.mainClass.getConstructor(InputStream.class);
                canonicalize = this.mainClass.getMethod("canonicalize", InputStream.class, OutputStream.class);
            } catch (NoSuchMethodException | SecurityException ex) {
                logger.fatal(ex);
            }

            InputStream config = new ByteArrayInputStream(applicationRun.getConfiguration().getConfig().getBytes());
            if (constructor != null) {
                try {
                    canonicalizer = constructor.newInstance(config);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
                        | InstantiationException ex) {
                    logger.fatal(ex);
                }

                DateTime startTime = DateTime.now();
                getStatus().setStartTime(startTime);
                applicationRun.setStartTime(startTime);
                for (Formula f : formulas) {
                    CanonicOutput co = canonicalize(f, canonicalizer, canonicalize, applicationRun);
                    co.setHashValue(Tools.getInstance().SHA1(co.getOutputForm()));

                    f.getOutputs().add(co);

                    List<Formula> sameHashFormulas = formulaService
                            .getFormulasByCanonicOutputHash(co.getHashValue());

                    logger.info(sameHashFormulas);

                    if (!sameHashFormulas.isEmpty()) {
                        for (Formula shf : sameHashFormulas) {
                            if (shf.equals(f)) {
                                sameHashFormulas.remove(f);
                                break;
                            }
                        }
                        if (!sameHashFormulas.isEmpty()) {
                            Annotation a = new Annotation();
                            a.setUser(userService.getSystemUser());
                            StringBuilder sb = new StringBuilder();
                            sb.append(sameOutputAnnotation).append(" [");
                            for (Formula shf : sameHashFormulas) {
                                sb.append(shf.getId()).append(", ");
                            }
                            sb.append("]");
                            a.setAnnotationContent(sb.toString());

                            annotationService.createAnnotation(a);

                            co.setAnnotations(Arrays.asList(a));

                            List<Formula> parents = new ArrayList<>(co.getParents());
                            parents.addAll(sameHashFormulas);
                            co.setParents(parents);
                        } else {
                            logger.info("No same matches found for canonic output [" + co.getHashValue() + "]");
                        }
                    }

                    canonicOutputService.createCanonicOutput(co);

                    formulaService.updateFormula(f);

                    logger.info(String.format("Formula %d canonicalized.", f.getId()));
                    getStatus().setCurrent(getStatus().getCurrent() + 1);
                }

                DateTime stopTime = DateTime.now();
                getStatus().setStopTime(stopTime);
                applicationRun.setStopTime(stopTime);
                applicationRunService.updateApplicationRun(applicationRun);

                String mailMessage = "Canonicalization started at %s has finished. The running time was "
                        + " %s ms and %d formulas were canonicalized. Task finished at %s";

                mailService.sendMail(null, applicationRun.getUser().getEmail(), "Canonicalization has finished.",
                        String.format(mailMessage, applicationRun.getStartTime().toString(),
                                (applicationRun.getStopTime().getMillis()
                                        - applicationRun.getStartTime().getMillis()),
                                formulas.size(), applicationRun.getStopTime().toString()));
            }
            return getStatus();
        }
    }

    /**
     * Method creates CanonicOutput out of given formula. For proper
     * canonicalization we need input formula, already instantiated
     * Canonicalizer via reflection, main method obtained via reflection and
     * ApplicationRun under which canonicalization task runs.
     *
     * @param f formula to be canonicalized
     * @param canonicalizer instance of Canonicalizer
     * @param canonicalize main method
     * @param applicationRun under which task runs
     * @return Canonic Output based on given formula.
     */
    private CanonicOutput canonicalize(Formula f, Object canonicalizer, Method canonicalize,
            ApplicationRun applicationRun) {
        InputStream input = new ByteArrayInputStream(f.getXml().getBytes());
        OutputStream output = new ByteArrayOutputStream();
        CanonicOutput co = new CanonicOutput();
        long start = System.currentTimeMillis();
        try {
            canonicalize.invoke(canonicalizer, input, output);
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            logger.fatal(ex);
        }

        co.setApplicationRun(applicationRun);
        co.setOutputForm(output.toString());
        //canonicOutput.setSimilarForm(similarityFormConverter.convert(canonicOutput.getOutputForm()));
        co.setRunningTime(System.currentTimeMillis() - start);
        co.setParents(Arrays.asList(f));

        return co;
    }

}