Java tutorial
package pt.iflow.flows; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import javax.sql.DataSource; import org.apache.commons.lang.StringUtils; import org.json.JSONException; import org.json.JSONObject; import pt.iflow.api.blocks.Attribute; import pt.iflow.api.blocks.Block; import pt.iflow.api.blocks.FormProps; import pt.iflow.api.blocks.Port; import pt.iflow.api.blocks.form.Form; import pt.iflow.api.core.BeanFactory; import pt.iflow.api.core.ProcessCatalogue; import pt.iflow.api.core.ProcessCatalogueImpl; import pt.iflow.api.core.Repository; import pt.iflow.api.db.DatabaseInterface; import pt.iflow.api.flows.FlowSetting; import pt.iflow.api.flows.FlowSettings; import pt.iflow.api.flows.FlowType; import pt.iflow.api.flows.IFlowData; import pt.iflow.api.flows.MailStartSettings; import pt.iflow.api.licensing.LicenseService; import pt.iflow.api.licensing.LicenseServiceException; import pt.iflow.api.licensing.LicenseServiceFactory; import pt.iflow.api.processtype.DataTypeEnum; import pt.iflow.api.processtype.ModelsDataType; import pt.iflow.api.processtype.ProcessDataType; import pt.iflow.api.services.types.FlowClassGeneratorConvert; import pt.iflow.api.services.types.FlowDataConvert; import pt.iflow.api.services.types.ForkJoinDepConvert; import pt.iflow.api.utils.Const; import pt.iflow.api.utils.Logger; import pt.iflow.api.utils.UserInfoInterface; import pt.iflow.api.utils.Utils; import pt.iflow.api.xml.FlowMarshaller; import pt.iflow.api.xml.codegen.flow.XmlAttribute; import pt.iflow.api.xml.codegen.flow.XmlBlock; import pt.iflow.api.xml.codegen.flow.XmlCatalogVarAttribute; import pt.iflow.api.xml.codegen.flow.XmlCatalogVars; import pt.iflow.api.xml.codegen.flow.XmlFlow; import pt.iflow.api.xml.codegen.flow.XmlFormTemplate; import pt.iflow.api.xml.codegen.flow.XmlPort; import pt.iknow.utils.StringUtilities; import pt.iknow.utils.security.SecurityException; import com.twolattes.json.Marshaller; /** * Flow representation. This class contains all information related to an * instantiated flow. * * @author oscar * */ public class FlowData implements IFlowData { private static final String BLOCK_PACKAGE = "pt.iflow.blocks."; //$NON-NLS-1$ private int _nId; private String _sName; private String _sFile; private Vector<Block> _vFlow; private boolean _bOnline; private boolean _bDeployed; private String _sApplicationId; private String _sApplicationName; private String _sError = null; private String _organizationId; private long _lastModified; private long _created; private HashMap<String, Integer> _hmIndexVars = new HashMap<String, Integer>(); private int indexPosition = 0; private boolean _hasDetail = false; private Block _detailForm = null; private int _seriesId = NO_SERIES; private ProcessCatalogueImpl _catalogue; private Map<String, Form> _hmFormTemplates = new HashMap<String, Form>(); private MailStartSettings _mailStartSettings = null; private FlowType flowType; private int maxBlockId; private FlowClassGenerator flowClassFile = null; private Hashtable<String, Hashtable<Integer, Object[]>> _htSubFlowEndPorts = new Hashtable<String, Hashtable<Integer, Object[]>>(); private Hashtable<Integer, ForkJoinDep> _htForkJoinDepPath = new Hashtable<Integer, ForkJoinDep>(); private HashSet<Set<Integer>> _hsAllStates = new HashSet<Set<Integer>>(); private Hashtable<String, String> _htSubFlows = new Hashtable<String, String>(); private final int iOFFSET = 1100000; private boolean hasSchedules = false; public static void reloadClasses(UserInfoInterface userInfo) { Repository rep = BeanFactory.getRepBean(); rep.reloadClassLoaders(userInfo); } /** * default constructor */ public FlowData() { super(); } /** * init constructor */ private FlowData(int anFlowId, String asName, String asFileName, String organizationId, long created, long lastModified, int seriesId, String typeCode) { this._nId = anFlowId; this._sName = asName; this._sFile = asFileName; this._vFlow = new Vector<Block>(); this._organizationId = organizationId; this._created = created; this._lastModified = lastModified; this._seriesId = seriesId; this._catalogue = new ProcessCatalogueImpl(); this.flowType = FlowType.getFlowType(typeCode); } protected FlowData(int anFlowId, String asName, String asFileName, boolean abOnline, String organizationId, long created, long lastModified, int seriesId, String typeCode) { this(anFlowId, asName, asFileName, organizationId, created, lastModified, seriesId, typeCode); this._bOnline = abOnline; } protected FlowData(int anFlowId, String asName, String asFileName, boolean abOnline, String organizationId, long created, long lastModified, int seriesId, String typeCode, int maxBlockId) { this(anFlowId, asName, asFileName, organizationId, created, lastModified, seriesId, typeCode); this._bOnline = abOnline; this.setMaxBlockId(maxBlockId); } // deploy or not protected FlowData(UserInfoInterface userInfo, int anFlowId, String asName, String asFileName, long created, long lastModified, int seriesId, String typeCode, final XmlFlow aXmlFlow) { this(userInfo, anFlowId, asName, asFileName, created, lastModified, seriesId, typeCode, aXmlFlow, true); } /** * Creates a flow * * @param aXmlFlow * the flow */ protected FlowData(final UserInfoInterface userInfo, final int anFlowId, final String asName, final String asFileName, final long created, final long lastModified, final int seriesId, String typeCode, final XmlFlow aXmlFlow, final boolean deploy) { this(anFlowId, asName, asFileName, userInfo.getOrganization(), created, lastModified, seriesId, typeCode); flowClassFile = new FlowClassGenerator(userInfo, anFlowId); // block cache to be used in the ForkJoin dependency graph Hashtable<Integer, Block> htBlocks = new Hashtable<Integer, Block>(); try { InstantiationResult flowResult = null; List<FlowSetting> alSettings = new ArrayList<FlowSetting>(); if (deploy) flowResult = this.instantiateFlow(userInfo, aXmlFlow, anFlowId, alSettings, htBlocks, 0); // SAVE FLOW SETTINGS AND PROCESS SETTINGS CATALOGUE VARS // first, "static" settings FlowSettings flowSettings = BeanFactory.getFlowSettingsBean(); List<FlowSetting> alDefaultSettings = flowSettings.getDefaultSettings(anFlowId); FlowSetting[] currentSettings = flowSettings.getFlowSettings(userInfo, anFlowId); Set<String> settingsToKill = new HashSet<String>(); if (currentSettings != null) { for (FlowSetting s : currentSettings) settingsToKill.add(s.getName()); } if (alDefaultSettings.size() > 0 || alSettings.size() > 0) { FlowSetting[] fsa = new FlowSetting[alDefaultSettings.size() + alSettings.size()]; // first static props for (int i = 0; i < alDefaultSettings.size(); i++) { fsa[i] = alDefaultSettings.get(i); // add property name to catalogue vars this.setFlowSettingVar(fsa[i]); } // now block properties for (int i = alDefaultSettings.size(), j = 0; j < alSettings.size(); i++, j++) { fsa[i] = alSettings.get(j); // add property name to catalogue vars this.setFlowSettingVar(fsa[i]); } flowSettings.saveFlowSettings(userInfo, fsa, true); // found some properties, save them from a painfull death! for (FlowSetting setting : fsa) settingsToKill.remove(setting.getName()); // nobody likes you, so i hope you die with cancer for (String settingName : settingsToKill) flowSettings.removeFlowSetting(userInfo, anFlowId, settingName); } // default format settings Map<DataTypeEnum, String> mapSettings = new HashMap<DataTypeEnum, String>(); String settingValue; FlowSetting setting; setting = flowSettings.getFlowSetting(anFlowId, Const.sFLOW_DATE_FORMAT); if (null == setting || StringUtils.isEmpty(setting.getValue())) settingValue = Const.sDEF_DATE_FORMAT; else settingValue = setting.getValue(); mapSettings.put(DataTypeEnum.Date, settingValue); mapSettings.put(DataTypeEnum.DateArray, settingValue); setting = flowSettings.getFlowSetting(anFlowId, Const.sFLOW_INT_FORMAT); if (null == setting || StringUtils.isEmpty(setting.getValue())) settingValue = Const.sDEF_INT_FORMAT; else settingValue = setting.getValue(); mapSettings.put(DataTypeEnum.Integer, settingValue); mapSettings.put(DataTypeEnum.IntegerArray, settingValue); setting = flowSettings.getFlowSetting(anFlowId, Const.sFLOW_FLOAT_FORMAT); if (null == setting || StringUtils.isEmpty(setting.getValue())) settingValue = Const.sDEF_FLOAT_FORMAT; else settingValue = setting.getValue(); mapSettings.put(DataTypeEnum.Float, settingValue); mapSettings.put(DataTypeEnum.FloatArray, settingValue); /* CatalogVars */ XmlCatalogVars xmlcv = aXmlFlow.getXmlCatalogVars(); if (xmlcv != null && xmlcv.getXmlCatalogVarAttributeCount() > 0) { for (int i = 0; i < xmlcv.getXmlCatalogVarAttributeCount(); i++) { XmlCatalogVarAttribute attr = xmlcv.getXmlCatalogVarAttribute(i); DataTypeEnum dataType = DataTypeEnum.getDataType(attr.getDataType()); String format = attr.getFormat(); if (StringUtils.isBlank(format)) format = mapSettings.get(dataType); String aux = attr.getDataType(); String modelsClass = dataType.isAbstractModel() ? (dataType.isList() ? aux.substring(0, aux.lastIndexOf("Array")) : aux) : null; this.setCatalogueVar(attr.getName(), attr.getInitVal(), dataType, modelsClass, attr.getIsSearchable(), attr.getPublicName(), format); flowClassFile.addVar(dataType, attr.getName(), modelsClass); } } Logger.debug(userInfo.getUtilizador(), this, "constructor", "Catalogue: " + System.getProperty("line.separator") + _catalogue); // end catalog stuff... if (!deploy) return; // flow not deployed, quit! // builds ForkJoin dependency path this.buildForkJoinDepPath(userInfo, htBlocks, new HashSet<Integer>(), flowResult.start, null); this.saveForkJoinDepPath(userInfo); try { instantiateDetailBlock(userInfo, flowResult.start, asFileName); Logger.info(userInfo.getUtilizador(), this, "constructor", "Process Detail Block instantiated in " + asFileName + "."); } catch (Throwable t) { Logger.warning(userInfo.getUtilizador(), this, "constructor", "Could not instantiate Process Detail Block", t); } try { loadFormTemplates(userInfo, aXmlFlow); Logger.info(userInfo.getUtilizador(), this, "constructor", "FormTemplates instantiated in " + asFileName + "."); } catch (Throwable t) { Logger.warning(userInfo.getUtilizador(), this, "constructor", "Could not instantiate FormTemplates", t); } instantiateMailStartSettings(userInfo, flowResult.start); setDeployed(true); flowClassFile.writeContent(); } catch (Exception e) { this._vFlow = null; // Mas que caralho esta merda! String flowError = userInfo.getMessages().getString("FlowData.error.deployFlow", e.getMessage()); this.setError(flowError); Logger.error(userInfo.getUtilizador(), this, "constructor", "Unable to build flow: " + e.getMessage(), e); } } private InstantiationResult instantiateFlow(UserInfoInterface ui, XmlFlow aXmlFlow, int anFlowId, List<FlowSetting> alSettings, Hashtable<Integer, Block> htBlocks, int offset) throws Exception { Block blockStart = null; ArrayList<Block> alBlockEnd = null; Hashtable<Integer, Integer> htPortMapIn = new Hashtable<Integer, Integer>(); Hashtable<Integer, Integer> htPortMapOut = new Hashtable<Integer, Integer>(); Class<? extends Block> blockClass = null; LicenseService licService = LicenseServiceFactory.getLicenseService(); for (int b = 0; b < aXmlFlow.getXmlBlockCount(); b++) { XmlBlock block = aXmlFlow.getXmlBlock(b); String blockType = block.getType(); try { licService.canInstantiateBlock(ui, blockType); } catch (LicenseServiceException e) { throw new ForbiddenBlockException(blockType); } // 10/01/2012 - P.Ussman - No longer used due to issue 578 solution // if (blockType.equals("BlockSubFlow")) { // InstantiationResult subflowResult = this.instantiateSubFlow(ui, // block, anFlowId, alSettings, htBlocks, offset); // htPortMapIn.put(new Integer(block.getId()), new Integer( // subflowResult.start.getId())); // Iterator<Block> it = subflowResult.getEndIterator(); // while (it.hasNext()) { // Block bEnd = it.next(); // htPortMapOut.put(new Integer(block.getId()), new Integer( // bEnd.getId())); // } // continue; // } Integer blockId = new Integer(block.getId() + offset); try { String stmp = BLOCK_PACKAGE + blockType; blockClass = loadBlockClass(ui, stmp); } catch (ClassNotFoundException cnfe) { throw new Exception("Erro ao criar bloco " + blockType, cnfe); } Logger.debug(null, this, "constructor", "Processing block " + blockClass.getName()); Constructor<? extends Block> argsConstructor = blockClass.getConstructor(int.class, int.class, int.class, String.class); Block bBlock = argsConstructor.newInstance(anFlowId, blockId, block.getId(), aXmlFlow.getName()); XmlPort xmlPort = null; try { // Ports for (int portNumber = 0; portNumber < block.getXmlPortCount(); portNumber++) { xmlPort = block.getXmlPort(portNumber); Logger.debug(null, this, "constructor", "Processing port " + xmlPort.getName()); Port port = new Port(); port.setName(xmlPort.getName()); port.setConnectedBlockId(xmlPort.getConnectedBlockId() + offset); port.setConnectedPortName(xmlPort.getConnectedPortName()); if (xmlPort.getName().equals("portEvent")) bBlock.setHasEvent(true); Field fPort = blockClass.getField(xmlPort.getName()); fPort.set(bBlock, port); } } catch (Exception e) { throw new Exception("Erro ao criar porto " + xmlPort.getName() + " para o bloco " + block.getType(), e); } HashMap<String, String> hmtmp = new HashMap<String, String>(); // Attributes for (int attrNumber = 0; attrNumber < block.getXmlAttributeCount(); attrNumber++) { XmlAttribute xmlAttribute = block.getXmlAttribute(attrNumber); String name = xmlAttribute.getName(); String value = xmlAttribute.getValue(); if (value == null) value = ""; if (name.startsWith(IFlowData.sSETTING) || name.startsWith(IFlowData.sSETTING_DESC)) { hmtmp.put(name, value); continue; } try { Logger.debug(null, this, "constructor", "Processing attribute " + name + "=" + value); Attribute attribute = new Attribute(); attribute.setName(name); attribute.setValue(value); bBlock.addAttribute(attribute); } catch (Exception e) { throw new Exception("Erro ao criar atributo " + name + " para o bloco " + blockType, e); } } HashSet<String> hsSettings = new HashSet<String>(); Iterator<String> iter = hmtmp.keySet().iterator(); while (iter.hasNext()) { String name = (String) iter.next(); if (!name.startsWith(IFlowData.sSETTING)) continue; String stmp = name.substring(IFlowData.sSETTING.length()); name = hmtmp.get(name); if (hsSettings.contains(name)) continue; try { String value = hmtmp.get(IFlowData.sSETTING_DESC + stmp); Logger.debug(null, this, "constructor", "Processing setting " + name + " (" + value + ")"); alSettings.add(new FlowSetting(anFlowId, name, value)); hsSettings.add(name); } catch (Exception e) { throw new Exception("Erro ao criar propriedade " + name + " para o bloco " + blockType, e); } } //Updates PopUp flow conected block id bBlock.setBlockRunningInPopup(block.getPopupReturnBlockId()); // refresh block's cache bBlock.refreshCache(ui); // Add the block to the vector this._vFlow.add(bBlock); // keeps a reference to Start Block to build ForkJoin dependency // path if (bBlock.isStartBlock()) { blockStart = bBlock; } else if (bBlock.isEndBlock()) { if (alBlockEnd == null) alBlockEnd = new ArrayList<Block>(); alBlockEnd.add(bBlock); } htBlocks.put(blockId, bBlock); } // for Iterator<Integer> it = htPortMapIn.keySet().iterator(); while (it.hasNext()) { Integer key = (Integer) it.next(); Integer substId = (Integer) htPortMapIn.get(key); Block bBlock = (Block) htBlocks.get(substId); // blockIn Port[] inPorts = bBlock.getInPorts(ui); for (int ip = 0; inPorts != null && ip < inPorts.length; ip++) { if (inPorts[ip] == null) continue; Integer iConId = new Integer(inPorts[ip].getConnectedBlockId()); Block btmp = (Block) htBlocks.get(iConId); Port[] outPorts = btmp.getOutPorts(ui); for (int op = 0; outPorts != null && op < outPorts.length; op++) { if (outPorts[op] == null) continue; int iOutBlockId = outPorts[op].getConnectedBlockId(); if (iOutBlockId == (key.intValue() + offset)) { outPorts[op].setConnectedBlockId(substId.intValue()); } } } } it = htPortMapOut.keySet().iterator(); while (it.hasNext()) { Integer key = (Integer) it.next(); Integer substId = (Integer) htPortMapOut.get(key); Block bBlock = (Block) htBlocks.get(substId); // blockOut Port[] outPorts = bBlock.getOutPorts(ui); for (int op = 0; outPorts != null && op < outPorts.length; op++) { if (outPorts[op] == null) continue; Integer iConId = new Integer(outPorts[op].getConnectedBlockId()); Block btmp = (Block) htBlocks.get(iConId); Port[] inPorts = btmp.getInPorts(ui); for (int ip = 0; inPorts != null && ip < inPorts.length; ip++) { if (inPorts[ip] == null) continue; int iInBlockId = inPorts[ip].getConnectedBlockId(); if (iInBlockId == (key.intValue() + offset)) { inPorts[ip].setConnectedBlockId(substId.intValue()); } } } } // uncomment to check Port Mapping if (Const.CHECK_PORT_MAPPING) { // should return a warning if any bad block port exist Logger.debug("", this, "", "\n******* Checking Port Mapping *******\n"); it = htBlocks.keySet().iterator(); while (it.hasNext()) { Integer key = (Integer) it.next(); Block bBlock = (Block) htBlocks.get(key); Logger.debug("", this, "", "\nBlockId: " + key + " block: " + bBlock); if (bBlock == null) continue; Port[] ports = bBlock.getInPorts(ui); for (int i = 0; ports != null && i < ports.length; i++) { if (ports[i] == null) Logger.debug("", this, "", " null -> b"); else Logger.debug("", this, "", " " + ports[i].getConnectedPortName() + ": " + ports[i].getConnectedBlockId() + " -> b " + ports[i].getName()); } ports = bBlock.getOutPorts(ui); for (int i = 0; ports != null && i < ports.length; i++) { if (ports[i] == null) Logger.debug("", this, "", " b -> null"); else Logger.debug("", this, "", " " + ports[i].getName() + " b -> " + ports[i].getConnectedBlockId()); } } } return new InstantiationResult(blockStart, alBlockEnd); } @Deprecated private InstantiationResult instantiateSubFlow(UserInfoInterface ui, XmlBlock xmlblock, int anFlowId, List<FlowSetting> alSettings, Hashtable<Integer, Block> htBlocks, int offset) throws Exception { Class<?>[] argsClass = new Class[] { int.class, int.class, int.class, String.class }; String subflow = null; Attribute attrActiv = null; final int FLOW = 0; final int SUBFLOW = 1; final int TYPE = 2; offset += iOFFSET; int size = (xmlblock.getXmlAttributeCount() - 1) / 4; // raio de conta String[][] saInVars = new String[size][3]; String[][] saOutVars = new String[size][3]; // Attributes do block In & Out for (int attrNumber = 0; attrNumber < xmlblock.getXmlAttributeCount(); attrNumber++) { XmlAttribute xmlAttribute = xmlblock.getXmlAttribute(attrNumber); String name = xmlAttribute.getName(); int pos = -1; try { pos = Integer.parseInt(name.substring(8, 9)); } catch (NumberFormatException nfe) { } if (name.charAt(0) == 'I') { if (name.substring(1, 8).equals("bigflow")) { saInVars[pos][FLOW] = xmlAttribute.getValue(); } else { saInVars[pos][SUBFLOW] = xmlAttribute.getValue(); } } else if (name.charAt(0) == 'O') { if (name.substring(1, 8).equals("bigflow")) { saOutVars[pos][FLOW] = xmlAttribute.getValue(); } else { saOutVars[pos][SUBFLOW] = xmlAttribute.getValue(); } } else if (name.charAt(0) == 'M') { subflow = xmlAttribute.getValue(); } else if (name.charAt(0) == 'A') { attrActiv = new Attribute(xmlAttribute.getName(), xmlAttribute.getValue()); } else if (name.charAt(0) == 'T') { saInVars[pos][TYPE] = xmlAttribute.getValue(); saOutVars[pos][TYPE] = xmlAttribute.getValue(); } } if (!this.hasSubFlow(subflow)) { this._htSubFlows.put(subflow, subflow); } else { throw new Exception("Recursividade de Fluxos encontrada!"); } byte[] sXml = BeanFactory.getFlowHolderBean().readSubFlowData(ui, subflow); XmlFlow xmlSubFlow = FlowMarshaller.unmarshal(sXml); InstantiationResult flowResult = instantiateFlow(ui, xmlSubFlow, anFlowId, alSettings, htBlocks, offset); if (flowResult == null) { throw new Exception("Não foi possivel instanciar o subfluxo " + subflow); } else if (flowResult.start == null) { throw new Exception("O subfluxo " + subflow + " não tem BlockStart"); } else if (flowResult.end == null || flowResult.end.size() == 0) { throw new Exception("O subfluxo " + subflow + " não tem BlockEnd"); } if (!_htSubFlowEndPorts.containsKey(subflow)) { Hashtable<Integer, Object[]> htPorts = new Hashtable<Integer, Object[]>(); this.buildConnEndPorts(ui, htBlocks, htPorts, flowResult.start); _htSubFlowEndPorts.put(subflow, htPorts); } // remove the start & end blocks // replace them by BlockSubFlowIn & BlockSubFlowOut htBlocks.remove(new Integer(flowResult.start.getId())); this._vFlow.remove(flowResult.start); Iterator<Block> it = flowResult.getEndIterator(); while (it.hasNext()) { Block bEnd = it.next(); htBlocks.remove(new Integer(bEnd.getId())); this._vFlow.remove(bEnd); } // BlockSubFlowIn Integer blockIdIn = new Integer(flowResult.start.getId() - 100000); Object[] args = new Object[] { new Integer(anFlowId), blockIdIn, new Integer(0), new String(subflow) }; String className = "pt.iflow.blocks.BlockSubFlowIn"; Class<? extends Block> blockClassIn = loadBlockClass(ui, className); Constructor<? extends Block> argsConstructor = blockClassIn.getConstructor(argsClass); Block bBlockIn = argsConstructor.newInstance(args); // attributes for (int i = 0; i < saInVars.length; i++) { if (StringUtils.isEmpty(saInVars[i][FLOW]) || StringUtils.isEmpty(saInVars[i][SUBFLOW])) continue; Attribute attr = new Attribute(); attr.setName(saInVars[i][FLOW]); attr.setValue(saInVars[i][SUBFLOW]); bBlockIn.addAttribute(attr); attr = new Attribute("Type_" + saInVars[i][FLOW], saInVars[i][TYPE]); bBlockIn.addAttribute(attr); } // BlockSubFlowOut Integer blockIdOut = new Integer(flowResult.end.get(0).getId() - 100000); args = new Object[] { new Integer(anFlowId), blockIdOut, new Integer(0), new String(subflow) }; className = "pt.iflow.blocks.BlockSubFlowOut"; Class<? extends Block> blockClassOut = loadBlockClass(ui, className); argsConstructor = blockClassOut.getConstructor(argsClass); Block bBlockOut = argsConstructor.newInstance(args); for (int i = 0; i < saOutVars.length; i++) { if (saOutVars[i][FLOW] == null || saOutVars[i][FLOW].equals("") || saOutVars[i][SUBFLOW] == null || saOutVars[i][SUBFLOW].equals("")) continue; Attribute attr = new Attribute(); attr.setName(saOutVars[i][FLOW]); attr.setValue(saOutVars[i][SUBFLOW]); bBlockOut.addAttribute(attr); attr = new Attribute("Type_" + saOutVars[i][FLOW], saOutVars[i][TYPE]); bBlockOut.addAttribute(attr); } if (attrActiv != null) bBlockOut.addAttribute(attrActiv); // portos do BlockSubFlowIn Port port = null; try { XmlPort xmlPort = xmlblock.getXmlPort(0); // portIn -> portIn port = new Port(); port.setName("portIn"); port.setConnectedBlockId(xmlPort.getConnectedBlockId() + (offset - iOFFSET)); port.setConnectedPortName(xmlPort.getConnectedPortName()); Field fPort = blockClassIn.getField("portIn"); fPort.set(bBlockIn, port); port = new Port(); // portOutThread port.setName("portOutThread"); port.setConnectedBlockId(bBlockOut.getId()); port.setConnectedPortName("portInThread"); fPort = blockClassIn.getField("portOutThread"); fPort.set(bBlockIn, port); port = new Port(); // portOut port.setName("portOut"); fPort = blockClassIn.getField("portOut"); fPort.set(bBlockIn, port); Port[] patmp = flowResult.start.getOutPorts(ui); for (int p = 0; patmp != null && p < patmp.length; p++) { if (patmp[p] == null) continue; Integer iBId = new Integer(patmp[p].getConnectedBlockId()); Block bInnerBlock = (Block) htBlocks.get(iBId); if (bInnerBlock == null) continue; bInnerBlock.getInPorts(ui)[0].setConnectedBlockId(bBlockIn.getId()); bBlockIn.getOutPorts(ui)[0].setConnectedBlockId(patmp[p].getConnectedBlockId()); bBlockIn.getOutPorts(ui)[0].setConnectedPortName(patmp[p].getConnectedPortName()); } // xmlPort = xmlblock.getXmlPort(2); // portError -> portError // port = new Port(); // port.setName("portError"); // port.setConnectedBlockId(xmlPort.getConnectedBlockId() // + (offset - iOFFSET)); // port.setConnectedPortName(xmlPort.getConnectedPortName()); // fPort = blockClassIn.getField("portError"); // fPort.set(bBlockIn, port); } catch (Exception e) { e.printStackTrace(); throw new Exception("Erro ao criar porto " + port.getName() + " para o bloco SubFlowIn"); } // portos do BlockSubFlowOut try { port = new Port(); // portIn port.setName("portIn"); Field fPort = blockClassOut.getField("portIn"); fPort.set(bBlockOut, port); Hashtable<Integer, Object[]> htPorts = _htSubFlowEndPorts.get(subflow); Iterator<Integer> portIt = htPorts.keySet().iterator(); while (portIt.hasNext()) { Integer itmp = portIt.next(); Object[] otmp = (Object[]) htPorts.get(itmp); Port outPort = (Port) otmp[0]; outPort.setConnectedBlockId(bBlockOut.getId()); outPort.setConnectedPortName(port.getName()); bBlockOut.getInPorts(ui)[0].setConnectedBlockId(itmp.intValue()); bBlockOut.getInPorts(ui)[0].setConnectedPortName(outPort.getName()); } port = new Port(); // portInThread port.setName("portInThread"); port.setConnectedBlockId(bBlockIn.getId()); port.setConnectedPortName("portOutThread"); fPort = blockClassOut.getField("portInThread"); fPort.set(bBlockOut, port); XmlPort xmlPort = xmlblock.getXmlPort(1); // portSuccess -> portOut port = new Port(); port.setName("portOut"); port.setConnectedBlockId(xmlPort.getConnectedBlockId() + (offset - iOFFSET)); port.setConnectedPortName(xmlPort.getConnectedPortName()); fPort = blockClassOut.getField("portOut"); fPort.set(bBlockOut, port); // xmlPort = xmlblock.getXmlPort(2); // portError // port = new Port(); // port.setName("portError"); // port.setConnectedBlockId(xmlPort.getConnectedBlockId() // + (offset - iOFFSET)); // port.setConnectedPortName(xmlPort.getConnectedPortName()); // fPort = blockClassOut.getField("portError"); // fPort.set(bBlockOut, port); } catch (Exception e) { e.printStackTrace(); throw new Exception("Erro ao criar porto " + port.getName() + " para o bloco SubFlowOut"); } this._vFlow.add(bBlockIn); this._vFlow.add(bBlockOut); htBlocks.put(blockIdIn, bBlockIn); htBlocks.put(blockIdOut, bBlockOut); ArrayList<Block> altmp = new ArrayList<Block>(); altmp.add(bBlockOut); return new InstantiationResult(bBlockIn, altmp); } private void buildConnEndPorts(UserInfoInterface ui, Hashtable<Integer, Block> htBlocks, Hashtable<Integer, Object[]> htPorts, Block btmp) { Port[] ptmp = btmp.getOutPorts(ui); for (int p = 0; ptmp != null && p < ptmp.length; p++) { if (ptmp[p] == null) continue; Integer connId = new Integer(ptmp[p].getConnectedBlockId()); Block bEndtmp = (Block) htBlocks.get(connId); if (bEndtmp == null) continue; if (bEndtmp.isEndBlock()) { Object[] otmp = new Object[2]; otmp[0] = ptmp[p]; otmp[1] = bEndtmp; htPorts.put(new Integer(btmp.getId()), otmp); } this.buildConnEndPorts(ui, htBlocks, htPorts, bEndtmp); } } /* private void setCatalogueVar(String sVar, String sValue, DataTypeEnum sType, boolean isSearchable, String sPublicName, String sDefaultFormat) { setCatalogueVar(sVar, sValue, sType, null, isSearchable, sPublicName, sDefaultFormat); } */ private void setCatalogueVar(String sVar, String sValue, DataTypeEnum sType, String modelClass, boolean isSearchable, String sPublicName, String sDefaultFormat) { if (this._catalogue.hasVar(sVar)) return; this._catalogue.importDataType(sVar, sValue, sType, modelClass, isSearchable, sPublicName, sDefaultFormat); if (isSearchable && indexPosition < Const.INDEX_COLUMN_COUNT) this._hmIndexVars.put(sVar, indexPosition++); } private void setFlowSettingVar(FlowSetting settingVar) { if (this._catalogue.hasVar(settingVar.getName())) return; this._catalogue.importFlowSetting(settingVar.getFlowId(), settingVar.getName(), settingVar.getDescription()); } public ProcessCatalogue getCatalogue() { return this._catalogue; } private void instantiateMailStartSettings(UserInfoInterface ui, Block startBlock) { _mailStartSettings = MailStartSettings.parse(startBlock); } private Block instantiateDetailBlock(UserInfoInterface ui, Block startBlock, String flowName) throws Exception { // Integer blockId = startBlock.getId(); _detailForm = null; String buildDetailForm = startBlock.getAttribute(sDETAIL_FORM); if (StringUtils.equalsIgnoreCase("no", buildDetailForm)) { this._hasDetail = false; return null; } else { this._hasDetail = true; // if not "form" or sDETAIL_FORM_EXISTINGBLOCKFORM, assumes "default" if (!(StringUtils.equalsIgnoreCase("form", buildDetailForm) || StringUtils.equalsIgnoreCase(sDETAIL_FORM_EXISTINGBLOCKFORM, buildDetailForm))) return null; } Class<? extends Block> blockClass = null; try { // force block to be a BlockDetailForm and not a BlockFormulario String className = BLOCK_PACKAGE + "BlockDetailForm";// startBlock.getAttribute(sDETAIL_CLASS); if (null == className) return null; blockClass = loadBlockClass(ui, className); } catch (ClassNotFoundException cnfe) { throw new Exception("Erro ao criar bloco de detalhe de processo", cnfe); } Logger.debug(null, this, "constructor", "Processing block " + blockClass.getName()); Constructor<? extends Block> argsConstructor = blockClass.getConstructor(int.class, int.class, int.class, String.class); Block bBlock = argsConstructor.newInstance(startBlock.getFlowId(), startBlock.getId(), startBlock.getSubFlowBlockId(), flowName); if (StringUtils.equalsIgnoreCase("form", buildDetailForm)) { HashMap<String, String> hmAttrs = startBlock.getAttributeMap(); // Attributes for (String name : hmAttrs.keySet()) { String value = startBlock.getAttribute(name); if (!name.startsWith(IFlowData.sDETAIL)) { continue; } Attribute attribute = new Attribute(); attribute.setName(name.substring(IFlowData.sDETAIL.length())); attribute.setValue(value); bBlock.addAttribute(attribute); } } else if (StringUtils.equalsIgnoreCase(sDETAIL_FORM_EXISTINGBLOCKFORM, buildDetailForm)) { int formBlockId = Integer.parseInt(startBlock.getAttribute(sDETAIL_FORM_BID)); Block bf = this.getBlock(formBlockId); HashMap<String, String> hmAttrs = bf.getAttributeMap(); // Attributes for (String name : hmAttrs.keySet()) { String value = bf.getAttribute(name); bBlock.addAttribute(new Attribute(name, value)); } bBlock.addAttribute(new Attribute(FormProps.READ_ONLY, "true")); } // clear cache bBlock.refreshCache(ui); _detailForm = bBlock; return bBlock; } private void saveForkJoinDepPath(UserInfoInterface userInfo) { String login = userInfo.getUtilizador(); DataSource ds = Utils.getDataSource(); Connection db = null; Statement st = null; try { db = ds.getConnection(); db.setAutoCommit(false); st = db.createStatement(); // clean former deploys st.executeUpdate("delete from forkjoin_state_dep where flowid=" + this._nId); st.executeUpdate("delete from forkjoin_hierarchy where flowid=" + this._nId); st.executeUpdate("delete from forkjoin_blocks where flowid=" + this._nId); // fill the block table Enumeration<ForkJoinDep> enumer = _htForkJoinDepPath.elements(); while (enumer.hasMoreElements()) { ForkJoinDep fjp = enumer.nextElement(); st.executeUpdate("insert into forkjoin_blocks (flowid, blockid, type) " + "values (" + this._nId + "," + fjp.getBlockId() + "," + fjp.getType() + ")"); } // now fill the 2 dependency tables enumer = _htForkJoinDepPath.elements(); while (enumer.hasMoreElements()) { ForkJoinDep fjp = enumer.nextElement(); // build fork/join hierarchy Enumeration<ForkJoinDep> enumJFStates = fjp.elementsJFStates(); while (enumJFStates.hasMoreElements()) { ForkJoinDep fjpSon = enumJFStates.nextElement(); st.executeUpdate("insert into forkjoin_hierarchy (flowid, " + "parentblockid, blockid) values (" + this._nId + "," + fjp.getBlockId() + "," + fjpSon.getBlockId() + ")"); } // build fork/join state dependencies Iterator<Integer> itStates = fjp.iteratorStates(); while (itStates.hasNext()) { Integer iState = itStates.next(); st.executeUpdate("insert into forkjoin_state_dep (flowid, " + "parentblockid, blockid) values (" + this._nId + "," + fjp.getBlockId() + "," + iState + ")"); } } db.commit(); } catch (SQLException sqle) { Logger.error(login, this, "saveForkJoinDepPath", "caught sql exception: " + sqle.getMessage()); sqle.printStackTrace(); try { db.rollback(); } catch (Exception e) { } } catch (Exception e) { Logger.error(login, this, "saveForkJoinDepPath", "caught exception: " + e.getMessage()); e.printStackTrace(); try { db.rollback(); } catch (Exception el) { } } finally { DatabaseInterface.closeResources(db, st); } } private void buildForkJoinDepPathImpl(UserInfoInterface userInfo, Hashtable<Integer, Block> htBlocks, Set<Integer> alStates, Block block, ForkJoinDep lastFJD) { if (block == null || block.isEndBlock()) return; Integer blockId = new Integer(block.getId()); if (alStates.contains(blockId)) return; if (_hsAllStates.contains(blockId)) return; if (lastFJD != null && lastFJD.hasDependency(blockId)) return; Port[] outports = block.getOutPorts(userInfo); Integer nextBlockId = null; Block nextBlock = null; if (block.getClass().getName().indexOf("BlockSincronizacao") != -1 || block.getClass().getName().indexOf("JuncaoExclusiva") != -1) { if (_htForkJoinDepPath.containsKey(blockId)) { if (lastFJD == null || !lastFJD.hasDependency(blockId)) { ForkJoinDep fjd = _htForkJoinDepPath.get(blockId); if (lastFJD != null) fjd.addJFState(lastFJD); fjd.addStates(alStates); _hsAllStates.add(alStates); } // other branch already passed here, so do not continue // recursion } else { ForkJoinDep fjd = new ForkJoinDep(blockId, ForkJoinDep.JOIN, alStates); if (lastFJD != null) fjd.addJFState(lastFJD); _htForkJoinDepPath.put(blockId, fjd); for (int i = 0; outports != null && i < outports.length; i++) { if (outports[i] == null) continue; nextBlockId = new Integer(outports[i].getConnectedBlockId()); nextBlock = htBlocks.get(nextBlockId); this.buildForkJoinDepPathImpl(userInfo, htBlocks, new HashSet<Integer>(), nextBlock, fjd); } } } else if (block.getClass().getName().indexOf("BlockBifurcacao") != -1) { ForkJoinDep fjd = new ForkJoinDep(blockId, ForkJoinDep.FORK, alStates); if (lastFJD != null) fjd.addJFState(lastFJD); _htForkJoinDepPath.put(blockId, fjd); for (int i = 0; outports != null && i < outports.length; i++) { if (outports[i] == null) continue; nextBlockId = new Integer(outports[i].getConnectedBlockId()); nextBlock = htBlocks.get(nextBlockId); this.buildForkJoinDepPathImpl(userInfo, htBlocks, new HashSet<Integer>(), nextBlock, fjd); } } else { if (!block.isStartBlock()) alStates.add(blockId); for (int i = 0; outports != null && i < outports.length; i++) { if (outports[i] == null) continue; nextBlockId = new Integer(outports[i].getConnectedBlockId()); nextBlock = htBlocks.get(nextBlockId); this.buildForkJoinDepPathImpl(userInfo, htBlocks, new HashSet<Integer>(alStates), nextBlock, lastFJD); } } } // TODO finish private void buildForkJoinDepPath(UserInfoInterface userInfo, Hashtable<Integer, Block> htBlocks, Set<Integer> alStates, Block block, ForkJoinDep lastFJD) { // So vale a pena gastar CPU a percorrer grafos se existirem blocos // bifurcao, sincronizao ou juno boolean blockFound = false; for (Block b : htBlocks.values()) { String name = b.getClass().getName(); // TODO encontrar uma forma mais elegante de efectuar este teste. if (name.contains("BlockSincronizacao") || name.contains("JuncaoExclusiva") || name.contains("BlockBifurcacao")) { blockFound = true; break; } } if (!blockFound) return; buildForkJoinDepPathImpl(userInfo, htBlocks, alStates, block, lastFJD); } /** * Checks if flow is guest accessible. * * @param userInfo * User information. * @return True if the flow is constructed in a way that allows unregistered * users to access it, false otherwise. */ public boolean isGuestCompatible(UserInfoInterface userInfo) { if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "isGuestCompatible(UserInfoInterface)", "start"); } FlowSetting procLocation = BeanFactory.getFlowSettingsBean().getFlowSetting(this.getId(), Const.sPROCESS_LOCATION); if (StringUtilities.isEqual(procLocation.getValue(), Const.sPROCESS_IN_DB)) { if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "isGuestCompatible(UserInfoInterface)", "process location set to db... returning 'false'."); } return false; } Vector<Block> blockVector = this.getFlow(); // search for start block Block startBlock = null; for (Block currentBlock : blockVector) { if (currentBlock.isStartBlock()) { startBlock = currentBlock; break; } } boolean result = searchDeep(userInfo, startBlock, new HashSet<Integer>()); if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "isGuestCompatible(UserInfoInterface)", "end : returning '" + result + "'."); } return result; } private boolean searchDeep(UserInfoInterface userInfo, Block currentBlock, HashSet<Integer> processedBlocks) { if (currentBlock == null) { return false; } if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "searchDeep(UserInfoInterface,Block)", "start : block id=" + currentBlock.getId() + " (isForwardBlock?" + currentBlock.isForwardBlock() + ", isEndBlock?" + currentBlock.isEndBlock() + ", isProcInDBRequired?" + currentBlock.isProcInDBRequired() + ", " + currentBlock.getClass().getName() + ")."); } if (currentBlock.isForwardBlock() || currentBlock.isEndBlock()) { if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "searchDeep(UserInfoInterface,Block)", "end : block id=" + currentBlock.getId() + ". Found " + (currentBlock.isForwardBlock() ? "forward" : "end") + " block, returning 'true'."); } return true; } else if (currentBlock.isProcInDBRequired()) { if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "searchDeep(UserInfoInterface,Block)", "end : block id=" + currentBlock.getId() + ". Unable to proceed with search from this block on: " + "isProcInDBRequired, returning 'false'."); } return false; } List<Block> queue = getChildBlocks(currentBlock); for (Block block : queue) { if (processedBlocks.contains(block.getId())) { Logger.info(userInfo.getUtilizador(), this, "searchDeep", "Already processed child block " + block.getId() + " for block " + currentBlock.getId()); continue; } processedBlocks.add(block.getId()); try { if (!searchDeep(userInfo, block, processedBlocks)) { if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "searchDeep(UserInfoInterface,Block)", "end : block id=" + currentBlock.getId() + ". Interrupted deep search algorithm, returning 'false'."); } return false; } } catch (StackOverflowError ex) { Logger.warning(userInfo.getUtilizador(), this, "searchDeep", "Stack overflow, returning 'false'!"); return false; } } if (Logger.isDebugEnabled()) { Logger.debug(userInfo.getUtilizador(), this, "searchDeep(UserInfoInterface,Block)", "end : block id=" + currentBlock.getId() + ". Finished deep search algorithm, returning 'true'."); } return true; } private List<Block> getChildBlocks(Block block) { List<Block> result = new ArrayList<Block>(); Port[] ports = block.getOutPorts(null); for (Port port : ports) { result.add(getBlock(port.getConnectedBlockId())); } return result; } private Block getBlock(int blockId) { Block result = null; Vector<Block> blockVector = this.getFlow(); for (Block currentBlock : blockVector) { if (currentBlock.getId() == blockId) { result = currentBlock; break; } } return result; } public int getId() { return this._nId; } public String getName() { return new String(this._sName); } public String getFileName() { return new String(this._sFile); } public boolean isOnline() { return this._bOnline; } protected void setOnline(boolean abOnline) { this._bOnline = abOnline; } public boolean isDeployed() { return this._bDeployed; } public boolean hasSubFlow(String subflow) { return this._htSubFlows.containsKey(subflow); } private void setDeployed(boolean abDeployed) { this._bDeployed = abDeployed; } public String getApplicationId() { return _sApplicationId; } public void setApplicationId(String applicationId) { _sApplicationId = applicationId; } public String getApplicationName() { return _sApplicationName; } public void setApplicationName(String applicationName) { _sApplicationName = applicationName; } public boolean hasError() { if (this._sError != null && !this._sError.equals("")) { return true; } return false; } public String getError() { return this._sError; } protected void setError(String asError) { this._sError = asError; } /** * Retrieves the blocks pertaining to this flow. * * @return Block vector */ public Vector<Block> getFlow() { return this._vFlow; } public Map<String, Integer> getIndexVars() { return this._hmIndexVars; } public String[] getIndexVarStrings() { String[] vars = new String[Const.INDEX_COLUMN_COUNT]; for (String name : this._hmIndexVars.keySet()) { int pos = this._hmIndexVars.get(name); vars[pos] = name; } return vars; } public static FlowDataConvert[] toFlowDataConvertArray(FlowData[] fd) { FlowDataConvert[] fdc = new FlowDataConvert[fd.length]; for (int i = 0; i < fdc.length; i++) { fdc[i] = fd[i].toFlowDataConvert(); } return fdc; } public FlowDataConvert toFlowDataConvert() { FlowDataConvert fdc = new FlowDataConvert(); fdc.setBLOCK_PACKAGE(BLOCK_PACKAGE); fdc.setiOFFSET(this.iOFFSET); fdc.setIndexPosition(this.indexPosition); //Probably deletable fdc.setFlowType(this.flowType.getCode()); fdc.setMaxBlockId(this.maxBlockId); fdc.set_nId(this._nId); fdc.set_sName(this._sName); fdc.set_sFile(this._sFile); //_vFlow has blocks, AXIS has problems with custom type Block, perphaps all blocks types needs mapping in wsdd //fdc.set_vFlow(this._vFlow); fdc.set_bOnline(this._bOnline); fdc.set_bDeployed(this._bDeployed); fdc.set_sApplicationId(this._sApplicationId); fdc.set_sApplicationName(this._sApplicationName); fdc.set_sError(this._sError); fdc.set_organizationId(this._organizationId); fdc.set_lastModified(this._lastModified); fdc.set_created(this._created); fdc.set_hmIndexVars(this._hmIndexVars); fdc.set_hasDetail(this._hasDetail); //_detailForm has blocks, AXIS has problems with custom type Block, perphaps all blocks types needs mapping in wsdd //fdc.set_detailForm(this._detailForm); fdc.set_seriesId(this._seriesId); //fdc.set_catalogue(this._catalogue.toProcessCatalogueConvert()); fdc.set_hmFormTemplates(this._hmFormTemplates); /*if (this._mailStartSettings != null) { fdc.set_mailStartSettings(this._mailStartSettings.toMailStartSettingsConvert()); }*/ if (this.flowClassFile != null) { try { fdc.setFlowClassFile(this.flowClassFile.toFlowClassGeneratorConvert()); } catch (Exception e) { Logger.warning(null, this, "toFlowDataConvert", "flowClassFile could not assigned"); } } fdc.set_htSubFlowEndPorts(this._htSubFlowEndPorts); fdc.set_htForkJoinDepPath(toHtForkJoinDepConvert(this._htForkJoinDepPath)); fdc.set_hsAllStates(this._hsAllStates); fdc.set_htSubFlows(this._htSubFlows); return fdc; } static Hashtable<Integer, ForkJoinDepConvert> toHtForkJoinDepConvert(Hashtable<Integer, ForkJoinDep> htfjd) { Enumeration e = htfjd.keys(); Hashtable<Integer, ForkJoinDepConvert> ht = new Hashtable<Integer, ForkJoinDepConvert>(); while (e.hasMoreElements()) { Integer iKey = (Integer) e.nextElement(); ForkJoinDepConvert fjdc = htfjd.get(iKey).toForkJoinDepConvert(); ht.put(iKey, fjdc); } return ht; } /** * * @author ptgm * * ForkJoinDep Fork & Join Dependency Path */ public class ForkJoinDep { public static final int FORK = 0; public static final int JOIN = 1; private Integer _blockId = null; private int _type = -1; // list of states that are behind this block until next fork/join private Set<Integer> _hsStates = new HashSet<Integer>(); // list of fork/join states that are behind with their own dependencies private Hashtable<Integer, ForkJoinDep> _htJFStates = new Hashtable<Integer, ForkJoinDep>(); public ForkJoinDep(Integer blockId, int type, Set<Integer> hsStates) { _blockId = blockId; _type = type; _hsStates = hsStates; _htJFStates = new Hashtable<Integer, ForkJoinDep>(); } public boolean hasDependency(Integer blockId) { if (_htJFStates.containsKey(blockId)) return true; Enumeration<ForkJoinDep> enumJF = this.elementsJFStates(); while (enumJF.hasMoreElements()) { ForkJoinDep fjd = enumJF.nextElement(); if (fjd.hasDependency(blockId)) return true; } return false; } public Integer getBlockId() { return _blockId; } public int getType() { return _type; } public void addStates(Set<Integer> moreStates) { _hsStates.addAll(moreStates); } public Iterator<Integer> iteratorStates() { return _hsStates.iterator(); } public void addJFState(ForkJoinDep btp) { _htJFStates.put(btp.getBlockId(), btp); } public ForkJoinDep getJFState(Integer blockId) { return (ForkJoinDep) _htJFStates.get(blockId); } public Enumeration<ForkJoinDep> elementsJFStates() { return _htJFStates.elements(); } public String toString() { StringBuffer sbtmp = new StringBuffer(); sbtmp.append("\nBlockID: ").append(_blockId); if (_type == FORK) sbtmp.append(" FORK"); else sbtmp.append(" JOIN"); sbtmp.append("\nState List: "); Iterator<Integer> it = this.iteratorStates(); boolean first = true; while (it.hasNext()) { if (!first) sbtmp.append(", "); sbtmp.append(it.next()); first = false; } sbtmp.append("\nFORK JOIN State List: "); Enumeration<ForkJoinDep> enumer = this.elementsJFStates(); first = true; while (enumer.hasMoreElements()) { if (!first) sbtmp.append(", "); ForkJoinDep fjp = enumer.nextElement(); sbtmp.append(fjp.getBlockId()); first = false; } return sbtmp.toString(); } public ForkJoinDepConvert toForkJoinDepConvert() { ForkJoinDepConvert fjdc = new ForkJoinDepConvert(); fjdc.setFORK(FORK); fjdc.setJOIN(JOIN); fjdc.set_blockId(_blockId); fjdc.set_type(_type); fjdc.set_hsStates(_hsStates); fjdc.set_htJFStates(toHtForkJoinDepConvert(this._htJFStates)); return fjdc; } } static class ForbiddenBlockException extends SecurityException { /** * */ private static final long serialVersionUID = -551535203284838499L; String msg; ForbiddenBlockException(String block) { super(); this.msg = MessageFormat.format("A licena no permite blocos do tipo {0}.", new Object[] { block }); ; } public String getMessage() { return msg; } } public String getOrganizationId() { return _organizationId; } protected void setOrganizationId(String organizationId) { _organizationId = organizationId; } public boolean runMaximized() { boolean retValue = false; FlowSetting setting = BeanFactory.getFlowSettingsBean().getFlowSetting(this.getId(), Const.sRUN_MAXIMIZED); if (null != setting && !StringUtils.isEmpty(setting.getValue()) && setting.getValue().equals(Const.sRUN_MAXIMIZED_YES)) { retValue = true; } return retValue; } public long getLastModified() { return this._lastModified; } public long getCreated() { return this._created; } public boolean hasDetail() { return this._hasDetail; } public Block getDetailForm() { return this._detailForm; } public int getSeriesId() { return this._seriesId; } public void setSeriesId(int seriesId) { this._seriesId = seriesId; } private static class InstantiationResult { private Block start = null; private List<Block> end = null; private InstantiationResult(Block start, List<Block> end) { this.start = start; this.end = end; } private Iterator<Block> getEndIterator() { if (null == end) return null; return end.iterator(); } } @SuppressWarnings("unchecked") private Class<? extends Block> loadBlockClass(UserInfoInterface ui, String className) throws ClassNotFoundException { Class<? extends Block> clazz = null; try { clazz = (Class<? extends Block>) BeanFactory.getRepBean().loadClass(ui, className); } catch (ClassNotFoundException e) { clazz = (Class<? extends Block>) Class.forName(className); } return clazz; } // template loading and retrieving private void loadFormTemplates(UserInfoInterface userInfo, XmlFlow aXmlFlow) { XmlFormTemplate[] templates = aXmlFlow.getXmlFormTemplate(); if (null == templates || templates.length == 0) return; Marshaller<Form> marshaller = Marshaller.create(Form.class); for (XmlFormTemplate xmlFormTemplate : templates) { String templateName = xmlFormTemplate.getName(); try { Form template = marshaller.unmarshall(new JSONObject(xmlFormTemplate.getValue())); _hmFormTemplates.put(templateName, template); } catch (JSONException e) { Logger.warning(userInfo.getUtilizador(), this, "loadFormTemplates", "Could not unmarshall form template: " + templateName, e); } } } public Form getFormTemplate(String name) { return _hmFormTemplates.get(name); } public MailStartSettings getMailSettings() { return _mailStartSettings; } public FlowType getFlowType() { return flowType; } public void setFlowType(FlowType flowType) { this.flowType = flowType; } public void setFlowType(String typeCode) { this.flowType = FlowType.getFlowType(typeCode); } public boolean isVisibleInMenu() { boolean retValue = true; FlowSetting setting = BeanFactory.getFlowSettingsBean().getFlowSetting(this.getId(), Const.sFLOW_MENU_ACCESSIBLE); if (null == setting || StringUtils.isEmpty(setting.getValue()) || setting.getValue().equals(Const.sFLOW_MENU_ACCESSIBLE_YES)) { retValue = true; } else { retValue = false; } return retValue; } public boolean hasSchedules() { return hasSchedules; } public void setHasSchedules(boolean hasSchedules) { this.hasSchedules = hasSchedules; } public void setMaxBlockId(int maxBlockId) { this.maxBlockId = maxBlockId; } public int getMaxBlockId() { return maxBlockId; } } class FlowClassGenerator { private UserInfoInterface userInfo; private StringBuilder header; private StringBuilder footer; private StringBuilder content; private String linesep = System.getProperty("line.separator"); public FlowClassGenerator(UserInfoInterface userInfo, int flowid) { if (!canGenerate()) { return; } this.userInfo = userInfo; header = new StringBuilder(); header.append("//your package here.. perhaps package flow").append(flowid).append(";").append(linesep) .append(linesep); header.append("import pt.iflow.api.processdata.ProcessData;").append(linesep); header.append("import pt.iflow.api.utils.UserInfoInterface;").append(linesep).append(linesep); header.append("//your imports here.. ").append(linesep).append(linesep); header.append("public abstract class Flow").append(flowid).append(" {").append(linesep).append(linesep); header.append(" protected UserInfoInterface userInfo;").append(linesep); header.append(" protected ProcessData procData;").append(linesep); content = new StringBuilder(); footer = new StringBuilder(); footer.append(linesep); footer.append(" // metodos que podem estar implementados na beanshell").append(linesep); footer.append(" public Object eval(String s) {").append(linesep); footer.append(" return null;").append(linesep); footer.append(" }").append(linesep); footer.append(linesep); footer.append(" // implementar este mtodo").append(linesep); footer.append(" public abstract void execute() throws Exception;").append(linesep); footer.append("}").append(linesep); } public void addVar(DataTypeEnum type, String varname, String modelsClass) { if (!canGenerate()) { return; } ProcessDataType pdt = type.newDataTypeInstance(); if (pdt == null) return; if (type.isAbstractModel()) { ((ModelsDataType) pdt).setClass(modelsClass); } String supportingClass = pdt.getSupportingClass().getName(); if (StringUtils.equals(supportingClass, "java.lang.String")) supportingClass = "String"; content.append(" protected ").append(supportingClass).append((type.isList() ? "[]" : "")).append(" _") .append(varname).append(";").append(linesep); } public String getContent() { if (!canGenerate()) { return null; } return header.toString() + content.toString() + footer.toString(); } public void writeContent() { if (!canGenerate()) { return; } Logger.debug(userInfo.getUtilizador(), this, "writeContent", "Flow beanshell helper class file: " + linesep + linesep + getContent() + linesep); } private boolean canGenerate() { return Const.nMODE == Const.nDEVELOPMENT; } public FlowClassGeneratorConvert toFlowClassGeneratorConvert() throws Exception { FlowClassGeneratorConvert fcgc = new FlowClassGeneratorConvert(); fcgc.setHeader(this.header.toString()); fcgc.setFooter(this.footer.toString()); fcgc.setContent(this.content.toString()); fcgc.setLinesep(this.linesep); return fcgc; } }