ru.codeinside.gses.manager.ManagerService.java Source code

Java tutorial

Introduction

Here is the source code for ru.codeinside.gses.manager.ManagerService.java

Source

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * Copyright (c) 2013, MPL CodeInside http://codeinside.ru
 */

package ru.codeinside.gses.manager;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.vaadin.addon.jpacontainer.filter.util.AdvancedFilterableSupport;
import com.vaadin.data.Container;
import com.vaadin.data.util.filter.Between;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.data.util.filter.SimpleStringFilter;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.lang.StringUtils;
import ru.codeinside.adm.database.DefinitionStatus;
import ru.codeinside.adm.database.Employee;
import ru.codeinside.adm.database.Procedure;
import ru.codeinside.adm.database.ProcedureProcessDefinition;
import ru.codeinside.adm.database.ProcedureType;
import ru.codeinside.adm.database.Service;
import ru.codeinside.adm.parser.ServiceFixtureParser;
import ru.codeinside.gses.webui.Flash;

import javax.ejb.DependsOn;
import javax.ejb.EJBException;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionManagement;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

@TransactionManagement
@TransactionAttribute
@Singleton
@DependsOn("BaseBean")
@Lock(LockType.READ)
public class ManagerService {

    @PersistenceContext(unitName = "myPU")
    EntityManager em;

    /**
     * ! ?  ? ? ??!
     */
    transient static ManagerService instance;

    public static ManagerService get() {
        if (instance == null) {

            throw new IllegalStateException("?  ?!");
        }
        return instance;
    }

    public Procedure createProcedure(String name, String description, String serviceId, Long code, String login,
            ProcedureType type) {
        try {
            if (hasProcedureWithSameRegisterCode(code)) {
                throw new RuntimeException(
                        " ?    ??");
            }
            final Procedure procedure = new Procedure();
            mergeProcedure(procedure, name, description, serviceId, code, type);
            procedure.setCreator(em.find(Employee.class, login));
            em.persist(procedure);
            return procedure;
        } catch (EJBException e) {
            final String message;
            if (e.getMessage() != null) {
                message = e.getMessage();
            } else if (e.getCausedByException() != null) {
                message = e.getCausedByException().getMessage();
            } else {
                message = e.getCause() != null ? e.getCause().getMessage() : e.getClass().toString();
            }
            throw new RuntimeException(message);
        }
    }

    private void mergeProcedure(final Procedure procedure, String name, String description, String serviceId,
            Long code, ProcedureType type) {
        procedure.setName(name);
        procedure.setDescription(description);
        if (serviceId != null) {
            procedure.setService(em.find(Service.class, Long.parseLong(serviceId)));
        }
        if (type != null) {
            procedure.setType(type);
        }
        procedure.setRegisterCode(code);
    }

    private boolean hasProcedureWithSameRegisterCode(Long code) {
        if (code == null) {
            return false;
        }
        int countWithCode = em
                .createQuery("select p from Procedure p where p.registerCode=:registerCode ", Procedure.class)
                .setParameter("registerCode", code).getResultList().size();
        return countWithCode != 0;
    }

    private boolean hasServiceWithSameRegisterCode(Long code) {
        if (code == null) {
            return false;
        }
        return em.createQuery("select count(p) from Service p where p.registerCode=:registerCode ", Long.class)
                .setParameter("registerCode", code).getSingleResult() > 0;
    }

    public void updateProcedure(String id, String name, String description, String serviceId, Long code) {
        Procedure procedure = em.find(Procedure.class, Long.parseLong(id));
        if (code != null && !code.equals(procedure.getRegisterCode()) && hasProcedureWithSameRegisterCode(code)) {
            throw new RuntimeException(" ?    ??");
        }
        mergeProcedure(procedure, name, description, serviceId, code, null);
        em.persist(procedure);
    }

    public void updateProcedure(Long id, String name, Long code) {
        Procedure procedure = em.find(Procedure.class, id);
        if (code != null && !code.equals(procedure.getRegisterCode()) && hasProcedureWithSameRegisterCode(code)) {
            throw new RuntimeException(" ?    ??");
        }
        mergeProcedure(procedure, name, procedure.getDescription(), null, code, null);
        em.persist(procedure);
    }

    public List<Procedure> findAllProcedures() {
        TypedQuery<Procedure> query = em.createNamedQuery("findAllProcedures", Procedure.class);
        return query.getResultList();
    }

    public List<Service> findAllServices() {
        TypedQuery<Service> query = em.createNamedQuery("findAllServices", Service.class);
        return query.getResultList();
    }

    public int getProcedureCount() {
        return em.createQuery("select count(p) from Procedure p", Number.class).getSingleResult().intValue();
    }

    public List<Procedure> getProcedures(int start, int count, String[] order, boolean[] asc, ProcedureType type,
            AdvancedFilterableSupport newSender) {
        StringBuilder q = new StringBuilder("select p from Procedure p where p.type=:type");
        Set<Timestamp> timestamps = null;
        if (newSender != null) {
            timestamps = procedureQueryFilters(newSender, q);
        }

        for (int i = 0; i < order.length; i++) {
            if (i == 0) {
                q.append(" order by ");
            } else {
                q.append(", ");
            }
            q.append("p.").append(order[i]).append(asc[i] ? " asc" : " desc");
        }

        if (newSender != null) {
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Procedure.class).setParameter("type", type)
                        .setParameter("value", iterator.next()).setFirstResult(start).setMaxResults(count)
                        .getResultList();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Procedure.class).setParameter("type", type)
                        .setParameter("startValue", next).setParameter("endValue", next1).setFirstResult(start)
                        .setMaxResults(count).getResultList();
            }
        }

        return em.createQuery(q.toString(), Procedure.class).setParameter("type", type).setFirstResult(start)
                .setMaxResults(count).getResultList();
    }

    public List<Procedure> getProceduresByServiceId(Long serviceId, int start, int count, String[] order,
            boolean[] asc, AdvancedFilterableSupport newSender) {
        StringBuilder q = new StringBuilder("select p from Procedure p where p.service.id=:serviceId ");

        Set<Timestamp> timestamps = null;
        if (newSender != null) {
            timestamps = procedureQueryFilters(newSender, q);
        }

        for (int i = 0; i < order.length; i++) {
            if (i == 0) {
                q.append(" order by ");
            } else {
                q.append(", ");
            }
            q.append("p.").append(order[i]).append(asc[i] ? " asc" : " desc");
        }

        if (newSender != null) {
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Procedure.class).setParameter("serviceId", serviceId)
                        .setParameter("value", iterator.next()).setFirstResult(start).setMaxResults(count)
                        .getResultList();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Procedure.class).setParameter("serviceId", serviceId)
                        .setParameter("startValue", next).setParameter("endValue", next1).setFirstResult(start)
                        .setMaxResults(count).getResultList();
            }
        }

        return em.createQuery(q.toString(), Procedure.class).setParameter("serviceId", serviceId)
                .setFirstResult(start).setMaxResults(count).getResultList();
    }

    private Set<Timestamp> procedureQueryFilters(AdvancedFilterableSupport newSender, StringBuilder q) {

        Set result = new HashSet();
        for (Container.Filter filter : newSender.getFilters()) {
            if (filter instanceof Between) {
                String field = ((Between) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Between) filter).getStartValue()).getTime()));
                result.add(new Timestamp(((Date) ((Between) filter).getEndValue()).getTime()));
                q.append(" and p." + field + "  >= :startValue and p." + field + " <= :endValue");
            } else if (filter instanceof Compare.GreaterOrEqual) {
                String field = ((Compare.GreaterOrEqual) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Compare.GreaterOrEqual) filter).getValue()).getTime()));
                q.append(" and p." + field + "  >= :value");
            } else if (filter instanceof Compare.LessOrEqual) {
                String field = ((Compare.LessOrEqual) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Compare.LessOrEqual) filter).getValue()).getTime()));
                q.append(" and p." + field + " <= :value");
            } else {
                String field = ((SimpleStringFilter) filter).getPropertyId().toString();
                String value = ((SimpleStringFilter) filter).getFilterString();
                if (field.equals("name") || field.equals("description") || field.equals("status")
                        || field.equals("version")) {
                    q.append(" and lower(p." + field + ") LIKE '" + value + "%'");
                } else if (field.equals("id")) {
                    if (checkString(value)) {
                        q.append(" and p." + field + " = '" + value + "'");
                    }
                }
            }
        }
        return result;
    }

    private Set<Timestamp> serviceQueryFilters(AdvancedFilterableSupport newSender, StringBuilder q) {

        Set result = new HashSet();
        for (Container.Filter filter : newSender.getFilters()) {
            if (filter instanceof Between) {
                String field = ((Between) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Between) filter).getStartValue()).getTime()));
                result.add(new Timestamp(((Date) ((Between) filter).getEndValue()).getTime()));
                q.append(" where s." + field + "  >= :startValue and s." + field + " <= :endValue");
            } else if (filter instanceof Compare.GreaterOrEqual) {
                String field = ((Compare.GreaterOrEqual) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Compare.GreaterOrEqual) filter).getValue()).getTime()));
                q.append(" where s." + field + "  >= :value");
            } else if (filter instanceof Compare.LessOrEqual) {
                String field = ((Compare.LessOrEqual) filter).getPropertyId().toString();
                result.add(new Timestamp(((Date) ((Compare.LessOrEqual) filter).getValue()).getTime()));
                q.append(" where s." + field + " <= :value");
            } else {
                String field = ((SimpleStringFilter) filter).getPropertyId().toString();
                String value = ((SimpleStringFilter) filter).getFilterString();
                if (field.equals("name")) {
                    q.append(" where lower(s." + field + ") LIKE '" + value + "%'");
                } else if (field.equals("id")) {
                    if (checkString(value)) {
                        q.append(" where s." + field + " = '" + value + "'");
                    }
                }
            }
        }
        return result;
    }

    public boolean checkString(String string) {
        try {
            Integer.parseInt(string);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public int getProcedureCountByServiceId(Long serviceId, AdvancedFilterableSupport newSender) {
        StringBuilder q = new StringBuilder("select count(p) from Procedure p where p.service.id=:serviceId ");

        if (newSender != null) {
            Set<Timestamp> timestamps = procedureQueryFilters(newSender, q);
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Number.class).setParameter("serviceId", serviceId)
                        .setParameter("value", iterator.next()).getSingleResult().intValue();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Number.class).setParameter("serviceId", serviceId)
                        .setParameter("startValue", next).setParameter("endValue", next1).getSingleResult()
                        .intValue();
            }
        }

        return em.createQuery(q.toString(), Number.class).setParameter("serviceId", serviceId).getSingleResult()
                .intValue();
    }

    public int getProcedureCount(ProcedureType type, AdvancedFilterableSupport newSender) {
        StringBuilder q = new StringBuilder("select count(p) from Procedure p where p.type=:type");

        if (newSender != null) {
            Set<Timestamp> timestamps = procedureQueryFilters(newSender, q);
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Number.class).setParameter("type", type)
                        .setParameter("value", iterator.next()).getSingleResult().intValue();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Number.class).setParameter("type", type)
                        .setParameter("startValue", next).setParameter("endValue", next1).getSingleResult()
                        .intValue();
            }
        }

        return em.createQuery(q.toString(), Number.class).setParameter("type", type).getSingleResult().intValue();
    }

    public Procedure getProcedure(String id) {
        return em.createQuery("select p from Procedure p where p.id = :procedureId?", Procedure.class)
                .setParameter("procedureId", Long.parseLong(id)).getSingleResult();
    }

    public int getApServiceCount(AdvancedFilterableSupport newSender) {

        StringBuilder q = new StringBuilder("select count(s) from Service s");

        if (newSender != null) {
            Set<Timestamp> timestamps = serviceQueryFilters(newSender, q);
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Number.class).setParameter("value", iterator.next())
                        .getSingleResult().intValue();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Number.class).setParameter("startValue", next)
                        .setParameter("endValue", next1).getSingleResult().intValue();
            }
        }

        return em.createQuery(q.toString(), Number.class).getSingleResult().intValue();
    }

    public Service getApService(String id) {
        return em.find(Service.class, Long.parseLong(id));
    }

    public List<Service> getApServices(int start, int count, String[] order, boolean[] asc,
            AdvancedFilterableSupport newSender) {
        StringBuilder q = new StringBuilder("select s from Service s");

        Set<Timestamp> timestamps = null;
        if (newSender != null) {
            timestamps = serviceQueryFilters(newSender, q);
        }

        for (int i = 0; i < order.length; i++) {
            if (i == 0) {
                q.append(" order by ");
            } else {
                q.append(", ");
            }
            q.append("s.").append(order[i]).append(asc[i] ? " asc" : " desc");
        }

        if (newSender != null) {
            Iterator<Timestamp> iterator = timestamps.iterator();
            if (timestamps.size() == 1) {
                return em.createQuery(q.toString(), Service.class).setParameter("value", iterator.next())
                        .setFirstResult(start).setMaxResults(count).getResultList();
            } else if (timestamps.size() == 2) {
                Timestamp next = iterator.next();
                Timestamp next1 = iterator.next();
                return em.createQuery(q.toString(), Service.class).setParameter("startValue", next)
                        .setParameter("endValue", next1).setFirstResult(start).setMaxResults(count).getResultList();
            }
        }

        return em.createQuery(q.toString(), Service.class).setFirstResult(start).setMaxResults(count)
                .getResultList();
    }

    public Service createApService(String name, Long code, String login) {
        if (hasServiceWithSameRegisterCode(code)) {
            throw new RuntimeException("? ?    ??");
        }
        Service service = new Service();
        service.setCreator(em.find(Employee.class, login));
        service.setName(name);
        service.setRegisterCode(code);
        em.persist(service);
        return service;
    }

    public long createApService(String name, Long code, String login, List<String> declarantTypes) {
        if (hasServiceWithSameRegisterCode(code)) {
            return 0;
        }
        Service service = new Service();
        service.setCreator(em.find(Employee.class, login));
        service.setName(name);
        service.setRegisterCode(code);
        service.setDeclarantTypes(declarantTypes);
        em.persist(service);
        return service.getId();
    }

    public Boolean updateApservice(String id, String name, Long code, List<String> declarantTypes) {
        Service service = em.find(Service.class, Long.parseLong(id));
        if (code != null && !code.equals(service.getRegisterCode()) && hasServiceWithSameRegisterCode(code)) {
            return true;
        }
        service.setRegisterCode(code);
        service.setName(name);
        service.setDeclarantTypes(declarantTypes);
        em.persist(service);
        return false;
    }

    public Service updateApservice(Long id, String name, Long code) {
        Service service = em.find(Service.class, id);
        if (code != null && !code.equals(service.getRegisterCode()) && hasServiceWithSameRegisterCode(code)) {
            throw new RuntimeException("? ?    ??");
        }
        service.setRegisterCode(code);
        service.setName(name);
        em.persist(service);
        return service;
    }

    public boolean existProcessDefinitionWithKeyOtherProcedure(String procedureId, String key) {
        int count = em.createQuery(
                "select count(e) from procedure_process_definition e where e.procedure.id!=:procedureId and e.processDefinitionKey=:processDefinitionKey and e.child is null ",
                Number.class).setParameter("procedureId", Long.parseLong(procedureId))
                .setParameter("processDefinitionKey", key.trim()).getSingleResult().intValue();
        return count > 0;
    }

    public ProcedureProcessDefinition createProcessDefination(String procedureId,
            ProcessDefinition processDefinition, String login, String processDefId) {
        ProcedureProcessDefinition ppd = new ProcedureProcessDefinition();
        ProcedureProcessDefinition processDefenition = StringUtils.isEmpty(processDefId) ? null
                : getProcessDefenition(processDefId);
        if (StringUtils.isEmpty(processDefId)) {
            Double newVersion = 0.00;
            if (getProcessDefenitionCountByProcedureId(procedureId) > 0) {
                newVersion = em.createQuery(
                        "select max(s.version) from procedure_process_definition s where s.procedure.id=:procedureId",
                        Number.class).setParameter("procedureId", Long.parseLong(procedureId)).getSingleResult()
                        .doubleValue();
            }
            ppd.setVersion(newVersion.intValue() + 1.00);
            ppd.setStatus(DefinitionStatus.Created);
        } else {
            Double version = (processDefenition == null || processDefenition.getVersion() == null) ? 1.00
                    : processDefenition.getVersion();
            ppd.setVersion(version + 0.01);
            ppd.setStatus(DefinitionStatus.Debugging);
        }
        Procedure procedure = getProcedure(procedureId);

        ppd.setProcedure(procedure);
        ppd.setCreator(em.find(Employee.class, login));
        ppd.setProcessDefinitionId(processDefinition.getId());
        ppd.setProcessDefinitionKey(processDefinition.getKey());
        em.persist(ppd);

        if (!StringUtils.isEmpty(processDefId) && processDefenition != null) {
            processDefenition.setStatus(DefinitionStatus.Archive);
            processDefenition.setChild(ppd);
            em.persist(processDefenition);
        }
        updateProcedureStatusAndVersion(procedureId);
        return ppd;
    }

    public boolean updateProcessDefinationStatus(String processDefinitionId, DefinitionStatus newStatus) {
        return updateProcessDefinationStatus(processDefinitionId, newStatus, 0);
    }

    public boolean updateProcessDefinationStatus(String processDefinitionId, DefinitionStatus newStatus,
            int waitOfMinCount) {
        ProcedureProcessDefinition processDefenition = getProcessDefenition(processDefinitionId);
        DefinitionStatus status = processDefenition.getStatus();
        if (!status.getAvailableStatus().contains(newStatus)) {
            return false;
        }
        if (DefinitionStatus.Work.equals(newStatus)) {
            for (ProcedureProcessDefinition ppd : getProcessDefenitionWithStatus(processDefenition,
                    DefinitionStatus.Work)) {
                updateProcessDefinationStatus(ppd.getProcessDefinitionId(), DefinitionStatus.Archive);
            }
        }
        if (DefinitionStatus.Archive.equals(newStatus)) {
            if (Flash.flash().getProcessEngine().getRuntimeService().createProcessInstanceQuery()
                    .processDefinitionId(processDefinitionId).count() > waitOfMinCount) {
                newStatus = DefinitionStatus.PathToArchive;
            }
        }
        processDefenition.setStatus(newStatus);
        em.persist(processDefenition);
        updateProcedureStatusAndVersion(processDefenition.getProcedure().getId());
        return true;
    }

    public void updateProcedureStatusAndVersion(String procedureId) {
        Procedure procedure = getProcedure(procedureId);

        String version = procedure.getVersion();
        String status = procedure.getStatus();

        for (ProcedureProcessDefinition p : getProcessDefenitionsByProcedureId(procedureId, 0, 1,
                new String[] { "status", "version" }, new boolean[] { true, false })) {
            status = p.getStatus().getLabelName();
            version = df.format(p.getVersion());
        }

        procedure.setVersion(version);
        procedure.setStatus(status);
        em.persist(procedure);
    }

    DecimalFormat df = new DecimalFormat("##.00");

    public int getProcessDefenitionCountByProcedureId(String procedureId) {
        return em.createQuery(
                "select count(e) from procedure_process_definition e where e.procedure.id=:procedureId and e.child is null",
                Number.class).setParameter("procedureId", Long.parseLong(procedureId)).getSingleResult().intValue();
    }

    public List<ProcedureProcessDefinition> getProcessDefenitionsByProcedureId(String procedureId, int start,
            int count, String[] order, boolean[] asc) {
        StringBuilder q = new StringBuilder(
                "select s from procedure_process_definition s where s.procedure.id=:procedureId and s.child is null");
        for (int i = 0; i < order.length; i++) {
            if (i == 0) {
                q.append(" order by ");
            } else {
                q.append(", ");
            }
            q.append("s.").append(order[i]).append(asc[i] ? " asc" : " desc");
        }
        return em.createQuery(q.toString(), ProcedureProcessDefinition.class)
                .setParameter("procedureId", Long.parseLong(procedureId)).setFirstResult(start).setMaxResults(count)
                .getResultList();
    }

    public ProcedureProcessDefinition getProcessDefenition(String id) {
        return em.find(ProcedureProcessDefinition.class, id);
    }

    public List<ProcedureProcessDefinition> getProcessDefenitionWithStatus(ProcedureProcessDefinition p,
            DefinitionStatus status) {
        return em.createQuery(
                "select s from procedure_process_definition s where s.procedure.id=:procedureId and s.child is null and s.status=:status",
                ProcedureProcessDefinition.class)
                .setParameter("procedureId", Long.parseLong(p.getProcedure().getId()))
                .setParameter("status", status).getResultList();
    }

    private class ServSearchByIdPredicate implements Predicate<Service> {
        private Long servId;

        public ServSearchByIdPredicate(Long servId) {
            this.servId = servId;
        }

        @Override
        public boolean apply(Service input) {
            return input != null && input.getId().equals(this.servId);
        }
    }

    public void loadServiceData(InputStream data, final String currentUserName) throws IOException {
        Preconditions.checkNotNull(data);
        Preconditions.checkArgument(StringUtils.isNotBlank(currentUserName), "User name is blank");
        ServiceFixtureParser parser = new ServiceFixtureParser();
        //  ?
        final Collection<Service> serviceList = new LinkedList<Service>();
        serviceList.addAll((findAllServices()));
        final Collection<Procedure> procedures = new LinkedList<Procedure>();
        procedures.addAll(findAllProcedures());
        parser.loadFixtures(data, new ServiceFixtureParser.PersistenceCallback() {
            @Override
            public Long onServiceComplete(String srvName, Long regCode) {
                List<Service> searchedSrv = ImmutableList
                        .copyOf(Collections2.filter(serviceList, new ServiceByRegCodePredicate(regCode)));
                Long result;
                if (searchedSrv.size() > 0) {
                    Service service = updateApservice(searchedSrv.get(0).getId(), srvName, regCode);
                    result = service.getId();
                } else {
                    Service service = createApService(srvName, regCode, currentUserName);
                    serviceList.add(service);
                    result = service.getId();
                }
                return result;
            }

            @Override
            public void onProcedureComplete(String name, Long regCode, long servId) {
                List<Service> parentList = ImmutableList
                        .copyOf(Collections2.filter(serviceList, new ServSearchByIdPredicate(servId)));
                Service parent = parentList.size() > 0 ? parentList.get(0) : null;
                if (parent != null) {
                    List<Long> children = em
                            .createQuery("select p.id from Procedure p where p.service.id = :service"
                                    + " and p.registerCode = :regCode", Long.class)
                            .setParameter("service", servId).setParameter("regCode", regCode).getResultList();
                    if (children.size() > 0) {
                        updateProcedure(children.get(0), name, regCode);
                    } else {
                        List<String> list = em
                                .createQuery("select p.name from Procedure p where p.registerCode = :regCode",
                                        String.class)
                                .setParameter("regCode", regCode).getResultList();
                        if (list.size() > 0) {
                            throw new RuntimeException(" ?  " + regCode
                                    + "  ??: " + list.get(0));
                        } else {
                            Procedure procedure = createProcedure(name, null, Long.toString(servId), regCode,
                                    currentUserName, ProcedureType.Administrative);
                            procedures.add(procedure);
                        }
                    }
                } else {
                    throw new IllegalStateException(
                            "?  " + name + "   ?.");
                }

            }
        });
    }

    private class ServiceByRegCodePredicate implements Predicate<Service> {
        private Long regCode;

        public ServiceByRegCodePredicate(Long regCode) {
            this.regCode = regCode;
        }

        @Override
        public boolean apply(Service input) {
            return input != null && input.getRegisterCode() != null && input.getRegisterCode().equals(this.regCode);
        }
    }

}