From fa310807db9bdaa6c590e2f8d1acbc935bf41a3b Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:01:34 +0100 Subject: [PATCH 01/91] Tim-connector: DAO for AppProperties DAO for AppProperties. Implementation of the interface IAppPropertiesDAO --- .../common/daos/AppPropertiesDAO.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/daos/AppPropertiesDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/daos/AppPropertiesDAO.java b/libreplan-business/src/main/java/org/libreplan/business/common/daos/AppPropertiesDAO.java new file mode 100644 index 000000000..f97c41292 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/daos/AppPropertiesDAO.java @@ -0,0 +1,76 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.daos; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.hibernate.Criteria; +import org.hibernate.criterion.Restrictions; +import org.libreplan.business.common.entities.AppProperties; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * DAO for {@link AppProperties} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class AppPropertiesDAO extends GenericDAOHibernate + implements IAppPropertiesDAO { + + @Override + @Transactional(readOnly = true) + public List getAll() { + return list(AppProperties.class); + } + + @Override + @Transactional(readOnly = true) + @SuppressWarnings("unchecked") + public Map findByMajorId(String majorId) { + Criteria c = getSession().createCriteria(AppProperties.class).add( + Restrictions.eq("majorId", majorId)); + List list = c.list(); + + Map map = new HashMap(); + for (AppProperties appProperty : list) { + map.put(appProperty.getPropertyName(), + appProperty.getPropertyValue()); + } + return map; + + } + + @Override + @Transactional(readOnly = true) + public AppProperties findByMajorIdAndName(String majorId, String proprtyName) { + return (AppProperties) getSession().createCriteria(AppProperties.class) + .add(Restrictions.eq("majorId", majorId)) + .add(Restrictions.eq("propertyName", proprtyName)) + .uniqueResult(); + } + +} From 3ba555853ff55178f7f52315f8ad90032eddbc18 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:06:11 +0100 Subject: [PATCH 02/91] Tim-connector: Contract for AppPropertiesDAO An interface that AppPropertiesDAO implements --- .../common/daos/IAppPropertiesDAO.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/daos/IAppPropertiesDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/daos/IAppPropertiesDAO.java b/libreplan-business/src/main/java/org/libreplan/business/common/daos/IAppPropertiesDAO.java new file mode 100644 index 000000000..862d73a6a --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/daos/IAppPropertiesDAO.java @@ -0,0 +1,40 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.daos; + +import java.util.List; +import java.util.Map; + +import org.libreplan.business.common.entities.AppProperties; + +/** + * Contract for {@link AppPropertiesDAO} + * + * @author Miciele Ghiorghis + */ +public interface IAppPropertiesDAO extends IGenericDAO { + + List getAll(); + + Map findByMajorId(String majorId); + + AppProperties findByMajorIdAndName(String majorId, String proprtyName); + +} From 5418fc21b016a1740a679e94d4abe58da4c5c49b Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:08:41 +0100 Subject: [PATCH 03/91] Tim-connector: Contract for JobSchedulerConfigurationDAO An interface that JobSchedulerConfigurationDAO implements --- .../daos/IJobSchedulerConfigurationDAO.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/daos/IJobSchedulerConfigurationDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/daos/IJobSchedulerConfigurationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/common/daos/IJobSchedulerConfigurationDAO.java new file mode 100644 index 000000000..32b6291e5 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/daos/IJobSchedulerConfigurationDAO.java @@ -0,0 +1,38 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.daos; + +import java.util.List; + +import org.libreplan.business.common.entities.JobSchedulerConfiguration; + +/** + * Contract for {@link JobSchedulerConfigurationDAO} + * + * @author Miciele Ghiorghis + */ +public interface IJobSchedulerConfigurationDAO extends + IGenericDAO { + + List getAll(); + + JobSchedulerConfiguration findByJobGroupAndJobName(String jobGroup, + String jobName); +} From f985a65a94d026a07eefcd429f473e79388348a9 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:10:29 +0100 Subject: [PATCH 04/91] Tim-connector: DAO for JobSchedulerConfiguration An implementation of IJobSchedulerConfigurationDAO --- .../daos/JobSchedulerConfigurationDAO.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/daos/JobSchedulerConfigurationDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/daos/JobSchedulerConfigurationDAO.java b/libreplan-business/src/main/java/org/libreplan/business/common/daos/JobSchedulerConfigurationDAO.java new file mode 100644 index 000000000..aa812251f --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/daos/JobSchedulerConfigurationDAO.java @@ -0,0 +1,58 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.daos; + +import java.util.List; + +import org.hibernate.criterion.Restrictions; +import org.libreplan.business.common.entities.JobSchedulerConfiguration; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * DAO for {@link JobSchedulerConfiguration} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class JobSchedulerConfigurationDAO extends + GenericDAOHibernate implements + IJobSchedulerConfigurationDAO { + + @Override + @Transactional(readOnly = true) + public List getAll() { + return list(JobSchedulerConfiguration.class); + } + + @Override + @Transactional(readOnly = true) + public JobSchedulerConfiguration findByJobGroupAndJobName(String jobGroup, + String jobName) { + return (JobSchedulerConfiguration) getSession() + .createCriteria(JobSchedulerConfiguration.class) + .add(Restrictions.eq("jobGroup", jobGroup)) + .add(Restrictions.eq("jobName", jobName)).uniqueResult(); + } + +} From ed26857809c793423e897071b67e38f30898a6b7 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:11:41 +0100 Subject: [PATCH 05/91] Tim-connector: AppProperties entity --- .../common/entities/AppProperties.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/entities/AppProperties.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/entities/AppProperties.java b/libreplan-business/src/main/java/org/libreplan/business/common/entities/AppProperties.java new file mode 100644 index 000000000..9613ec7e7 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/entities/AppProperties.java @@ -0,0 +1,71 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.entities; + +import org.libreplan.business.common.BaseEntity; + +/** + * AppProperties Entity + * + * @author Miciele Ghiorghis + */ +public class AppProperties extends BaseEntity { + + public static AppProperties create() { + return create(new AppProperties()); + } + + private String majorId; + private String minorId; + private String propertyName; + private String propertyValue; + + public String getMajorId() { + return majorId; + } + + public void setMajorId(String majorId) { + this.majorId = majorId; + } + + public String getMinorId() { + return minorId; + } + + public void setMinorId(String minorId) { + this.minorId = minorId; + } + + public String getPropertyName() { + return propertyName; + } + + public void setPropertyName(String propertyName) { + this.propertyName = propertyName; + } + + public String getPropertyValue() { + return propertyValue; + } + + public void setPropertyValue(String propertyValue) { + this.propertyValue = propertyValue; + } +} From 8869325b60a536d92f02ae4cd9aa1a09b9374268 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:15:15 +0100 Subject: [PATCH 06/91] Tim-connector: JobSchedulerConfiguration entity --- .../entities/JobSchedulerConfiguration.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/common/entities/JobSchedulerConfiguration.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobSchedulerConfiguration.java b/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobSchedulerConfiguration.java new file mode 100644 index 000000000..0ef1ed9d7 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/common/entities/JobSchedulerConfiguration.java @@ -0,0 +1,89 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.common.entities; + +import org.libreplan.business.common.BaseEntity; + +/** + * JobSchedulerConfiguration entity + * + * @author Miciele Ghiorghis + */ +public class JobSchedulerConfiguration extends BaseEntity { + + public static JobSchedulerConfiguration create() { + return create(new JobSchedulerConfiguration()); + } + + private String jobGroup; + private String jobName; + private String triggerGroup; + private String triggerName; + private String cronExpression; + private String jobClassName; + + public String getJobGroup() { + return jobGroup; + } + + public void setJobGroup(String jobGroup) { + this.jobGroup = jobGroup; + } + + public String getJobName() { + return jobName; + } + + public void setJobName(String jobName) { + this.jobName = jobName; + } + + public String getTriggerGroup() { + return triggerGroup; + } + + public void setTriggerGroup(String triggerGroup) { + this.triggerGroup = triggerGroup; + } + + public String getTriggerName() { + return triggerName; + } + + public void setTriggerName(String triggerName) { + this.triggerName = triggerName; + } + + public String getCronExpression() { + return cronExpression; + } + + public void setCronExpression(String cronExpression) { + this.cronExpression = cronExpression; + } + + public String getJobClassName() { + return jobClassName; + } + + public void setJobClassName(String jobClassName) { + this.jobClassName = jobClassName; + } +} From b459606e72128d75ca6f9d42c15a2ab46aee60ae Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:16:06 +0100 Subject: [PATCH 07/91] Tim-connector: Contract for OrderSyncInfo An interface that OrderSyncInfoDAO implements. --- .../orders/daos/IOrderSyncInfoDAO.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderSyncInfoDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderSyncInfoDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderSyncInfoDAO.java new file mode 100644 index 000000000..1973be538 --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/IOrderSyncInfoDAO.java @@ -0,0 +1,56 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.orders.daos; + +import java.util.List; + +import org.libreplan.business.common.daos.IGenericDAO; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderSyncInfo; + +/** + * Contract for {@link OrderSyncInfoDAO} + * + * @author Miciele Ghiorghis + */ +public interface IOrderSyncInfoDAO extends IGenericDAO { + + /** + * Search last sychronized info for the specified {@link Order} + * + * @param order + * the order to search for + * + * @return Last synchronized info + */ + OrderSyncInfo findByOrderLastSynchronizedInfo(Order order); + + /** + * Search last synchronized infos for the specified + * {@link Order} + * + * @param order + * the order to search for + * + * @return list of last synchronized infos + */ + List findByOrderLastSynchronizedInfos(Order order); + +} From 07c2ccaec9d0f27f373822e2af63c14bd2fd6e52 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:18:06 +0100 Subject: [PATCH 08/91] Tim-connector: DAO for OrderSyncInfo An implementation of the interface IOrderSyncInfoDAO --- .../orders/daos/OrderSyncInfoDAO.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderSyncInfoDAO.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderSyncInfoDAO.java b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderSyncInfoDAO.java new file mode 100644 index 000000000..7e19cc77d --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/daos/OrderSyncInfoDAO.java @@ -0,0 +1,71 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.orders.daos; + +import java.util.List; + +import org.hibernate.Criteria; +import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.Restrictions; +import org.libreplan.business.common.daos.GenericDAOHibernate; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderSyncInfo; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Repository; + +/** + * DAO for {@link OrderSyncInfo} + * + * @author Miciele Ghiorghis + */ +@Repository +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class OrderSyncInfoDAO extends GenericDAOHibernate + implements IOrderSyncInfoDAO { + + @Override + public OrderSyncInfo findByOrderLastSynchronizedInfo(Order order) { + DetachedCriteria mostRecentDate = DetachedCriteria + .forClass(OrderSyncInfo.class) + .setProjection(Projections.max("lastSyncDate")) + .add(Restrictions.isNotNull("code")); + + Criteria criteria = getSession().createCriteria(OrderSyncInfo.class); + + criteria.add(Restrictions.eq("order", order)); + criteria.add(Property.forName("lastSyncDate").eq(mostRecentDate)); + + return (OrderSyncInfo) criteria.uniqueResult(); + } + + @Override + @SuppressWarnings("unchecked") + public List findByOrderLastSynchronizedInfos(Order order) { + Criteria criteria = getSession().createCriteria(OrderSyncInfo.class); + criteria.add(Restrictions.eq("order", order)); + criteria.add(Restrictions.isNotNull("code")); + criteria.addOrder(org.hibernate.criterion.Order.desc("lastSyncDate")); + return criteria.list(); + } + +} From f1762336ee9edd84af86d454e0cbd14116071925 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:19:50 +0100 Subject: [PATCH 09/91] Tim-connector: OrderSyncInfo entity --- .../orders/entities/OrderSyncInfo.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderSyncInfo.java diff --git a/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderSyncInfo.java b/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderSyncInfo.java new file mode 100644 index 000000000..f6ef418fd --- /dev/null +++ b/libreplan-business/src/main/java/org/libreplan/business/orders/entities/OrderSyncInfo.java @@ -0,0 +1,85 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.business.orders.entities; + +import java.util.Date; + +import org.apache.commons.lang.Validate; +import org.libreplan.business.common.BaseEntity; + +/** + * OrderSyncInfo entity + * + * @author Miciele Ghiorghis + */ +public class OrderSyncInfo extends BaseEntity { + + private Date lastSyncDate; + private String label; + private String code; + private Order order; + + public static OrderSyncInfo create(Order order) { + Validate.notNull(order); + return create(new OrderSyncInfo(order)); + } + + protected OrderSyncInfo() { + + } + + private OrderSyncInfo(Order order) { + this.lastSyncDate = new Date(); + this.order = order; + } + + public Date getLastSyncDate() { + return lastSyncDate; + } + + public void setLastSyncDate(Date lastSyncDate) { + this.lastSyncDate = lastSyncDate; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Order getOrder() { + return order; + } + + public void setOrder(Order order) { + this.order = order; + } + +} From 4ffd4e5b5086905ab198841a2ad47612af0d79fd Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:21:50 +0100 Subject: [PATCH 10/91] Tim-connector: Hibernate mapping file for AppProperties --- .../common/entities/AppProperties.hbm.xml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 libreplan-business/src/main/resources/org/libreplan/business/common/entities/AppProperties.hbm.xml diff --git a/libreplan-business/src/main/resources/org/libreplan/business/common/entities/AppProperties.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/common/entities/AppProperties.hbm.xml new file mode 100644 index 000000000..185cc5a58 --- /dev/null +++ b/libreplan-business/src/main/resources/org/libreplan/business/common/entities/AppProperties.hbm.xml @@ -0,0 +1,21 @@ + + + + + + + + 100 + + + + + + + + + + + + From 3ee39bcffe633f06496a878260276ee4a897e0dc Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:23:41 +0100 Subject: [PATCH 11/91] Tim-connector: Hibernate mapping file for JobSchedulerConfiguration --- .../JobSchedulerConfiguration.hbm.xml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 libreplan-business/src/main/resources/org/libreplan/business/common/entities/JobSchedulerConfiguration.hbm.xml diff --git a/libreplan-business/src/main/resources/org/libreplan/business/common/entities/JobSchedulerConfiguration.hbm.xml b/libreplan-business/src/main/resources/org/libreplan/business/common/entities/JobSchedulerConfiguration.hbm.xml new file mode 100644 index 000000000..881a4aa8d --- /dev/null +++ b/libreplan-business/src/main/resources/org/libreplan/business/common/entities/JobSchedulerConfiguration.hbm.xml @@ -0,0 +1,23 @@ + + + + + + + + 100 + + + + + + + + + + + + + + From 138e4d6fac63cb87aa06db2a88876c7cd4128b34 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:25:15 +0100 Subject: [PATCH 12/91] Tim-connector: Export timesheets to Tim SOAP server An interface that ExportTimesheetsTomTim implements. It exports timesheets of an existing order to Tim SOAP server. --- .../importers/IExportTimesheetsToTim.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java new file mode 100644 index 000000000..4dfdb0a9e --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/IExportTimesheetsToTim.java @@ -0,0 +1,62 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderSyncInfo; + +/** + * Export time sheets of an existing order to Tim SOAP server using + * {@link TimSoapClient}. + * + * @author Miciele Ghiorghis + */ +public interface IExportTimesheetsToTim { + + /** + * Exports time sheets of the specified productCode and + * {@link Order} + * + * @param productCode + * the Tim's productCode + * @param order + * an existing order + */ + boolean exportTimesheets(String productCode, Order order); + + /** + * Loops through all the time sheets of all {@link Order}s which has tim's + * productcodes and export them to Tim SOAP server + *

+ * This method is of importance for the scheduler service + *

+ */ + void exportTimesheets(); + + /** + * Gets the most recent synchronized time sheet info + * + * @param order + * the order + * @return recent synchronized time sheet info + */ + OrderSyncInfo getOrderLastSyncInfo(Order order); + +} From d7835871234286d3a17cfe051365e757d004c3ff Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:31:56 +0100 Subject: [PATCH 13/91] Tim-connector: exports timesheet to Tim SOAP server An implementation of the interface IExportTimesheetsTOTim. It exports timesheets of an existing order to Tim SOAP server. --- .../importers/ExportTimesheetsToTim.java | 291 ++++++++++++++++++ 1 file changed, 291 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java new file mode 100644 index 000000000..0909538e0 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetsToTim.java @@ -0,0 +1,291 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.IAdHocTransactionService; +import org.libreplan.business.common.IOnTransaction; +import org.libreplan.business.common.daos.IAppPropertiesDAO; +import org.libreplan.business.common.daos.IConfigurationDAO; +import org.libreplan.business.orders.daos.IOrderDAO; +import org.libreplan.business.orders.daos.IOrderSyncInfoDAO; +import org.libreplan.business.orders.entities.Order; +import org.libreplan.business.orders.entities.OrderSyncInfo; +import org.libreplan.business.resources.daos.IWorkerDAO; +import org.libreplan.business.resources.entities.Worker; +import org.libreplan.business.workreports.daos.IWorkReportLineDAO; +import org.libreplan.business.workreports.entities.WorkReportLine; +import org.libreplan.importers.tim.Duration; +import org.libreplan.importers.tim.Person; +import org.libreplan.importers.tim.Product; +import org.libreplan.importers.tim.RegistrationDate; +import org.libreplan.importers.tim.TimOptions; +import org.libreplan.importers.tim.TimeRegistration; +import org.libreplan.importers.tim.TimeRegistrationRequest; +import org.libreplan.importers.tim.TimeRegistrationResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Scope(BeanDefinition.SCOPE_PROTOTYPE) +public class ExportTimesheetsToTim implements IExportTimesheetsToTim { + + private static final Log LOG = LogFactory + .getLog(ExportTimesheetsToTim.class); + + @Autowired + private IWorkerDAO workerDAO; + + @Autowired + private IWorkReportLineDAO workReportLineDAO; + + @Autowired + private IConfigurationDAO configurationDAO; + + @Autowired + IOrderSyncInfoDAO orderSyncInfoDAO; + + @Autowired + private IAdHocTransactionService adHocTransactionService; + + private List workers; + + @Autowired + private IAppPropertiesDAO appPropertiesDAO; + + @Autowired + private IOrderDAO orderDAO; + + @Override + @Transactional(readOnly = true) + public void exportTimesheets() { + Map prop = appPropertiesDAO.findByMajorId("Tim"); + List orders = orderDAO.getOrders(); + for (Order order : orders) { + OrderSyncInfo orderSyncInfo = orderSyncInfoDAO + .findByOrderLastSynchronizedInfo(order); + if (orderSyncInfo == null) { + LOG.warn("Order '" + order.getName() + + "' is not yet synchronized"); + } else { + boolean result = exportTimesheets(orderSyncInfo.getCode(), + orderSyncInfo.getOrder(), prop); + LOG.info("Export successful: " + result); + } + } + } + + @Override + @Transactional(readOnly = true) + public boolean exportTimesheets(String productCode, Order order) { + if (productCode == null || productCode.isEmpty()) { + throw new RuntimeException("Product code should not be empty"); + } + if (order == null) { + throw new RuntimeException("Order should not be empty"); + } + + Map prop = appPropertiesDAO.findByMajorId("Tim"); + return exportTimesheets(productCode, order, prop); + + } + + /** + * exports time sheets to Tim + * + * @param productCode + * the product code + * @param order + * the order + * @param appProperties + * the app properties + * + * @return true if export is succeeded, false otherwise + */ + private boolean exportTimesheets(String productCode, Order order, + Map appProperties) { + + workers = workerDAO.findAll(); + LOG.info("workers.findAll(): " + workers.size()); + if (workers == null && workers.isEmpty()) { + LOG.warn("No workers found!"); + return false; + } + + String url = appProperties.get("Server"); + String userName = appProperties.get("Username"); + String password = appProperties.get("Password"); + int nrDaysTimesheetToTim = Integer.parseInt(appProperties + .get("NrDaysTimesheetToTim")); + + Calendar dateNrOfDaysBack = Calendar.getInstance(); + dateNrOfDaysBack.add(Calendar.DAY_OF_MONTH, -nrDaysTimesheetToTim); + + List workReportLines = order.getWorkReportLines( + new Date(dateNrOfDaysBack.getTimeInMillis()), new Date(), true); + if (workReportLines == null || workReportLines.isEmpty()) { + LOG.warn("No work reportlines are found"); + return false; + } + + List timeRegistrations = new ArrayList(); + + for (WorkReportLine workReportLine : workReportLines) { + TimeRegistration timeRegistration = createExportTimeRegistration( + productCode, workReportLine); + if (timeRegistration != null) { + timeRegistrations.add(timeRegistration); + } + } + + if (timeRegistrations.isEmpty()) { + LOG.warn("Unable to crate timeregistration request"); + return false; + } + + TimeRegistrationRequest timeRegistrationRequest = new TimeRegistrationRequest(); + timeRegistrationRequest.setTimeRegistrations(timeRegistrations); + + TimeRegistrationResponse timeRegistrationResponse = TimSoapClient + .sendRequestReceiveResponse(url, userName, password, + timeRegistrationRequest, TimeRegistrationResponse.class); + + if (isRefsListEmpty(timeRegistrationResponse.getRefs())) { + LOG.warn("Registration response empty refs"); + return false; + } + saveSyncInfoOnAnotherTransaction(productCode, order); + return true; + } + + /** + * checks if list of refs is empty + * + * @param refs + * the list of refs + * @return true if list is empty otherwise false + */ + private boolean isRefsListEmpty(List refs) { + if (refs == null) { + return true; + } + refs.removeAll(Collections.singleton(0)); + return refs.isEmpty(); + } + + /** + * Saves synchronization info + * + * @param productCode + * the productcode + * @param order + * the order + */ + private void saveSyncInfoOnAnotherTransaction(final String productCode, + final Order order) { + adHocTransactionService + .runOnAnotherTransaction(new IOnTransaction() { + @Override + public Void execute() { + OrderSyncInfo orderSyncInfo = OrderSyncInfo + .create(order); + orderSyncInfo.setCode(productCode); + orderSyncInfoDAO.save(orderSyncInfo); + return null; + } + }); + } + + /** + * Creates export time registration + * + * @param productCode + * the product code + * @param workReportLine + * the workreportLine + * @return timeRegistration + */ + private TimeRegistration createExportTimeRegistration(String productCode, + WorkReportLine workReportLine) { + Worker worker = getWorker(workReportLine.getResource().getCode()); + if (worker == null) { + LOG.warn("Worker not found!"); + return null; + } + + Person person = new Person(); + person.setName(worker.getName()); + // person.setNetworkName(worker.getNif()); + person.setOptions(TimOptions.UPDATE_OR_INSERT); + + Product product = new Product(); + product.setOptions(TimOptions.UPDATE_OR_INSERT); + product.setCode(productCode); + + RegistrationDate date = new RegistrationDate(); + date.setOptions(TimOptions.UPDATE_OR_INSERT); + date.setDate(workReportLine.getLocalDate()); + + Duration duration = new Duration(); + duration.setOptions(TimOptions.DECIMAL); + duration.setDuration(workReportLine.getEffort() + .toHoursAsDecimalWithScale(2).doubleValue()); + + TimeRegistration timeRegistration = new TimeRegistration(); + timeRegistration.setPerson(person); + timeRegistration.setProduct(product); + timeRegistration.setRegistrationDate(date); + timeRegistration.setDuration(duration); + return timeRegistration; + } + + /** + * get worker based on the specified code + * + * @param code + * @return worker + */ + private Worker getWorker(String code) { + for (Worker worker : workers) { + if (worker.getCode().equals(code)) { + return worker; + } + } + return null; + } + + @Override + @Transactional(readOnly = true) + public OrderSyncInfo getOrderLastSyncInfo(Order order) { + return orderSyncInfoDAO.findByOrderLastSynchronizedInfo(order); + } + +} From 071c3e84d9352c1de49aaab3deaa734359731314 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:34:05 +0100 Subject: [PATCH 14/91] Tim-connector: A job that exports timesheets to Tim SOAP server This is the job that is scheduled by the scheduler to export timesheets to tim SOAP server It is executed based on the cron-expression defined for this job. --- .../importers/ExportTimesheetToTimJob.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java new file mode 100644 index 000000000..ce7863ff2 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ExportTimesheetToTimJob.java @@ -0,0 +1,54 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; + +/** + * A job that exports time sheets to Tim SOAP server + * + * @author Miciele Ghiorghis + */ +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class ExportTimesheetToTimJob extends QuartzJobBean { + + private IExportTimesheetsToTim exportTimesheetsToTim; + + public IExportTimesheetsToTim getExportTimesheetsToTim() { + return exportTimesheetsToTim; + } + + public void setExportTimesheetsToTim( + IExportTimesheetsToTim exportTimesheetsToTim) { + this.exportTimesheetsToTim = exportTimesheetsToTim; + } + + @Override + protected void executeInternal(JobExecutionContext context) + throws JobExecutionException { + exportTimesheetsToTim.exportTimesheets(); + } + +} From 225a3475de27ff33d0889c228cd4931f9e7340db Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:42:52 +0100 Subject: [PATCH 15/91] Tim-connector: Imports Rosters from Tim SOAP server An interface that ImportRosterFromTim implements It import Rosters from Tim SOAP server and convert them to workers calendar Exception. If workers calendar exception already existis it updates the effort duration, otherwise creates new worker's calendar exception --- .../importers/IImportRosterFromTim.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java new file mode 100644 index 000000000..05349b835 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/IImportRosterFromTim.java @@ -0,0 +1,39 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import org.libreplan.business.calendars.entities.CalendarException; + +/** + * Import Rosters from Tim SOAP server using {@link TimSoapClient} and updates + * worker's Exception calendar accordingly + * + * @author Miciele Ghiorghis + */ +public interface IImportRosterFromTim { + + /** + * Import rosters from Tim and update workers' {@link CalendarException} + *

+ * If worker's calendar exception already exists it will be removed and + * added new one, in other cases a new calendar exception will be created + */ + void importRosters(); +} From d9fba94d7ca0ef523a7eb3c33b1bd524c7dbc808 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:46:05 +0100 Subject: [PATCH 16/91] Tim-connector: Import rosters from Tim SOAP Server and convert them to worker's calendar exception An implementation of the interface IImportRosterFromTim It import rosters from Tim convert them to workers calendar exception. If worker's calendar exception already exists it updates effort duration, otherwise creates new worker's calendar exception. --- .../importers/ImportRosterFromTim.java | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java new file mode 100644 index 000000000..60bfeed41 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTim.java @@ -0,0 +1,386 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.joda.time.LocalDate; +import org.libreplan.business.calendars.daos.ICalendarExceptionTypeDAO; +import org.libreplan.business.calendars.entities.CalendarException; +import org.libreplan.business.calendars.entities.CalendarExceptionType; +import org.libreplan.business.calendars.entities.Capacity; +import org.libreplan.business.calendars.entities.PredefinedCalendarExceptionTypes; +import org.libreplan.business.calendars.entities.ResourceCalendar; +import org.libreplan.business.common.IAdHocTransactionService; +import org.libreplan.business.common.IOnTransaction; +import org.libreplan.business.common.daos.IAppPropertiesDAO; +import org.libreplan.business.common.daos.IConfigurationDAO; +import org.libreplan.business.common.exceptions.InstanceNotFoundException; +import org.libreplan.business.resources.daos.IResourceDAO; +import org.libreplan.business.resources.daos.IWorkerDAO; +import org.libreplan.business.resources.entities.Worker; +import org.libreplan.business.workingday.EffortDuration; +import org.libreplan.importers.RosterException.RosterExceptionItem; +import org.libreplan.importers.tim.Data; +import org.libreplan.importers.tim.Department; +import org.libreplan.importers.tim.Filter; +import org.libreplan.importers.tim.Period; +import org.libreplan.importers.tim.Person; +import org.libreplan.importers.tim.Roster; +import org.libreplan.importers.tim.RosterCategory; +import org.libreplan.importers.tim.RosterRequest; +import org.libreplan.importers.tim.RosterResponse; +import org.libreplan.web.calendars.IBaseCalendarModel; +import org.libreplan.web.resources.worker.IWorkerModel; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class ImportRosterFromTim implements IImportRosterFromTim { + + private static final Log LOG = LogFactory.getLog(ImportRosterFromTim.class); + + @Autowired + private IConfigurationDAO configurationDAO; + + @Autowired + private IWorkerDAO workerDAO; + + @Autowired + private IResourceDAO resourceDAO; + + @Autowired + private IWorkerModel workerModel; + + @Autowired + private IAppPropertiesDAO appPropertiesDAO; + + @Autowired + private IAdHocTransactionService adHocTransactionService; + + @Autowired + private ICalendarExceptionTypeDAO calendarExceptionTypeDAO; + + @Autowired + @Qualifier("subclass") + private IBaseCalendarModel baseCalendarModel; + + private List workers; + + @Override + @Transactional + public void importRosters() { + Map prop = appPropertiesDAO.findByMajorId("Tim"); + String url = prop.get("Server"); + String userName = prop.get("Username"); + String password = prop.get("Password"); + int nrDaysRosterFromTim = Integer.parseInt(prop + .get("NrDaysRosterFromTim")); + + RosterRequest rosterRequest = createRosterRequest(nrDaysRosterFromTim); + RosterResponse rosterResponse = TimSoapClient + .sendRequestReceiveResponse(url, userName, password, + rosterRequest, RosterResponse.class); + + updateWorkersCalendarException(rosterResponse); + } + + + /** + * updates workers Exception calendar + * + * @param rosterResponse + * the response from Tim SOAP server + */ + private void updateWorkersCalendarException( + final RosterResponse rosterResponse) { + adHocTransactionService + .runOnAnotherTransaction(new IOnTransaction() { + + @Override + public Void execute() { + addAllWorkers(); + List rosterExceptions = getRosterExceptions(rosterResponse); + if (!rosterExceptions.isEmpty()) { + updateCalendarException(rosterExceptions); + } else { + LOG.info("No roster-exceptions found in the response object"); + } + return null; + } + }); + } + + /** + * Loops through rosterResponse and creates + * {@link RosterException}s if any and link them to the worker + * + * @param rosterResponse + * the response + * @return a list of RosterExceptions + */ + private List getRosterExceptions( + RosterResponse rosterResponse) { + Map> map = getRosterExceptionPerWorker(rosterResponse); + List rosterExceptions = new ArrayList(); + + for (Map.Entry> entry : map.entrySet()) { + Worker worker = getWorker(entry.getKey()); + if (worker != null) { + List list = entry.getValue(); + Collections.sort(list, new Comparator() { + @Override + public int compare(Roster o1, Roster o2) { + return o1.getDate().compareTo(o2.getDate()); + } + }); + RosterException re = new RosterException(worker); + re.addRosterExceptions(list); + rosterExceptions.add(re); + } + } + return rosterExceptions; + } + + /** + * Filters the roster exceptions and creates map of personsNetwork name with + * associated roster (exceptions) + * + * @param rosterResponse + * the response + * @return person-roster exception map + */ + private Map> getRosterExceptionPerWorker( + RosterResponse rosterResponse) { + Map> rosterMap = new HashMap>(); + List rosters = rosterResponse.getRosters(); + for (Roster roster : rosters) { + if (roster.getPrecence().equals("Afwezig")) { + String personsNetWorkName = roster.getPersons().get(0) + .getNetworkName(); + if (!rosterMap.containsKey(personsNetWorkName)) { + rosterMap.put(personsNetWorkName, new ArrayList()); + } + rosterMap.get(personsNetWorkName).add(roster); + } + } + return rosterMap; + } + + + /** + * updates workers calendar exception + * + * @param rosterExceptions + * list of roster exceptions + */ + private void updateCalendarException(List rosterExceptions) { + for (RosterException rosterException : rosterExceptions) { + List items = rosterException + .getRosterExceptionItems(); + for (RosterExceptionItem item : items) { + updateCalendarExceptionPerWorker(rosterException.getWorker(), + item.getDate(), item.getExceptionType(), + item.getEffortDuration()); + } + } + + } + + + /** + * updates calendar exception of the specified {@link Worker} + * for the specified date + * + * @param worker + * the worker + * @param date + * the date of the exception + * @param exceptionName + * the exception name + * @param effortDuration + * the exceptions effortDurtaion + */ + private void updateCalendarExceptionPerWorker(Worker worker, + LocalDate date, String exceptionName, EffortDuration effortDuration) { + if (!effortDuration.isZero()) { + CalendarExceptionType calendarExceptionType = getCalendarExceptionType(exceptionName); + if (calendarExceptionType == null) { + return; + } + ResourceCalendar resourceCalendar = worker.getCalendar(); + if (resourceCalendar == null) { + LOG.warn("ResourceCalendar of worker '" + worker.getNif() + + "' not found"); + return; + } + CalendarException calendarExceptionDay = resourceCalendar + .getExceptionDay(date); + Capacity capacity = Capacity.create(effortDuration); + if (calendarExceptionDay != null) { + resourceCalendar.removeExceptionDay(calendarExceptionDay + .getDate()); + } + baseCalendarModel.initEdit(resourceCalendar); + baseCalendarModel.updateException(calendarExceptionType, date, + date, capacity); + } + } + + /** + * Searches and returns the calendarExcptionType based on the specified + * name + * + * @param name + * the exception calendar name + */ + private CalendarExceptionType getCalendarExceptionType(String name) { + if (name == null || name.isEmpty()) { + LOG.error("name should not be empty"); + return null; + } + try { + String nameToSearch = name; + if (nameToSearch.contains("Vakantie")) { + nameToSearch = PredefinedCalendarExceptionTypes.RESOURCE_HOLIDAY + .toString(); + } + return calendarExceptionTypeDAO.findUniqueByName(nameToSearch); + } catch (InstanceNotFoundException e) { + LOG.error("Calendar exceptionType not found", e); + } + return null; + } + + + /** + * adds all existing workers to workers list + */ + private void addAllWorkers() { + workers = workerDAO.findAll(); + } + + /** + * returns {@link Worker} based on the specified nif + * + * @param nif + * the worker's nif + * @return Worker if found, otherwise null + */ + private Worker getWorker(String nif) { + for (Worker worker : workers) { + if (worker.getNif().equals(nif)) { + return worker; + } + } + return null; + } + + /** + * creates and returns {@link RosterRequest} + * + * @param nrDaysRosterFromTim + * nr of days required to set the end date + */ + private RosterRequest createRosterRequest(int nrDaysRosterFromTim) { + Roster roster = createRoster(nrDaysRosterFromTim); + + Period periode = new Period(); + periode.setStart(new org.joda.time.DateTime().minusDays(10)); + periode.setEnd(new org.joda.time.DateTime() + .plusDays(nrDaysRosterFromTim)); + List periods = new ArrayList(); + periods.add(periode); + + Department department = new Department(); + department.setRef("4"); // TODO: make this configurable + + Filter filter = new Filter(); + filter.setPeriods(periods); + filter.setDepartment(department); + + roster.setFilter(filter); + + roster.setPersons(createPerson()); + + roster.setRosterCategories(createRosterCategory()); + + roster.setDepartment(department); + + roster.setPrecence(new String()); + roster.setPeriods(periods); + + RosterRequest exportRosterRequest = new RosterRequest(); + Data data = new Data(); + data.setData(roster); + + exportRosterRequest.setData(data); + return exportRosterRequest; + + } + + /** + * creates and returns list of {@link Persoon} + */ + private List createPerson() { + List persons = new ArrayList(); + persons.add(new Person()); + return persons; + } + + /** + * creates and returns list of {@link RosterCategory} + */ + private List createRosterCategory() { + List rosterCategories = new ArrayList(); + RosterCategory rosterCategory = new RosterCategory(); + rosterCategory.setName(new String()); + rosterCategories.add(rosterCategory); + return rosterCategories; + } + + /** + * creates and returns {@Roster} + */ + private Roster createRoster(int nrDaysRosterFromTim) { + Roster roster = new Roster(); + roster.setStartDate(new LocalDate().minusDays(10)); + roster.setEndDate(new LocalDate().plusDays(nrDaysRosterFromTim)); + roster.setResourcePlanning(false); + roster.setDayPlanning(false); + roster.setCalendar(false); + roster.setNonPlaned(true); + roster.setFullDay(false); + roster.setConcept(false); + return roster; + } +} From 93fc9a8a41b1b72e64a822d4fb6ae45c2d33ea68 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:49:10 +0100 Subject: [PATCH 17/91] Tim-connector: A job that import rosters from Tim SOAP server This is the job that is scheduled by the scheduler to import rosters from Tim SOAP server. It is executed based on the cron-expression defined for this job. --- .../importers/ImportRosterFromTimJob.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java new file mode 100644 index 000000000..5278a2e46 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ImportRosterFromTimJob.java @@ -0,0 +1,57 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.scheduling.quartz.QuartzJobBean; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +/** + * A job that import rosters from Tim SOAP server + * + * @author Miciele Ghiorghis + */ +@Component +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class ImportRosterFromTimJob extends QuartzJobBean { + + private IImportRosterFromTim importRosterFromTim; + + public IImportRosterFromTim getImportRosterFromTim() { + return importRosterFromTim; + } + + public void setImportRosterFromTim(IImportRosterFromTim importRosterFromTim) { + this.importRosterFromTim = importRosterFromTim; + } + + @Override + @Transactional + protected void executeInternal(JobExecutionContext context) + throws JobExecutionException { + importRosterFromTim.importRosters(); + } + + +} From 3619f716ee6bc8d1d2ffba7b13a89dae6b74a04e Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 17:58:08 +0100 Subject: [PATCH 18/91] Tim-connector: A manager that dynamically creates jobs and cron-triggers using spring quartz library An interface that SchedulerManager implements. Dynamically creates jobs and cron triggers. It associated the triggers with the jobs and add them to the scheduler. It also supports the rescheduling of jobs. --- .../importers/ISchedulerManager.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/ISchedulerManager.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/ISchedulerManager.java b/libreplan-webapp/src/main/java/org/libreplan/importers/ISchedulerManager.java new file mode 100644 index 000000000..b02a75d44 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/ISchedulerManager.java @@ -0,0 +1,80 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.util.List; + +import org.libreplan.business.common.entities.JobSchedulerConfiguration; +import org.springframework.scheduling.quartz.CronTriggerBean; +import org.springframework.scheduling.quartz.JobDetailBean; + +/** + * A manager(client) that dynamically creates jobs and cron-triggers using + * spring quartz library. + *

+ * The start and destroy of the scheduler itself is managed by the Spring + * framework. The scheduler starts automatically when the application starts and + * destroyed when the application stops. The sole purpose of this manager is to + * create jobs {@link JobDetailBean} and cron-triggers {@link CronTriggerBean} + * when the scheduler is started. It links the triggers with the jobs and add + * them to the scheduler. + *

+ * It also supports the rescheduling of jobs. + *

+ * The SchedulerManager reads the jobs to be scheduled and the cron-triggers to + * fire the jobs form {@link JobSchedulerConfiguration}. Hence the + * {@link JobSchedulerConfiguration} must exist with predefined jobs and valid + * cron-triggers + * + * @author Miciele Ghiorghis + */ +public interface ISchedulerManager { + + /** + * Reads job configuration from the database and schedules the jobs + */ + void scheduleJobs(); + + /** + * Reschedule the job. + *

+ * Reads the job to be rescheduled from the specified parameter + * {@link JobSchedulerConfiguration} and reschedule the job + * + * @param jobSchedulerConfiguration + * the job scheduler configuration + */ + void rescheduleJob(JobSchedulerConfiguration jobSchedulerConfiguration); + + /** + * returns the scheduler info list. This is necessary for UI + * + * @return + */ + List getSchedulerInfos(); + + /** + * To manually execute the job specified by jobName + * + * @param jobName + * the name of the job to be executed + */ + void doManual(String jobName); +} From fd30e75940d2144548425e863513d297e6c819d1 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:04:25 +0100 Subject: [PATCH 19/91] Tim-connector: A manager that dynamically creates jobs and cron-triggers using spring quartz libraray An implementation of the interface ISchedulerManager Dynamically creates jobs and cron triggers. It associated the triggers with the jobs and add them to the scheduler. It also supports the rescheduling of jobs. --- .../libreplan/importers/SchedulerManager.java | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java new file mode 100644 index 000000000..14a007cb3 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerManager.java @@ -0,0 +1,249 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.text.ParseException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.daos.IJobSchedulerConfigurationDAO; +import org.libreplan.business.common.entities.JobSchedulerConfiguration; +import org.quartz.CronExpression; +import org.quartz.CronTrigger; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.Scope; +import org.springframework.scheduling.quartz.CronTriggerBean; +import org.springframework.scheduling.quartz.JobDetailBean; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Scope(BeanDefinition.SCOPE_SINGLETON) +public class SchedulerManager implements ISchedulerManager { + + private static final Log LOG = LogFactory.getLog(SchedulerManager.class); + + @Autowired + private Scheduler scheduler; + + @Autowired + private IImportRosterFromTim importRosterFromTim; + + @Autowired + private IExportTimesheetsToTim exportTimesheetsToTim; + + @Autowired + private IJobSchedulerConfigurationDAO jobSchedulerConfigurationDAO; + + public Scheduler getScheduler() { + return scheduler; + } + + public void setScheduler(Scheduler scheduler) { + this.scheduler = scheduler; + } + + @Override + public void scheduleJobs() { + List jobSchedulerConfigurations = jobSchedulerConfigurationDAO + .getAll(); + for (JobSchedulerConfiguration conf : jobSchedulerConfigurations) { + CronTriggerBean cronTriggerBean = createCronTriggerBean( + conf.getTriggerGroup(), conf.getTriggerName(), + conf.getCronExpression()); + if (cronTriggerBean != null) { + cronTriggerBean.setJobName(conf.getJobName()); + cronTriggerBean.setJobGroup(conf.getJobGroup()); + JobDetailBean jobDetailBean = createJobDetailBean( + conf.getJobName(), conf.getJobGroup(), + conf.getJobClassName()); + if (jobDetailBean != null) { + scheduleJob(jobDetailBean, cronTriggerBean); + } + } + } + } + + /** + * Creates and returns {@link CronTriggerBean} + * + * @param triggerGroup + * the trigger group + * @param triggerName + * the trigger name + * @param cronExpression + * the cron expression string + */ + private CronTriggerBean createCronTriggerBean(String triggerGroup, + String triggerName, String cronExpression) { + CronTriggerBean cronTriggerBean = new CronTriggerBean(); + cronTriggerBean.setGroup(triggerGroup); + cronTriggerBean.setName(triggerName); + try { + cronTriggerBean + .setCronExpression(new CronExpression(cronExpression)); + return cronTriggerBean; + } catch (ParseException e) { + LOG.error("Unable to parse cron expression", e); + } + return null; + } + + /** + * Creates and returns {@link JobDetailBean} + * + * @param jobName + * the job name + * @param jobGroup + * the job group + * @param jobClassName + * the job classname + */ + private JobDetailBean createJobDetailBean(String jobName, String jobGroup, + String jobClassName) { + JobDetailBean jobDetailBean = new JobDetailBean(); + + Class jobClass = getJobClass(jobClassName); + if (jobClass == null) { + LOG.error("JobClass '" + jobClassName + "' not found"); + return null; + } + jobDetailBean.setGroup(jobGroup); + jobDetailBean.setName(jobName); + jobDetailBean.setJobClass(jobClass); + + Map jobDataAsMap = new HashMap(); + if (jobDetailBean.getJobClass().getSimpleName() + .equals("ImportRosterFromTimJob")) { + jobDataAsMap.put("importRosterFromTim", importRosterFromTim); + } else { + jobDataAsMap.put("exportTimesheetsToTim", exportTimesheetsToTim); + } + jobDetailBean.setJobDataAsMap(jobDataAsMap); + return jobDetailBean; + } + + /** + * Schedules the job specified by {@link JobDetailBean} and + * link it with the specified {@link CronTriggerBean} + * + * @param jobDetailBean + * the jobDetailBean + * @param cronTriggerBean + * the cronTriggerBean + */ + private void scheduleJob(JobDetailBean jobDetailBean, + CronTriggerBean cronTriggerBean) { + try { + this.scheduler.scheduleJob(jobDetailBean, cronTriggerBean); + } catch (SchedulerException e) { + LOG.error("unable to schedule job", e); + } + } + + /** + * returns jobClass based on jobClassName parameter + * + * @param jobClassName + * job className + */ + private Class getJobClass(String jobClassName) { + if (jobClassName.equals("ImportRosterFromTimJob")) { + return org.libreplan.importers.ImportRosterFromTimJob.class; + } + + if (jobClassName.equals("ExportTimesheetToTimJob")) { + return org.libreplan.importers.ExportTimesheetToTimJob.class; + } + + return null; + } + + @Override + public void rescheduleJob(JobSchedulerConfiguration jobSchedulerConfiguration) { + CronTriggerBean cronTriggerBean = createCronTriggerBean( + jobSchedulerConfiguration.getTriggerGroup(), + jobSchedulerConfiguration.getTriggerName(), + jobSchedulerConfiguration.getCronExpression()); + cronTriggerBean.setName(jobSchedulerConfiguration.getTriggerName()); + cronTriggerBean.setGroup(jobSchedulerConfiguration.getTriggerGroup()); + try { + cronTriggerBean.setCronExpression(jobSchedulerConfiguration + .getCronExpression()); + } catch (ParseException e) { + throw new RuntimeException("Invalid cron expression"); + } + cronTriggerBean.setJobName(jobSchedulerConfiguration.getJobName()); + cronTriggerBean.setJobGroup(jobSchedulerConfiguration.getJobGroup()); + try { + scheduler.rescheduleJob(jobSchedulerConfiguration.getTriggerName(), + jobSchedulerConfiguration.getTriggerGroup(), + cronTriggerBean); + } catch (SchedulerException e) { + throw new RuntimeException("Unable to reschedule the job"); + } + } + + @Override + @Transactional(readOnly = true) + public List getSchedulerInfos() { + List jobSchedulerConfigurations = jobSchedulerConfigurationDAO + .getAll(); + List results = new ArrayList(); + for (JobSchedulerConfiguration jobSchedulerConfiguration : jobSchedulerConfigurations) { + SchedulerInfo schedulerInfo = new SchedulerInfo(); + schedulerInfo + .setJobSchedulerConfiguration(jobSchedulerConfiguration); + try { + CronTrigger trigger = (CronTrigger) scheduler.getTrigger( + jobSchedulerConfiguration.getTriggerName(), + jobSchedulerConfiguration.getTriggerGroup()); + if (trigger != null) { + schedulerInfo.setNextFireTime(trigger.getNextFireTime() + .toString()); + } + results.add(schedulerInfo); + } catch (SchedulerException e) { + LOG.error("unable to get the trigger"); + } + } + return results; + } + + @Override + public void doManual(String jobName) { + if (jobName.equals("Import roster from Tim")) { + importRosterFromTim.importRosters(); + return; + } + + if (jobName.equals("Export timesheet to Tim")) { + exportTimesheetsToTim.exportTimesheets(); + return; + } + } +} From 7520f27604e65fe6fe974cfa9253b4dc58b16bb4 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:06:39 +0100 Subject: [PATCH 20/91] Tim-connector: The scheduler info (non persistent bean) --- .../libreplan/importers/SchedulerInfo.java | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerInfo.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerInfo.java b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerInfo.java new file mode 100644 index 000000000..277d45fac --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/SchedulerInfo.java @@ -0,0 +1,59 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import org.libreplan.business.common.entities.JobSchedulerConfiguration; + +/** + * The schedulerInfo non persistent entity + * + * @author Miciele Ghiorghis + */ +public class SchedulerInfo { + + private JobSchedulerConfiguration jobSchedulerConfiguration; + private String nextFireTime; + + public SchedulerInfo() { + + } + + public SchedulerInfo(JobSchedulerConfiguration jobSchedulerConfiguration) { + this.jobSchedulerConfiguration = jobSchedulerConfiguration; + } + + public String getNextFireTime() { + return nextFireTime; + } + + public void setNextFireTime(String nextFireTime) { + this.nextFireTime = nextFireTime; + } + + public JobSchedulerConfiguration getJobSchedulerConfiguration() { + return jobSchedulerConfiguration; + } + + public void setJobSchedulerConfiguration( + JobSchedulerConfiguration jobSchedulerConfiguration) { + this.jobSchedulerConfiguration = jobSchedulerConfiguration; + } + +} From b313de6935532634b0e984d06e1aec50ed107981 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:08:30 +0100 Subject: [PATCH 21/91] Tim-connector: Helper class to convert Tim rosters to RosterExceptions --- .../libreplan/importers/RosterException.java | 142 ++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/RosterException.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/RosterException.java b/libreplan-webapp/src/main/java/org/libreplan/importers/RosterException.java new file mode 100644 index 000000000..4fee77f05 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/RosterException.java @@ -0,0 +1,142 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.joda.time.LocalDate; +import org.libreplan.business.resources.entities.Worker; +import org.libreplan.business.workingday.EffortDuration; +import org.libreplan.importers.tim.Roster; + +/** + * Helper class to convert the Roster response to the RosterExceptions + * + * @author Miciele Ghiorghis + */ +public class RosterException { + private Worker worker; + List rosterExceptionItems = new ArrayList(); + + public RosterException(Worker worker) { + this.worker = worker; + } + + /** + * Reads the rosters and add the exceptions to + * rosterExceptionItems + * + * @param rosters + */ + public void addRosterExceptions(List rosters) { + Map> mapDateRoster = new TreeMap>(); + + for (Roster roster : rosters) { + if (!mapDateRoster.containsKey(roster.getDate())) { + mapDateRoster.put(roster.getDate(), new ArrayList()); + } + mapDateRoster.get(roster.getDate()).add(roster); + + } + + for (Map.Entry> entry : mapDateRoster + .entrySet()) { + RosterExceptionItem item = new RosterExceptionItem(entry.getKey()); + updateExceptionTypeAndEffort(item, entry.getValue()); + rosterExceptionItems.add(item); + } + } + + /** + * updates the exceptionType and effortDuration + * + * @param rosterExceptionItem + * the rosterException item + * @param rosters + * list of rosters + */ + private void updateExceptionTypeAndEffort( + RosterExceptionItem rosterExceptionItem, List rosters) { + EffortDuration max = EffortDuration.zero(); + EffortDuration sum = EffortDuration.zero(); + String rosterCatName = rosters.get(0).getRosterCategories().get(0) + .getName(); + for (Roster roster : rosters) { + EffortDuration duration = EffortDuration + .parseFromFormattedString(roster.getDuration()); + if (duration.compareTo(max) > 0) { + rosterCatName = roster.getRosterCategories().get(0).getName(); + } + max = EffortDuration.max(max, duration); + sum = EffortDuration.sum(sum, duration); + + } + rosterExceptionItem.setExceptionType(rosterCatName); + rosterExceptionItem.setEffortDuration(sum); + } + + /** + * returns {@link Worker} + */ + public Worker getWorker() { + return worker; + } + + /** + * returns list of {@link RosterExceptionItem} + */ + public List getRosterExceptionItems() { + return rosterExceptionItems; + } + + public class RosterExceptionItem { + private LocalDate date; + private String exceptionType; + private EffortDuration effortDuration; + + public RosterExceptionItem(LocalDate date) { + this.date = date; + } + + public LocalDate getDate() { + return date; + } + + public String getExceptionType() { + return exceptionType; + } + + public void setExceptionType(String exceptionType) { + this.exceptionType = exceptionType; + } + + public EffortDuration getEffortDuration() { + return effortDuration; + } + + public void setEffortDuration(EffortDuration effortDuration) { + this.effortDuration = effortDuration; + } + } + +} From ae54764b179feb1ac1128d97e2951ef83ce9184e Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:09:44 +0100 Subject: [PATCH 22/91] Tim-connector: SOAP client to interact with Tim SOAP server This client creates SOAP message, makes connection to the SOAP server, sends the request and processes the response. It uses jaxb lirary to marshal and unmarshal the request and response. --- .../libreplan/importers/TimSoapClient.java | 334 ++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/importers/TimSoapClient.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/importers/TimSoapClient.java b/libreplan-webapp/src/main/java/org/libreplan/importers/TimSoapClient.java new file mode 100644 index 000000000..f51835b74 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/importers/TimSoapClient.java @@ -0,0 +1,334 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.importers; + +import java.io.File; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.Node; +import javax.xml.soap.SOAPBody; +import javax.xml.soap.SOAPConnection; +import javax.xml.soap.SOAPConnectionFactory; +import javax.xml.soap.SOAPEnvelope; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.soap.SOAPPart; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.cxf.common.util.Base64Utility; +import org.libreplan.importers.tim.RosterResponse; + +/** + * Client to interact with Tim SOAP server. + *

+ * It creates SOAP message, makes connection to the SOAP server and sends the + * request. + *

+ * The received response is converted to java objects + * + * @author Miciele Ghiorghis + */ +public class TimSoapClient { + + private static final Log LOG = LogFactory.getLog(TimSoapClient.class); + + /** + * Creates request message to be send to the SOAP server + * + * @param clazz + * @param userName + * the user name + * @param password + * the password + * @return the created soap message + * @throws SOAPException + * @throws JAXBException + */ + private static SOAPMessage createRequest(T clazz, String userName, + String password) throws SOAPException, JAXBException { + + SOAPMessage message = createMessage(); + + addAuthorization(message, userName, password); + + SOAPEnvelope soapEnvelope = createEnvelope(message.getSOAPPart()); + + SOAPBody soapBody = soapEnvelope.getBody(); + marshal(clazz, soapBody); + + message.saveChanges(); + return message; + } + + /** + * Creates SOAP message to be send to the SOAP server + * + * @return the SOAP message + * @throws SOAPException + */ + private static SOAPMessage createMessage() throws SOAPException { + MessageFactory messageFactory = MessageFactory.newInstance(); + SOAPMessage message = messageFactory.createMessage(); + return message; + } + + /** + * Adds authorization to the specified parameter message + * + * @param message + * the message + * @param username + * the user name + * @param password + * the password + */ + private static void addAuthorization(SOAPMessage message, String username, + String password) { + String encodeUserInfo = username + ":" + password; + encodeUserInfo = Base64Utility.encode(encodeUserInfo.getBytes()); + message.getMimeHeaders().setHeader("Authorization", + "Basic " + encodeUserInfo); + } + + /** + * Creates SOAP envelope + * + * @param soapPart + * the message part + * @return the SOAP envelope + * @throws SOAPException + */ + private static SOAPEnvelope createEnvelope(SOAPPart soapPart) + throws SOAPException { + SOAPEnvelope soapEnvelope = soapPart.getEnvelope(); + addNamespaceDeclaration(soapEnvelope); + setEncodingStyle(soapEnvelope); + return soapEnvelope; + } + + /** + * Adds namespace declaration to the specified parameter + * soapEnvelop + * + * @param soapEnvelope + * the SOAP envelope + * @throws SOAPException + */ + private static void addNamespaceDeclaration(SOAPEnvelope soapEnvelope) + throws SOAPException { + soapEnvelope.addNamespaceDeclaration("xsd", + "http://www.w3.org/2001/XMLSchema"); + soapEnvelope.addNamespaceDeclaration("xsi", + "http://www.w3.org/2001/XMLSchema-instance"); + soapEnvelope.addNamespaceDeclaration("enc", + "http://schemas.xmlsoap.org/soap/encoding/"); + soapEnvelope.addNamespaceDeclaration("env", + "http://schemas.xmlsoap.org/soap/envelop/"); + + } + + /** + * Sets the encoding style to the specified parameter + * soapEnvelop + * + * @param soapEnvelope + * the SOAP envelope + * @throws SOAPException + */ + private static void setEncodingStyle(SOAPEnvelope soapEnvelope) + throws SOAPException { + soapEnvelope + .setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/"); + } + + /** + * Marshals the specified parameter clazz + * + * @param clazz + * the object to be marshaled + * @param soapBody + * the SOAP body + * @throws JAXBException + */ + private static void marshal(T clazz, SOAPBody soapBody) + throws JAXBException { + JAXBContext jaxbContext = JAXBContext.newInstance(clazz.getClass()); + Marshaller marshaller = jaxbContext.createMarshaller(); + marshaller.marshal(clazz, soapBody); + } + + /** + * Unmarshals the specified paramter soapBody + * + * @param clazz + * object for unmarashal + * @param soapBody + * the soap body to be unmarshalled + * @return the unmarashalled object + * @throws JAXBException + */ + @SuppressWarnings("unchecked") + private static T unmarshal(Class clazz, SOAPBody soapBody) + throws JAXBException { + JAXBContext jaxbContext = JAXBContext.newInstance(clazz); + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + Node bindElement = (Node) soapBody.getFirstChild(); + while (bindElement.getNodeType() != Node.ELEMENT_NODE) { + bindElement = (Node) bindElement.getNextSibling(); + } + return unmarshaller.unmarshal(bindElement, clazz).getValue(); + } + + /** + * Sends the SOAP message request to the SOAP server + * + * @param url + * the endpoint of the web service + * @param message + * the SOAP message to be send + * @return the response, SOAP message + * @throws SOAPException + */ + private static SOAPMessage sendRequest(String url, SOAPMessage message) + throws SOAPException { + SOAPConnection connection = null; + SOAPMessage response = null; + try { + connection = createConnection(); + response = connection.call(message, url); + } finally { + if (connection != null) { + closeConnection(connection); + } + } + return response; + } + + + /** + * Creates a SOAP connection to the SOAP server + * + * @return the SOAPconnection object + * @throws SOAPException + */ + private static SOAPConnection createConnection() throws SOAPException { + SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory + .newInstance(); + SOAPConnection connection = soapConnectionFactory.createConnection(); + return connection; + } + + /** + * Closes the SOAP connection + * + * @param connection + * the SOAP connection + * @throws SOAPException + */ + private static void closeConnection(SOAPConnection connection) + throws SOAPException { + connection.close(); + } + + /** + * Sends soap request to the SOAP server. Receives and unmarshals the + * response + * + * @param url + * the SOAP server url(endpoint) + * @param userName + * the user + * @param password + * the password + * @param request + * the request object + * @param response + * the response class + * @return returns the expected object + */ + public static T sendRequestReceiveResponse(String url, + String userName, String password, U request, Class response) { + try { + SOAPMessage requestMsg = createRequest(request, userName, password); + SOAPMessage responseMsg = sendRequest(url, requestMsg); + return unmarshal(response, responseMsg.getSOAPBody()); + } catch (SOAPException soapExp) { + LOG.error("SOAPException: ", soapExp); + } catch (JAXBException jaxbExp) { + LOG.error("JAXBException: ", jaxbExp); + } + + return null; + } + + /** + * Checks authorization based on the specified username and + * password + * + * @param url + * webservices url + * @param username + * the user + * @param password + * the password + * @return true if user is authorized otherwise false + */ + public static boolean checkAuthorization(String url, String username, + String password) { + try { + SOAPMessage message = createMessage(); + addAuthorization(message, username, password); + sendRequest(url, message); + return true; + } catch (SOAPException e) { + LOG.error("SOAP Exception: ", e); + } + return false; + } + + /** + * simulates roster response, to be used for example by unit test + *

+ * unmarshals roster xml from file and returns {@link RosterResponse} + * + * @param file + * file with xml contents + */ + public static RosterResponse unmarshalRosterFromFile(File file) { + try { + JAXBContext jaxbContext = JAXBContext + .newInstance(RosterResponse.class); + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + RosterResponse exportResponse = (RosterResponse) unmarshaller + .unmarshal(file); + return exportResponse; + } catch (JAXBException e) { + LOG.error("Error processing response: ", e); + } + return null; + } +} From 5cd6ac75665df66991ff1687730e7ce1eeafa533 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:14:52 +0100 Subject: [PATCH 23/91] Tim-connector: A controller for Tim synchronizing of timesheets --- .../orders/TimSynchronizationController.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/orders/TimSynchronizationController.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/orders/TimSynchronizationController.java b/libreplan-webapp/src/main/java/org/libreplan/web/orders/TimSynchronizationController.java new file mode 100644 index 000000000..9303b8b59 --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/orders/TimSynchronizationController.java @@ -0,0 +1,108 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.orders; + +import static org.libreplan.web.I18nHelper._; + +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.daos.IAppPropertiesDAO; +import org.libreplan.business.common.entities.AppProperties; +import org.libreplan.business.orders.entities.OrderSyncInfo; +import org.libreplan.importers.IExportTimesheetsToTim; +import org.libreplan.web.common.IMessagesForUser; +import org.libreplan.web.common.Level; +import org.libreplan.web.common.MessagesForUser; +import org.libreplan.web.common.Util; +import org.springframework.beans.factory.annotation.Autowired; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.Label; +import org.zkoss.zul.Textbox; + +/** + * Controller for Tim synchronization + * + * @author Miciele Ghiorghis + */ +public class TimSynchronizationController extends GenericForwardComposer { + + private static final org.apache.commons.logging.Log LOG = LogFactory + .getLog(TimSynchronizationController.class); + + private OrderCRUDController orderController; + + private Textbox txtProductCode; + private Label labelProductCode, labelLastSyncDate; + + @Autowired + private IExportTimesheetsToTim exportTimesheetsToTim; + + @Autowired + private IAppPropertiesDAO appPropertiesDAO; + + private Component messagesContainer; + + private IMessagesForUser messagesForUser; + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("timSynchronizationController", this, true); + txtProductCode = (Textbox) comp.getFellowIfAny("txtProductCode"); + labelLastSyncDate = (Label) comp.getFellowIfAny("labelLastSyncDate"); + labelProductCode = (Label) comp.getFellowIfAny("labelProductCode"); + messagesForUser = new MessagesForUser(messagesContainer); + updateOrderLastSyncInfoScreen(); + } + + public void startExportToTim() { + LOG.info("startExportToTim(): " + orderController.getOrder().getName()); + txtProductCode.setConstraint("no empty:" + _("cannot be empty")); + if (exportTimesheetsToTim.exportTimesheets(txtProductCode.getValue(), + orderController.getOrder())) { + messagesForUser.showMessage(Level.INFO, + "Exporting timesheets to Tim is completed successfully"); + } else { + messagesForUser.showMessage(Level.ERROR, + _("Exporting timesheets to Tim failed")); + } + updateOrderLastSyncInfoScreen(); + } + + private void updateOrderLastSyncInfoScreen() { + OrderSyncInfo orderSyncInfo = exportTimesheetsToTim + .getOrderLastSyncInfo(orderController.getOrder()); + if (orderSyncInfo != null) { + if (labelLastSyncDate != null) { + labelLastSyncDate.setValue(Util.formatDateTime(orderSyncInfo + .getLastSyncDate())); + } + if (labelProductCode != null) { + labelProductCode.setValue("(" + orderSyncInfo.getCode() + ")"); + } + } + } + + public boolean isTimDeactivated() { + AppProperties appProperties = appPropertiesDAO.findByMajorIdAndName( + "Tim", "Activated"); + return !appProperties.getPropertyValue().equalsIgnoreCase("Y"); + } +} From 339a35a28d4064429dbbe9cdb948d85df8ace426 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:16:02 +0100 Subject: [PATCH 24/91] Tim-connector: A controller for job scheduling --- .../web/common/JobSchedulerController.java | 342 ++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java new file mode 100644 index 000000000..724d9ad4c --- /dev/null +++ b/libreplan-webapp/src/main/java/org/libreplan/web/common/JobSchedulerController.java @@ -0,0 +1,342 @@ +/* + * This file is part of LibrePlan + * + * Copyright (C) 2013 St. Antoniusziekenhuis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.libreplan.web.common; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.commons.lang.Validate; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.libreplan.business.common.IAdHocTransactionService; +import org.libreplan.business.common.IOnTransaction; +import org.libreplan.business.common.daos.IJobSchedulerConfigurationDAO; +import org.libreplan.business.common.entities.JobSchedulerConfiguration; +import org.libreplan.importers.ISchedulerManager; +import org.libreplan.importers.SchedulerInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.zkoss.zk.ui.Component; +import org.zkoss.zk.ui.event.Event; +import org.zkoss.zk.ui.event.EventListener; +import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.GenericForwardComposer; +import org.zkoss.zul.Button; +import org.zkoss.zul.Cell; +import org.zkoss.zul.Grid; +import org.zkoss.zul.Hbox; +import org.zkoss.zul.Label; +import org.zkoss.zul.Popup; +import org.zkoss.zul.Row; +import org.zkoss.zul.RowRenderer; +import org.zkoss.zul.Rows; +import org.zkoss.zul.SimpleListModel; +import org.zkoss.zul.Toolbarbutton; + +/** + * Controller for job scheduler manager + * + * @author Miciele Ghiorghis + */ +public class JobSchedulerController extends GenericForwardComposer { + private static final Log LOG = LogFactory + .getLog(JobSchedulerController.class); + + private Grid jobSchedulerGrid, cronExpressionGrid; + + private Popup cronExpressionInputPopup; + + private Label jobGroupLabel, jobNameLable; + + @Autowired + ISchedulerManager schedulerManager; + + @Autowired + IJobSchedulerConfigurationDAO jobSchedulerConfigurationDAO; + + @Override + public void doAfterCompose(Component comp) throws Exception { + super.doAfterCompose(comp); + comp.setVariable("jobSchedulerController", this, true); + reloadSchedulerJobs(); + } + + public List getSchedulerInfo() { + List schedulerInfoList = schedulerManager + .getSchedulerInfos(); + Collections.sort(schedulerInfoList, new Comparator() { + + @Override + public int compare(SchedulerInfo o1, SchedulerInfo o2) { + int result = o1 + .getJobSchedulerConfiguration() + .getJobGroup() + .compareTo( + o2.getJobSchedulerConfiguration().getJobGroup()); + if (result == 0) { + result = o1 + .getJobSchedulerConfiguration() + .getJobName() + .compareTo( + o2.getJobSchedulerConfiguration() + .getJobName()); + } + return result; + } + }); + return schedulerInfoList; + } + + private void reloadSchedulerJobs() { + jobSchedulerGrid.setModel(new SimpleListModel(getSchedulerInfo())); + jobSchedulerGrid.invalidate(); + } + + public JobSchedulingRenderer getJobSchedulingRenderer() { + return new JobSchedulingRenderer(); + } + + public class JobSchedulingRenderer implements RowRenderer { + @Override + public void render(Row row, Object data) { + + SchedulerInfo schedulerInfo = (SchedulerInfo) data; + Util.appendLabel(row, schedulerInfo.getJobSchedulerConfiguration() + .getJobGroup()); + Util.appendLabel(row, schedulerInfo.getJobSchedulerConfiguration() + .getJobName()); + appendCronExpressionAndButton(row, schedulerInfo); + Util.appendLabel(row, schedulerInfo.getNextFireTime()); + appendManualStart(row, schedulerInfo); + } + } + + private void appendCronExpressionAndButton(final Row row, + final SchedulerInfo schedulerInfo) { + final Hbox hBox = new Hbox(); + hBox.setWidth("100%"); + Cell cell = new Cell(); + cell.setHflex("2"); + cell.setAlign("left"); + + Label label = new Label(schedulerInfo.getJobSchedulerConfiguration() + .getCronExpression()); + cell.appendChild(label); + + Cell cell2 = new Cell(); + cell2.setHflex("1"); + cell2.setWidth("10px"); + final Toolbarbutton button = new Toolbarbutton(); + button.setImage("/common/img/ico_editar.png"); + cell2.appendChild(button); + hBox.appendChild(cell); + hBox.appendChild(cell2); + + button.addEventListener(Events.ON_CLICK, new EventListener() { + + @Override + public void onEvent(Event event) throws Exception { + setupCronExpressionPopup(schedulerInfo); + cronExpressionInputPopup.open(jobSchedulerGrid, "at_pointer"); + } + }); + row.appendChild(hBox); + } + + + private void setupCronExpressionPopup(final SchedulerInfo schedulerInfo) { + List list = new ArrayList(); + list.add(getCronExpression(schedulerInfo.getJobSchedulerConfiguration() + .getCronExpression())); + cronExpressionGrid.setModel(new SimpleListModel(list)); + + jobGroupLabel = (Label) cronExpressionInputPopup + .getFellowIfAny("jobGroup"); + jobNameLable = (Label) cronExpressionInputPopup + .getFellowIfAny("jobName"); + jobGroupLabel.setValue(schedulerInfo.getJobSchedulerConfiguration() + .getJobGroup()); + jobNameLable.setValue(schedulerInfo.getJobSchedulerConfiguration() + .getJobName()); + } + + @Autowired + private IAdHocTransactionService adHocTransactionService; + + private void saveJobConfigurationAndReschedule( + final String jobGroup, final String jobName, final String cronExp) { + adHocTransactionService + .runOnAnotherTransaction(new IOnTransaction() { + @Override + public Void execute() { + JobSchedulerConfiguration jobSchedulerConfiguration = jobSchedulerConfigurationDAO + .findByJobGroupAndJobName(jobGroup, jobName); + jobSchedulerConfiguration.setCronExpression(cronExp); + jobSchedulerConfigurationDAO + .save(jobSchedulerConfiguration); + schedulerManager.rescheduleJob(jobSchedulerConfiguration); + reloadSchedulerJobs(); + return null; + } + }); + } + + private CronExpression getCronExpression(String cronExpressionStr) { + CronExpression cronExpression = new CronExpression(); + StringTokenizer st = new StringTokenizer(cronExpressionStr); + int countTokens = st.countTokens(); + if (countTokens < 6) { + throw new IllegalArgumentException("Cron expression is not valid"); + } + cronExpression.setSeconds(getNextToken(st.nextToken())); + cronExpression.setMinutes(getNextToken(st.nextToken())); + cronExpression.setHours(getNextToken(st.nextToken())); + cronExpression.setDayOfMonth(getNextToken(st.nextToken())); + cronExpression.setMonth(getNextToken(st.nextToken())); + cronExpression.setDayOfWeek(getNextToken(st.nextToken())); + if (countTokens > 6) { // optional + cronExpression.setYear(getNextToken(st.nextToken())); + } else { + cronExpression.setYear(""); + } + + return cronExpression; + } + + private String getNextToken(String token) { + return token.isEmpty() ? "" : token.trim(); + } + private void appendManualStart(final Row row, + final SchedulerInfo schedulerInfo) { + final Button rescheduleButton = new Button("Manual"); + rescheduleButton.addEventListener(Events.ON_CLICK, new EventListener() { + + @Override + public void onEvent(Event event) throws Exception { + schedulerManager.doManual(schedulerInfo + .getJobSchedulerConfiguration().getJobName()); + } + }); + row.appendChild(rescheduleButton); + } + + public void reschedule() { + jobGroupLabel = (Label) cronExpressionInputPopup + .getFellowIfAny("jobGroup"); + jobNameLable = (Label) cronExpressionInputPopup + .getFellowIfAny("jobName"); + + Rows rows = cronExpressionGrid.getRows(); + Row row = (Row) rows.getChildren().get(0); + CronExpression cronExp = (CronExpression) row.getValue(); + saveJobConfigurationAndReschedule(jobGroupLabel.getValue(), + jobNameLable.getValue(), convertToCronExpressionStr(cronExp)); + cronExpressionInputPopup.close(); + getJobSchedulingRenderer(); + } + + private String convertToCronExpressionStr(CronExpression cronExp) { + return String.format("%1$s %2$s %3$s %4$s %5$s %6$s %7$s", + cronExp.getSeconds(), cronExp.getMinutes(), cronExp.getHours(), + cronExp.getDayOfMonth(), cronExp.getMonth(), + cronExp.getDayOfWeek(), cronExp.getYear()).trim(); + } + + public void cancel() { + cronExpressionInputPopup.invalidate(); + cronExpressionInputPopup.close(); + } + + public class CronExpression { + private String seconds; + private String minutes; + private String hours; + private String dayOfMonth; + private String month; + private String dayOfWeek; + private String year; + + public String getSeconds() { + return seconds; + } + + public void setSeconds(String seconds) { + Validate.notEmpty(seconds, "Seconds is mandatory"); + this.seconds = seconds; + } + + public String getMinutes() { + return minutes; + } + + public void setMinutes(String minutes) { + Validate.notEmpty(minutes, "Minutes is mandatory"); + this.minutes = minutes; + } + + public String getHours() { + return hours; + } + + public void setHours(String hours) { + Validate.notEmpty(hours, "Hours is mandatory"); + this.hours = hours; + } + + public String getDayOfMonth() { + return dayOfMonth; + } + + public void setDayOfMonth(String dayOfMonth) { + Validate.notEmpty(dayOfMonth, "day of month is mandatory"); + this.dayOfMonth = dayOfMonth; + } + + public String getMonth() { + return month; + } + + public void setMonth(String month) { + Validate.notEmpty(month, "month is mandatory"); + this.month = month; + } + + public String getDayOfWeek() { + return dayOfWeek; + } + + public void setDayOfWeek(String dayOfWeek) { + Validate.notEmpty(dayOfWeek, "day of week is mandatory"); + this.dayOfWeek = dayOfWeek; + } + + public String getYear() { + return year; + } + + public void setYear(String year) { + this.year = year; + } + + } + +} From 4605d318f8b96460af4756cc55bd5a7f631773b4 Mon Sep 17 00:00:00 2001 From: Miciele Ghiorghis Date: Wed, 16 Jan 2013 18:16:44 +0100 Subject: [PATCH 25/91] Tim-connector: UI for job scheduling --- .../common/job_scheduler_configuration.zul | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 libreplan-webapp/src/main/webapp/common/job_scheduler_configuration.zul diff --git a/libreplan-webapp/src/main/webapp/common/job_scheduler_configuration.zul b/libreplan-webapp/src/main/webapp/common/job_scheduler_configuration.zul new file mode 100644 index 000000000..f86ca9af0 --- /dev/null +++ b/libreplan-webapp/src/main/webapp/common/job_scheduler_configuration.zul @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ ${i18n:_("For more details on cron expression click")} + ${i18n:_('this')} +
+
+
+ + + +