/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.generator.utils; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.openflexo.foundation.dm.AutoGeneratedProcessBusinessDataDMEntity; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.wkf.FlexoProcess; import org.openflexo.generator.Generator; /** * This class is used to create the samples for each processes. <br> * We do not use directly the method from FlexoProcess because it doesn't creates Ids and relationship with parent process. <br> * Additionally the format is transformed to easily change it to CSV file. * * @author nid * */ public class PrototypeProcessBusinessDataSamplesCreator { public static final String PROCESSINSTANCE_ID_KEY = "__ID__"; Map<String, List<List<String>>> businessDataSamples = new HashMap<String, List<List<String>>>(); public PrototypeProcessBusinessDataSamplesCreator(FlexoProject project) { Map<String, List<FlexoProcess>> processesWithParentForBusinessDataKey = new HashMap<String, List<FlexoProcess>>(); Map<String, Map<String, List<Object>>> samplesMapForBusinessData = new HashMap<String, Map<String, List<Object>>>(); // 1 Get all samples from all processes and merge same used business data in one map for (FlexoProcess process : project.getAllLocalFlexoProcesses()) { String businessDataKey = process.getBusinessDataDictionaryKey(); if (process.getParentProcess() != null) { List<FlexoProcess> processes = processesWithParentForBusinessDataKey.get(businessDataKey); if (processes == null) { processes = new ArrayList<FlexoProcess>(); processesWithParentForBusinessDataKey.put(businessDataKey, processes); } processes.add(process); } Map<String, List<Object>> results = samplesMapForBusinessData.get(businessDataKey); if (results == null) { results = new HashMap<String, List<Object>>(); samplesMapForBusinessData.put(businessDataKey, results); } Map<String, List<Object>> samples = process.getProcessInstanceDictionaryPrototypeSamples(); int maxRows = getMaxNumberOfSamples(results); int maxRowsSamples = getMaxNumberOfSamples(samples); if (maxRows < maxRowsSamples) { maxRows = maxRowsSamples; } mergeMaps(results, samples); GregorianCalendar creationDate = new GregorianCalendar(2001, 1, 1, 10, 0); GregorianCalendar updateDate = new GregorianCalendar(2001, 1, 1, 10, 0); for (Map.Entry<String, List<Object>> entry : results.entrySet()) { int index = 0; while (entry.getValue().size() != maxRows) { if (entry.getValue().size() > maxRows) { entry.getValue().remove(entry.getValue().size() - 1); } else { if (entry.getKey().equals(FlexoProcess.PROCESSINSTANCE_CREATIONDATE_KEY)) { entry.getValue().add(creationDate.getTime()); creationDate.add(Calendar.MONTH, 4); creationDate.add(Calendar.DAY_OF_MONTH, 6); creationDate.add(Calendar.HOUR_OF_DAY, 1); } else if (entry.getKey().equals(FlexoProcess.PROCESSINSTANCE_LASTUPDATEDATE_KEY)) { entry.getValue().add(updateDate.getTime()); updateDate.add(Calendar.MONTH, 4); updateDate.add(Calendar.DAY_OF_MONTH, 6); updateDate.add(Calendar.HOUR_OF_DAY, 1); } else { if (entry.getValue().size() == 0) { entry.getValue().add(null); } else { entry.getValue().add(entry.getValue().get(index)); index++; } } } } } } // 2. Transform the samplesMapForBusinessData into Map<String, List<List<String>>> for (Map.Entry<String, Map<String, List<Object>>> entryBusinessData : samplesMapForBusinessData.entrySet()) { List<List<String>> results = new ArrayList<List<String>>(); businessDataSamples.put(entryBusinessData.getKey(), results); // 1st line contains keys List<String> keys = new ArrayList<String>(entryBusinessData.getValue().keySet()); Collections.sort(keys, String.CASE_INSENSITIVE_ORDER); results.add(new ArrayList<String>(keys)); results.get(0).add(0, PROCESSINSTANCE_ID_KEY); for (String key : keys) { int i = 1; for (Object value : entryBusinessData.getValue().get(key)) { if (results.size() <= i) { results.add(new ArrayList<String>()); results.get(i).add(String.valueOf(i - 1)); } if (value instanceof Date) { results.get(i).add(Generator.getDateFormat("dd/MM/yyyy HH:mm").format(value)); } else if (value != null) { results.get(i).add(value.toString()); } else { results.get(i).add(null); } i++; } } } // 3. Create relationship with parent process if any and create also missing parent/child instances (depending if it is a single sub // process or a multiple). for (String businessDataKey : processesWithParentForBusinessDataKey.keySet()) { List<FlexoProcess> processesWithParent = processesWithParentForBusinessDataKey.get(businessDataKey); Collections.sort(processesWithParent, new Comparator<FlexoProcess>() { // Starts with single parent process with max rows @Override public int compare(FlexoProcess o1, FlexoProcess o2) { boolean o1IsSingleSubProcess = o1.isSingleSubProcess(); boolean o2IsSingleSubProcess = o2.isSingleSubProcess(); if (o1IsSingleSubProcess && !o2IsSingleSubProcess) { return -1; } if (!o1IsSingleSubProcess && o2IsSingleSubProcess) { return 1; } return businessDataSamples.get(o2.getParentProcess().getBusinessDataDictionaryKey()).size() - businessDataSamples.get(o1.getParentProcess().getBusinessDataDictionaryKey()).size(); } }); for (FlexoProcess process : processesWithParent) { // Specify the parent process id (split evenly among parent instances if it is a multiple process, or one by parent if it is // single) List<String> keyLine = businessDataSamples.get(process.getBusinessDataDictionaryKey()).get(0); if (!keyLine .contains(AutoGeneratedProcessBusinessDataDMEntity.getParentProcessBusinessDataIdKey(process.getParentProcess()))) { keyLine.add(1, AutoGeneratedProcessBusinessDataDMEntity.getParentProcessBusinessDataIdKey(process.getParentProcess())); if (process.isSingleSubProcess()) { for (int i = 1; i < businessDataSamples.get(businessDataKey).size(); i++) { businessDataSamples.get(businessDataKey).get(i).add(1, String.valueOf(i - 1)); if (businessDataSamples.get(process.getParentProcess().getBusinessDataDictionaryKey()).size() < i) { List<String> lastElement = businessDataSamples.get( process.getParentProcess().getBusinessDataDictionaryKey()).get( businessDataSamples.get(process.getParentProcess().getBusinessDataDictionaryKey()).size() - 1); lastElement = new ArrayList<String>(lastElement); lastElement.set(0, String.valueOf(i - 1)); businessDataSamples.get(process.getParentProcess().getBusinessDataDictionaryKey()).add(lastElement); } } // If some parent does not have children, create one while (businessDataSamples.get(process.getParentProcess().getBusinessDataDictionaryKey()).size() > businessDataSamples .get(businessDataKey).size()) { List<String> lastElement = businessDataSamples.get(businessDataKey).get( businessDataSamples.get(businessDataKey).size() - 1); lastElement = new ArrayList<String>(lastElement); lastElement.set(0, String.valueOf(Integer.parseInt(lastElement.get(0)) + 1)); lastElement.set(1, String.valueOf(Integer.parseInt(lastElement.get(1)) + 1)); businessDataSamples.get(businessDataKey).add(lastElement); } } else { int numberOfParentInstance = businessDataSamples.get(process.getParentProcess().getBusinessDataDictionaryKey()) .size() - 1; int parentId = 0; for (int i = 1; i < businessDataSamples.get(businessDataKey).size(); i++) { businessDataSamples.get(businessDataKey).get(i).add(1, String.valueOf(parentId)); parentId++; if (parentId >= numberOfParentInstance) { parentId = 0; } } } } } } } private int getMaxNumberOfSamples(Map<String, List<Object>> map) { int max = 1; for (List list : map.values()) { if (list.size() > max) { max = list.size(); } } return max; } private void mergeMaps(Map<String, List<Object>> results, Map<String, List<Object>> samples) { for (Map.Entry<String, List<Object>> sampleEntry : samples.entrySet()) { if (results.get(sampleEntry.getKey()) == null) { results.put(sampleEntry.getKey(), sampleEntry.getValue()); } else { results.get(sampleEntry.getKey()).addAll(sampleEntry.getValue()); } } } public Set<String> getAllBusinessDataKeys() { return businessDataSamples.keySet(); } public List<List<String>> getProcessSamples(String businessDataKey) { return businessDataSamples.get(businessDataKey); } }