diff --git a/modules/activiti-cxf/src/main/java/org/activiti/engine/impl/webservice/WSDLImporter.java b/modules/activiti-cxf/src/main/java/org/activiti/engine/impl/webservice/WSDLImporter.java index 3ba9283be224914da9a8891776bd38d6b67c87ca..9206bb702ec0c9aaba3fade40debf1d07b9e9383 100644 --- a/modules/activiti-cxf/src/main/java/org/activiti/engine/impl/webservice/WSDLImporter.java +++ b/modules/activiti-cxf/src/main/java/org/activiti/engine/impl/webservice/WSDLImporter.java @@ -33,8 +33,8 @@ import javax.wsdl.xml.WSDLReader; import javax.xml.namespace.QName; import org.activiti.engine.ActivitiException; -import org.activiti.engine.impl.bpmn.SimpleStructure; -import org.activiti.engine.impl.bpmn.Structure; +import org.activiti.engine.impl.bpmn.SimpleStructureDefinition; +import org.activiti.engine.impl.bpmn.StructureDefinition; import org.activiti.engine.impl.bpmn.parser.BpmnParse; import org.activiti.engine.impl.bpmn.parser.XMLImporter; import org.activiti.engine.impl.util.ReflectUtil; @@ -60,27 +60,22 @@ import com.sun.tools.xjc.api.XJC; */ public class WSDLImporter implements XMLImporter { - -// This class should be refactored to use our own parser like this: -// Parser wsdlImportParser = new Parser(); -// Element rootElement = wsdlImportParser.createParse() -// .sourceUrl(this.wsdlLocation) -// .execute() -// .getRootElement(); -// -// Element typesElement = rootElement.elementNS("the-wsdl-namespace-uri", "types"); -// Element schemaElement = typesElement.elementNS("the-wsdl-namespace-uri", "schema"); - - protected Map wsServices = new HashMap(); protected Map wsOperations = new HashMap(); - protected Map structures = new HashMap(); + protected Map structures = new HashMap(); protected String wsdlLocation; + + protected String namespace; + + public WSDLImporter() { + this.namespace = ""; + } public void importFrom(org.activiti.engine.impl.util.xml.Element element, BpmnParse parse) { + this.namespace = element.attribute("namespace") == null ? "" : element.attribute("namespace") + ":"; this.importFrom(element.attribute("location")); this.transferImportsToParse(parse); } @@ -120,7 +115,7 @@ public class WSDLImporter implements XMLImporter { for (Object serviceObject : definition.getServices().values()) { Service service = (Service) serviceObject; WSService wsService = this.importService(service); - this.wsServices.put(wsService.getName(), wsService); + this.wsServices.put(this.namespace + wsService.getName(), wsService); Port port = (Port) service.getPorts().values().iterator().next(); for (Object bindOperationObject : port.getBinding().getBindingOperations()) { @@ -128,7 +123,7 @@ public class WSDLImporter implements XMLImporter { WSOperation operation = this.processOperation(bindOperation.getOperation(), wsService); wsService.addOperation(operation); - this.wsOperations.put(operation.getName(), operation); + this.wsOperations.put(this.namespace + operation.getName(), operation); } } } @@ -149,12 +144,12 @@ public class WSDLImporter implements XMLImporter { } } - WSService wsService = new WSService(name, location, this.wsdlLocation); + WSService wsService = new WSService(this.namespace + name, location, this.wsdlLocation); return wsService; } private WSOperation processOperation(Operation wsOperation, WSService service) { - WSOperation operation = new WSOperation(wsOperation.getName(), service); + WSOperation operation = new WSOperation(this.namespace + wsOperation.getName(), wsOperation.getName(), service); return operation; } @@ -182,7 +177,7 @@ public class WSDLImporter implements XMLImporter { private void importStructure(Mapping mapping) { QName qname = mapping.getElement(); JDefinedClass theClass = (JDefinedClass) mapping.getType().getTypeClass(); - SimpleStructure structure = (SimpleStructure) this.structures.get(qname.getLocalPart()); + SimpleStructureDefinition structure = (SimpleStructureDefinition) this.structures.get(this.namespace + qname.getLocalPart()); Map fields = theClass.fields(); int index = 0; @@ -204,8 +199,8 @@ public class WSDLImporter implements XMLImporter { NodeList complexTypes = rootTypes.getElementsByTagName("xs:complexType"); for (int i = 0; i < complexTypes.getLength(); i++) { Element element = (Element) complexTypes.item(i); - String structureName = element.getAttribute("name"); - SimpleStructure structure = new SimpleStructure(structureName); + String structureName = this.namespace + element.getAttribute("name"); + SimpleStructureDefinition structure = new SimpleStructureDefinition(structureName); this.structures.put(structure.getId(), structure); } } @@ -227,7 +222,7 @@ public class WSDLImporter implements XMLImporter { private void transferImportsToParse(BpmnParse parse) { if (parse != null) { - for (Structure structure : this.structures.values()) { + for (StructureDefinition structure : this.structures.values()) { parse.addStructure(structure); } for (WSService service : this.wsServices.values()) { @@ -239,7 +234,7 @@ public class WSDLImporter implements XMLImporter { } } - public Collection getStructures() { + public Collection getStructures() { return this.structures.values(); } diff --git a/modules/activiti-cxf/src/test/java/org/activiti/engine/impl/webservice/WSDLImporterTest.java b/modules/activiti-cxf/src/test/java/org/activiti/engine/impl/webservice/WSDLImporterTest.java index 07e0ad73004984d263ced9d74d2f30bf4c68c752..aeb5cc48f88eee55b8925000f3b97dec1255bff3 100644 --- a/modules/activiti-cxf/src/test/java/org/activiti/engine/impl/webservice/WSDLImporterTest.java +++ b/modules/activiti-cxf/src/test/java/org/activiti/engine/impl/webservice/WSDLImporterTest.java @@ -20,8 +20,8 @@ import java.util.List; import junit.framework.Assert; -import org.activiti.engine.impl.bpmn.SimpleStructure; -import org.activiti.engine.impl.bpmn.Structure; +import org.activiti.engine.impl.bpmn.SimpleStructureDefinition; +import org.activiti.engine.impl.bpmn.StructureDefinition; import org.activiti.engine.impl.util.ReflectUtil; import org.activiti.engine.impl.webservice.WSDLImporter; import org.activiti.engine.impl.webservice.WSOperation; @@ -46,9 +46,9 @@ public class WSDLImporterTest { Assert.assertEquals("Counter", service.getName()); Assert.assertEquals("http://localhost:63081/counter", service.getLocation()); - List structures = new ArrayList(importer.getStructures()); - Collections.sort(structures, new Comparator() { - public int compare(Structure o1, Structure o2) { + List structures = new ArrayList(importer.getStructures()); + Collections.sort(structures, new Comparator() { + public int compare(StructureDefinition o1, StructureDefinition o2) { return o1.getId().compareTo(o2.getId()); } }); @@ -89,14 +89,14 @@ public class WSDLImporterTest { Assert.assertEquals(service, wsOperation.getService()); } - private void assertStructure(Structure structure, String structureId, String[] parameters, Class[] classes) { - SimpleStructure simpleStructure = (SimpleStructure) structure; + private void assertStructure(StructureDefinition structure, String structureId, String[] parameters, Class[] classes) { + SimpleStructureDefinition simpleStructure = (SimpleStructureDefinition) structure; Assert.assertEquals(structureId, simpleStructure.getId()); - for (int i = 0; i < structure.getFieldSize(); i++) { - Assert.assertEquals(parameters[i], structure.getFieldNameAt(i)); - Assert.assertEquals(classes[i], structure.getFieldTypeAt(i)); + for (int i = 0; i < simpleStructure.getFieldSize(); i++) { + Assert.assertEquals(parameters[i], simpleStructure.getFieldNameAt(i)); + Assert.assertEquals(classes[i], simpleStructure.getFieldTypeAt(i)); } } } diff --git a/modules/activiti-engine/pom.xml b/modules/activiti-engine/pom.xml index 71cad73514510fa738de37fdd5bba2b3f2b25bab..9cf30f59dda73eecbcbfb6012beb4e2a1b9267f2 100644 --- a/modules/activiti-engine/pom.xml +++ b/modules/activiti-engine/pom.xml @@ -58,8 +58,17 @@ org.apache.openjpa openjpa test + + + commons-lang + commons-lang + + - + + commons-lang + commons-lang + org.apache.commons diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructure.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructureDefinition.java similarity index 65% rename from modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructure.java rename to modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructureDefinition.java index 1604c0a604ce6f2de931528a7030a791da7a99e6..9d0b3e30f094f48e5e73da62f1f913d0591ef58f 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructure.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ClassStructureDefinition.java @@ -17,28 +17,41 @@ package org.activiti.engine.impl.bpmn; * * @author Esteban Robles Luna */ -public class ClassStructure implements Structure { +public class ClassStructureDefinition implements FieldBaseStructureDefinition { - protected Class classStructure; + protected String id; - public ClassStructure(Class classStructure) { + protected Class< ? > classStructure; + + public ClassStructureDefinition(Class classStructure) { + this(classStructure.getName(), classStructure); + } + + public ClassStructureDefinition(String id, Class classStructure) { + this.id = id; this.classStructure = classStructure; } public String getId() { - return this.classStructure.getName(); + return this.id; } public int getFieldSize() { - //TODO + // TODO return 0; } public String getFieldNameAt(int index) { + // TODO return null; } public Class< ? > getFieldTypeAt(int index) { + // TODO return null; } + + public StructureInstance createInstance() { + return new FieldBaseStructureInstance(this); + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataAssociation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataInputAssociation.java similarity index 89% rename from modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataAssociation.java rename to modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataInputAssociation.java index 563fac985c3b6c855837f773d0f396ffa4385f47..68f1b10c4075c49e650a9d5387e018d24e2a85d9 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataAssociation.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataInputAssociation.java @@ -18,11 +18,11 @@ import java.util.List; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; /** - * A data association between a source and a target + * A data input association between a source and a target * * @author Esteban Robles Luna */ -public class DataAssociation { +public class DataInputAssociation { protected String source; @@ -30,7 +30,7 @@ public class DataAssociation { protected List assignments; - public DataAssociation(String source, String target) { + public DataInputAssociation(String source, String target) { this.source = source; this.target = target; this.assignments = new ArrayList(); diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataOutputAssociation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataOutputAssociation.java new file mode 100644 index 0000000000000000000000000000000000000000..e7dace28086a0e525cac94d346a10a322d25029c --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/DataOutputAssociation.java @@ -0,0 +1,37 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +import org.activiti.engine.impl.el.Expression; +import org.activiti.engine.impl.pvm.delegate.ActivityExecution; + +/** + * A data output association between a source and a target + * + * @author Esteban Robles Luna + */ +public class DataOutputAssociation { + + protected String targetRef; + + protected Expression transformation; + + public DataOutputAssociation(String targetRef, Expression transformation) { + this.targetRef = targetRef; + this.transformation = transformation; + } + + public void evaluate(ActivityExecution execution) { + //TODO + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Structure.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureDefinition.java similarity index 85% rename from modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Structure.java rename to modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureDefinition.java index d555afd9398d6389d892a7374176c9130842e1c2..d08c8b901cf0f15b8029305e3f556430e05cac91 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Structure.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureDefinition.java @@ -13,18 +13,11 @@ package org.activiti.engine.impl.bpmn; /** - * Represents a structure used to exchange information + * Represents a structure definition based on fields * * @author Esteban Robles Luna */ -public interface Structure { - - /** - * Obtains the id of this structure - * - * @return the id of this structure - */ - String getId(); +public interface FieldBaseStructureDefinition extends StructureDefinition { /** * Obtains the number of fields that this structure has diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureInstance.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..0f46e638e6a521c0e5c2d6414df3ea2dfc0b4aa9 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/FieldBaseStructureInstance.java @@ -0,0 +1,69 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +import java.util.HashMap; +import java.util.Map; + +/** + * An instance of {@link FieldBaseStructureDefinition} + * + * @author Esteban Robles Luna + */ +public class FieldBaseStructureInstance implements StructureInstance { + + protected FieldBaseStructureDefinition structureDefinition; + + protected Map fieldValues; + + public FieldBaseStructureInstance(FieldBaseStructureDefinition structureDefinition) { + this.structureDefinition = structureDefinition; + this.fieldValues = new HashMap(); + } + + public Object getFieldValue(String fieldName) { + return this.fieldValues.get(fieldName); + } + + public void setFieldValue(String fieldName, Object value) { + this.fieldValues.put(fieldName, value); + } + + public int getFieldSize() { + return this.structureDefinition.getFieldSize(); + } + + public String getFieldNameAt(int index) { + return this.structureDefinition.getFieldNameAt(index); + } + + public Object[] toArray() { + int fieldSize = this.getFieldSize(); + Object[] arguments = new Object[fieldSize]; + for (int i = 0; i < fieldSize; i++) { + String fieldName = this.getFieldNameAt(i); + Object argument = this.getFieldValue(fieldName); + arguments[i] = argument; + } + return arguments; + } + + public void loadFrom(Object[] array) { + int fieldSize = this.getFieldSize(); + for (int i = 0; i < fieldSize; i++) { + String fieldName = this.getFieldNameAt(i); + Object fieldValue = array[i]; + this.setFieldValue(fieldName, fieldValue); + } + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/IOSpecification.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/IOSpecification.java index bef2c750aaa37097ce16b01974a203188d290f66..a0e7f064d2419af9292d45cdef2e518237246f85 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/IOSpecification.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/IOSpecification.java @@ -13,8 +13,11 @@ package org.activiti.engine.impl.bpmn; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import org.activiti.engine.impl.pvm.delegate.ActivityExecution; + /** * Implementation of the BPMN 2.0 'ioSpecification' * @@ -37,6 +40,24 @@ public class IOSpecification { this.dataOutputRefs = new ArrayList(); } + public void initialize(ActivityExecution execution) { + for (Data data : this.dataInputs) { + execution.setVariable(data.getId(), data.getDefinition().createInstance()); + } + + for (Data data : this.dataOutputs) { + execution.setVariable(data.getId(), data.getDefinition().createInstance()); + } + } + + public List getDataInputs() { + return Collections.unmodifiableList(this.dataInputs); + } + + public List getDataOutputs() { + return Collections.unmodifiableList(this.dataOutputs); + } + public void addInput(Data data) { this.dataInputs.add(data); } @@ -52,4 +73,12 @@ public class IOSpecification { public void addOutputRef(DataRef dataRef) { this.dataOutputRefs.add(dataRef); } + + public String getFirstDataInputId() { + return this.dataInputs.get(0).getId(); + } + + public String getFirstDataOutputId() { + return this.dataOutputs.get(0).getId(); + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemDefinition.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemDefinition.java index 4ea51aeab80251a5e069107fd7a3778f07d81fb4..9d58eb688615213b19c5a2e5339b61e59e7287f7 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemDefinition.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemDefinition.java @@ -12,6 +12,7 @@ */ package org.activiti.engine.impl.bpmn; + /** * Implementation of the BPMN 2.0 'itemDefinition' * @@ -21,7 +22,7 @@ public class ItemDefinition { protected String id; - protected Structure structure; + protected StructureDefinition structure; protected boolean isCollection; @@ -32,13 +33,17 @@ public class ItemDefinition { this.itemKind = ItemKind.Information; } - public ItemDefinition(String id, Structure structure) { + public ItemDefinition(String id, StructureDefinition structure) { this(); this.id = id; this.structure = structure; } - public Structure getStructure() { + public ItemInstance createInstance() { + return new ItemInstance(this, this.structure.createInstance()); + } + + public StructureDefinition getStructureDefinition() { return this.structure; } @@ -57,4 +62,8 @@ public class ItemDefinition { public void setItemKind(ItemKind itemKind) { this.itemKind = itemKind; } + + public String getId() { + return this.id; + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemInstance.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..69b9d21b3d54b18f90781c8d5d77b65e9ddaa4d9 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/ItemInstance.java @@ -0,0 +1,38 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +/** + * An instance of {@link ItemDefinition} + * + * @author Esteban Robles Luna + */ +public class ItemInstance { + + protected ItemDefinition item; + + protected StructureInstance structureInstance; + + public ItemInstance(ItemDefinition item, StructureInstance structureInstance) { + this.item = item; + this.structureInstance = structureInstance; + } + + public ItemDefinition getItem() { + return this.item; + } + + public StructureInstance getStructureInstance() { + return this.structureInstance; + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Message.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageDefinition.java similarity index 73% rename from modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Message.java rename to modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageDefinition.java index 7451dab13bf7f561a0af20a67e33fe1a9a78164b..9c6331aaf35b2fad09cbe0072e0d19fac6397888 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Message.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageDefinition.java @@ -17,26 +17,30 @@ package org.activiti.engine.impl.bpmn; * * @author Esteban Robles Luna */ -public class Message { +public class MessageDefinition { protected String id; protected ItemDefinition itemDefinition; - public Message(String id, ItemDefinition itemDefinition) { + public MessageDefinition(String id, ItemDefinition itemDefinition) { this.id = id; this.itemDefinition = itemDefinition; } public MessageInstance createInstance() { - return new MessageInstance(this); + return new MessageInstance(this, this.itemDefinition.createInstance()); } public ItemDefinition getItemDefinition() { return this.itemDefinition; } - public Structure getStructure() { - return this.itemDefinition.getStructure(); + public StructureDefinition getStructureDefinition() { + return this.itemDefinition.getStructureDefinition(); + } + + public String getId() { + return this.id; } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageInstance.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageInstance.java index d8fd797a7f39398e75906bc51d5458feec874922..13b2796d9825f75ab97f173e9de9c44be073558f 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageInstance.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/MessageInstance.java @@ -12,42 +12,28 @@ */ package org.activiti.engine.impl.bpmn; -import java.util.HashMap; -import java.util.Map; /** - * An instance of a {@link Message} + * An instance of a {@link MessageDefinition} * * @author Esteban Robles Luna */ public class MessageInstance { - protected Message message; + protected MessageDefinition message; - protected Map fieldValues; + protected ItemInstance item; - MessageInstance(Message message) { + MessageInstance(MessageDefinition message, ItemInstance item) { this.message = message; - this.fieldValues = new HashMap(); + this.item = item; } - public Object getFieldValue(String fieldName) { - return this.fieldValues.get(fieldName); + public StructureInstance getStructureInstance() { + return this.item.getStructureInstance(); } - public void setFieldValue(String fieldName, Object value) { - this.fieldValues.put(fieldName, value); - } - - public int getFieldSize() { - return this.getMessage().getStructure().getFieldSize(); - } - - public String getFieldNameAt(int index) { - return this.getMessage().getStructure().getFieldNameAt(index); - } - - public Message getMessage() { + public MessageDefinition getMessage() { return this.message; } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Operation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Operation.java index 2bd1fffd68a0740ec464ba3ade8b07e41e1bb94d..14374b830d97ccd4ed75bfc78ec897802c7cd992 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Operation.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/Operation.java @@ -24,9 +24,9 @@ public class Operation { protected String name; - protected Message inMessage; + protected MessageDefinition inMessage; - protected Message outMessage; + protected MessageDefinition outMessage; protected OperationImplementation implementation; @@ -39,17 +39,13 @@ public class Operation { } - public Operation(String id, String name, BpmnInterface bpmnInterface, Message inMessage) { + public Operation(String id, String name, BpmnInterface bpmnInterface, MessageDefinition inMessage) { setId(id); setName(name); setInterface(bpmnInterface); setInMessage(inMessage); } - public MessageInstance createEmptySendMessage() { - return this.inMessage.createInstance(); - } - public MessageInstance sendMessage(MessageInstance message) { return this.implementation.sendFor(message, this); } @@ -78,19 +74,19 @@ public class Operation { this.bpmnInterface = bpmnInterface; } - public Message getInMessage() { + public MessageDefinition getInMessage() { return inMessage; } - public void setInMessage(Message inMessage) { + public void setInMessage(MessageDefinition inMessage) { this.inMessage = inMessage; } - public Message getOutMessage() { + public MessageDefinition getOutMessage() { return outMessage; } - public void setOutMessage(Message outMessage) { + public void setOutMessage(MessageDefinition outMessage) { this.outMessage = outMessage; } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/OperationImplementation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/OperationImplementation.java index 80654b572ebe05b72e0ea05cdcf2268350af413f..b3c3843e7f7c1ddc56f944d70a0742c3394d8480 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/OperationImplementation.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/OperationImplementation.java @@ -19,6 +19,11 @@ package org.activiti.engine.impl.bpmn; */ public interface OperationImplementation { + /** + * @return the id of this implementation + */ + String getId(); + /** * @return the name of this implementation */ diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureDefinition.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureDefinition.java new file mode 100644 index 0000000000000000000000000000000000000000..372dd1b590c5088e2bd6d32dd5bf26a9e8e973eb --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureDefinition.java @@ -0,0 +1,42 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +/** + * Represents a structure based on a primitive class + * + * @author Esteban Robles Luna + */ +public class PrimitiveStructureDefinition implements StructureDefinition { + + protected String id; + + protected Class primitiveClass; + + public PrimitiveStructureDefinition(String id, Class primitiveClass) { + this.id = id; + this.primitiveClass = primitiveClass; + } + + public String getId() { + return this.id; + } + + public Class getPrimitiveClass() { + return primitiveClass; + } + + public StructureInstance createInstance() { + return new PrimitiveStructureInstance(this); + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureInstance.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..5a9ee477bc160623d991355070566c30c3675868 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/PrimitiveStructureInstance.java @@ -0,0 +1,52 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +/** + * An instance of {@link PrimitiveStructureDefinition} + * + * @author Esteban Robles Luna + */ +public class PrimitiveStructureInstance implements StructureInstance { + + protected Object primitive; + + protected PrimitiveStructureDefinition definition; + + public PrimitiveStructureInstance(PrimitiveStructureDefinition definition) { + this(definition, null); + } + + public PrimitiveStructureInstance(PrimitiveStructureDefinition definition, Object primitive) { + this.definition = definition; + this.primitive = primitive; + } + + public Object getPrimitive() { + return this.primitive; + } + + public Object[] toArray() { + return new Object[] { this.primitive }; + } + + public void loadFrom(Object[] array) { + for (int i = 0; i < array.length; i++) { + Object object = array[i]; + if (this.definition.getPrimitiveClass().isInstance(object)) { + this.primitive = object; + return; + } + } + } +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructure.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructureDefinition.java similarity index 88% rename from modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructure.java rename to modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructureDefinition.java index 2b877c4c79cba44e5b47634b56efd7b4f429418e..5468c139f3e6afec4b65adf5cedec78ce4f98dc9 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructure.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/SimpleStructureDefinition.java @@ -20,7 +20,7 @@ import java.util.List; * * @author Esteban Robles Luna */ -public class SimpleStructure implements Structure { +public class SimpleStructureDefinition implements FieldBaseStructureDefinition { protected String id; @@ -28,7 +28,7 @@ public class SimpleStructure implements Structure { protected List> fieldTypes; - public SimpleStructure(String id) { + public SimpleStructureDefinition(String id) { this.id = id; this.fieldNames = new ArrayList(); this.fieldTypes = new ArrayList>(); @@ -64,4 +64,8 @@ public class SimpleStructure implements Structure { public Class getFieldTypeAt(int index) { return this.fieldTypes.get(index); } + + public StructureInstance createInstance() { + return new FieldBaseStructureInstance(this); + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureDefinition.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureDefinition.java new file mode 100644 index 0000000000000000000000000000000000000000..edc27e960dbb42ec71d23530e443303f5a3aa70d --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureDefinition.java @@ -0,0 +1,33 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +/** + * Represents a definition of a structure used to exchange information + * + * @author Esteban Robles Luna + */ +public interface StructureDefinition { + + /** + * Obtains the id of this structure + * + * @return the id of this structure + */ + String getId(); + + /** + * @return a new instance of this structure definition + */ + StructureInstance createInstance(); +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureInstance.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..7bac9298d51ca66f0719656fb1e56b8d1e555f89 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/StructureInstance.java @@ -0,0 +1,35 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.bpmn; + +/** + * An instance of {@link StructureDefinition} + * + * @author Esteban Robles Luna + */ +public interface StructureInstance { + + /** + * Converts this structure instance into an array + * + * @return this structure as an array + */ + Object[] toArray(); + + /** + * Loads this structure from array + * + * @param array the array where this structure loads data + */ + void loadFrom(Object[] array); +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/WebServiceActivityBehavior.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/WebServiceActivityBehavior.java index 60d1c315aaaa8861ef6cadf426dfbde17f61aa4f..2865c4a717fe06bfbc502025941cd77c56213611 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/WebServiceActivityBehavior.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/WebServiceActivityBehavior.java @@ -27,41 +27,65 @@ public class WebServiceActivityBehavior implements ActivityBehavior { protected Operation operation; - protected List dataInputAssociations; + protected IOSpecification ioSpecification; + + protected List dataInputAssociations; - protected List dataOutputAssociations; + protected List dataOutputAssociations; public WebServiceActivityBehavior(Operation operation) { this.operation = operation; - this.dataInputAssociations = new ArrayList(); - this.dataOutputAssociations = new ArrayList(); + this.dataInputAssociations = new ArrayList(); + this.dataOutputAssociations = new ArrayList(); + } + + public void addDataInputAssociation(DataInputAssociation dataAssociation) { + this.dataInputAssociations.add(dataAssociation); + } + + public void addDataOutputAssociation(DataOutputAssociation dataAssociation) { + this.dataOutputAssociations.add(dataAssociation); } /** * {@inheritDoc} */ public void execute(ActivityExecution execution) throws Exception { - MessageInstance message = this.createEmptyMessage(); + MessageInstance message; + + if (ioSpecification != null) { + this.ioSpecification.initialize(execution); + ItemInstance inputItem = (ItemInstance) execution.getVariable(this.ioSpecification.getFirstDataInputId()); + message = new MessageInstance(this.operation.getInMessage(), inputItem); + } else { + message = this.operation.getInMessage().createInstance(); + } + this.fillMessage(message, execution); + MessageInstance receivedMessage = this.operation.sendMessage(message); + + if (ioSpecification != null) { + ItemInstance outputItem = (ItemInstance) execution.getVariable(this.ioSpecification.getFirstDataOutputId()); + outputItem.getStructureInstance().loadFrom(receivedMessage.getStructureInstance().toArray()); + } + this.returnMessage(receivedMessage, execution); } private void returnMessage(MessageInstance message, ActivityExecution execution) { - //TODO DO SOMETHING WITH THE MESSAGE AND THE EXECUTION CONTEXT BEFORE? - for (DataAssociation dataAssociation : this.dataOutputAssociations) { + for (DataOutputAssociation dataAssociation : this.dataOutputAssociations) { dataAssociation.evaluate(execution); } } private void fillMessage(MessageInstance message, ActivityExecution execution) { - //TODO DO SOMETHING WITH THE MESSAGE AND THE EXECUTION CONTEXT BEFORE? - for (DataAssociation dataAssociation : this.dataInputAssociations) { + for (DataInputAssociation dataAssociation : this.dataInputAssociations) { dataAssociation.evaluate(execution); } } - private MessageInstance createEmptyMessage() { - return this.operation.createEmptySendMessage(); + public void setIoSpecification(IOSpecification ioSpecification) { + this.ioSpecification = ioSpecification; } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/BpmnParse.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/BpmnParse.java index 7da7d6561e9e57179c1dfdaffd3afdabd5ae9ffe..ff5d2e26702705c252a534d74838f334e8e408b3 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/BpmnParse.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/parser/BpmnParse.java @@ -24,21 +24,27 @@ import java.util.logging.Logger; import org.activiti.engine.ActivitiException; import org.activiti.engine.delegate.JavaDelegation; +import org.activiti.engine.impl.bpmn.Assignment; import org.activiti.engine.impl.bpmn.BoundaryTimerEventActivity; import org.activiti.engine.impl.bpmn.BpmnInterface; import org.activiti.engine.impl.bpmn.BpmnInterfaceImplementation; import org.activiti.engine.impl.bpmn.CallActivityBehaviour; -import org.activiti.engine.impl.bpmn.ClassStructure; +import org.activiti.engine.impl.bpmn.ClassStructureDefinition; import org.activiti.engine.impl.bpmn.Condition; +import org.activiti.engine.impl.bpmn.Data; +import org.activiti.engine.impl.bpmn.DataInputAssociation; +import org.activiti.engine.impl.bpmn.DataOutputAssociation; +import org.activiti.engine.impl.bpmn.DataRef; import org.activiti.engine.impl.bpmn.ExclusiveGatewayActivity; import org.activiti.engine.impl.bpmn.ExpressionExecutionListener; import org.activiti.engine.impl.bpmn.ExpressionTaskListener; +import org.activiti.engine.impl.bpmn.IOSpecification; import org.activiti.engine.impl.bpmn.ItemDefinition; import org.activiti.engine.impl.bpmn.ItemKind; import org.activiti.engine.impl.bpmn.JavaDelegationDelegate; import org.activiti.engine.impl.bpmn.MailActivityBehavior; import org.activiti.engine.impl.bpmn.ManualTaskActivity; -import org.activiti.engine.impl.bpmn.Message; +import org.activiti.engine.impl.bpmn.MessageDefinition; import org.activiti.engine.impl.bpmn.NoneEndEventActivity; import org.activiti.engine.impl.bpmn.NoneStartEventActivity; import org.activiti.engine.impl.bpmn.Operation; @@ -47,7 +53,7 @@ import org.activiti.engine.impl.bpmn.ParallelGatewayActivity; import org.activiti.engine.impl.bpmn.ReceiveTaskActivity; import org.activiti.engine.impl.bpmn.ScriptTaskActivity; import org.activiti.engine.impl.bpmn.ServiceTaskExpressionActivityBehavior; -import org.activiti.engine.impl.bpmn.Structure; +import org.activiti.engine.impl.bpmn.StructureDefinition; import org.activiti.engine.impl.bpmn.SubProcessActivity; import org.activiti.engine.impl.bpmn.TaskActivity; import org.activiti.engine.impl.bpmn.UserTaskActivity; @@ -112,12 +118,12 @@ public class BpmnParse extends Parse { * that this map doesn't need to be re-initialized for each new process * definition. */ - protected Map messages = new HashMap(); + protected Map messages = new HashMap(); /** - * Map that contains the {@link Structure} + * Map that contains the {@link StructureDefinition} */ - protected Map structures = new HashMap(); + protected Map structures = new HashMap(); /** * Map that contains the {@link BpmnInterfaceImplementation} @@ -163,6 +169,10 @@ public class BpmnParse extends Parse { protected Map importers = new HashMap(); + protected Map prefixs = new HashMap(); + + protected String targetNamespace; + /** * Constructor to be called by the {@link BpmnParser}. * @@ -174,6 +184,12 @@ public class BpmnParse extends Parse { this.expressionManager = parser.getExpressionManager(); this.parseListeners = parser.getParseListeners(); setSchemaResource(ReflectUtil.getResource(BpmnParser.SCHEMA_RESOURCE).toString()); + this.initializeXSDItemDefinitions(); + } + + private void initializeXSDItemDefinitions() { + this.itemDefinitions.put("http://www.w3.org/2001/XMLSchema:string", + new ItemDefinition("http://www.w3.org/2001/XMLSchema:string", new ClassStructureDefinition(String.class))); } public BpmnParse deployment(DeploymentEntity deployment) { @@ -205,6 +221,7 @@ public class BpmnParse extends Parse { private void parseDefinitionsAttributes() { String typeLanguage = rootElement.attribute("typeLanguage"); String expressionLanguage = rootElement.attribute("expressionLanguage"); + this.targetNamespace = rootElement.attribute("targetNamespace"); if (typeLanguage != null) { if (typeLanguage.contains("XMLSchema")) { @@ -218,6 +235,26 @@ public class BpmnParse extends Parse { LOG.info("XPath currently not supported as typeLanguage"); } } + + for (String attribute : rootElement.attributes()) { + if (attribute.startsWith("xmlns:")) { + String prefixValue = rootElement.attribute(attribute); + String prefixName = attribute.substring(6); + this.prefixs.put(prefixName, prefixValue); + } + } + } + + protected String resolveName(String name) { + if (name == null) { return null; } + int indexOfP = name.indexOf(':'); + if (indexOfP != -1) { + String prefix = name.substring(0, indexOfP); + String resolvedPrefix = this.prefixs.get(prefix); + return resolvedPrefix + ":" + name.substring(indexOfP + 1); + } else { + return name; + } } /** @@ -269,24 +306,24 @@ public class BpmnParse extends Parse { public void parseItemDefinitions() { for (Element itemDefinitionElement : rootElement.elements("itemDefinition")) { String id = itemDefinitionElement.attribute("id"); - String structureRef = itemDefinitionElement.attribute("structureRef"); + String structureRef = this.resolveName(itemDefinitionElement.attribute("structureRef")); String itemKind = itemDefinitionElement.attribute("itemKind"); - Structure structure = null; + StructureDefinition structure = null; try { //it is a class Class classStructure = ReflectUtil.loadClass(structureRef); - structure = new ClassStructure(classStructure); + structure = new ClassStructureDefinition(classStructure); } catch (ActivitiException e) { //it is a reference to a different structure structure = this.structures.get(structureRef); } - ItemDefinition itemDefinition = new ItemDefinition(id, structure); + ItemDefinition itemDefinition = new ItemDefinition(this.targetNamespace + ":" + id, structure); if (itemKind != null) { itemDefinition.setItemKind(ItemKind.valueOf(itemKind)); } - itemDefinitions.put(id, itemDefinition); + itemDefinitions.put(itemDefinition.getId(), itemDefinition); } } @@ -301,14 +338,14 @@ public class BpmnParse extends Parse { public void parseMessages() { for (Element messageElement : rootElement.elements("message")) { String id = messageElement.attribute("id"); - String itemRef = messageElement.attribute("itemRef"); + String itemRef = this.resolveName(messageElement.attribute("itemRef")); if (!this.itemDefinitions.containsKey(itemRef)) { addError(itemRef + " does not exist", messageElement); } else { ItemDefinition itemDefinition = this.itemDefinitions.get(itemRef); - Message message = new Message(id, itemDefinition); - this.messages.put(id, message); + MessageDefinition message = new MessageDefinition(this.targetNamespace + ":" + id, itemDefinition); + this.messages.put(message.getId(), message); } } } @@ -325,8 +362,8 @@ public class BpmnParse extends Parse { // Create the interface String id = interfaceElement.attribute("id"); String name = interfaceElement.attribute("name"); - String implementationRef = interfaceElement.attribute("implementationRef"); - BpmnInterface bpmnInterface = new BpmnInterface(id, name); + String implementationRef = this.resolveName(interfaceElement.attribute("implementationRef")); + BpmnInterface bpmnInterface = new BpmnInterface(this.targetNamespace + ":" + id, name); bpmnInterface.setImplementation(this.interfaceImplementations.get(implementationRef)); // Handle all its operations @@ -335,31 +372,33 @@ public class BpmnParse extends Parse { bpmnInterface.addOperation(operation); } - bpmnInterfaces.put(id, bpmnInterface); + bpmnInterfaces.put(bpmnInterface.getId(), bpmnInterface); } } public Operation parseOperation(Element operationElement, BpmnInterface bpmnInterface) { Element inMessageRefElement = operationElement.element("inMessageRef"); + String inMessageRef = this.resolveName(inMessageRefElement.getText()); - if (!this.messages.containsKey(inMessageRefElement.getText())) { - addError(inMessageRefElement.getText() + " does not exist", inMessageRefElement); + if (!this.messages.containsKey(inMessageRef)) { + addError(inMessageRef + " does not exist", inMessageRefElement); return null; } else { - Message inMessage = this.messages.get(inMessageRefElement.getText()); + MessageDefinition inMessage = this.messages.get(inMessageRef); String id = operationElement.attribute("id"); String name = operationElement.attribute("name"); - String implementationRef = operationElement.attribute("implementationRef"); - Operation operation = new Operation(id, name, bpmnInterface, inMessage); + String implementationRef = this.resolveName(operationElement.attribute("implementationRef")); + Operation operation = new Operation(this.targetNamespace + ":" + id, name, bpmnInterface, inMessage); operation.setImplementation(this.operationImplementations.get(implementationRef)); Element outMessageRefElement = operationElement.element("outMessageRef"); - if (this.messages.containsKey(outMessageRefElement.getText())) { - Message outMessage = this.messages.get(outMessageRefElement.getText()); + String outMessageRef = this.resolveName(outMessageRefElement.getText()); + if (this.messages.containsKey(outMessageRef)) { + MessageDefinition outMessage = this.messages.get(outMessageRef); operation.setOutMessage(outMessage); } - operations.put(id, operation); + operations.put(operation.getId(), operation); return operation; } } @@ -438,6 +477,65 @@ public class BpmnParse extends Parse { parseBoundaryEvents(scopeElement, parentScope); parseSequenceFlow(scopeElement, parentScope); parseExecutionListenersOnScope(scopeElement, parentScope); + + IOSpecification ioSpecification = parseIOSpecification(scopeElement.element("ioSpecification")); + parentScope.setIoSpecification(ioSpecification); + } + + protected IOSpecification parseIOSpecification(Element ioSpecificationElement) { + if (ioSpecificationElement == null) { + return null; + } + + IOSpecification ioSpecification = new IOSpecification(); + + for (Element dataInputElement : ioSpecificationElement.elements("dataInput")) { + String id = dataInputElement.attribute("id"); + String itemSubjectRef = this.resolveName(dataInputElement.attribute("itemSubjectRef")); + ItemDefinition itemDefinition = this.itemDefinitions.get(itemSubjectRef); + Data dataInput = new Data(this.targetNamespace + ":" + id, itemDefinition); + ioSpecification.addInput(dataInput); + } + + for (Element dataOutputElement : ioSpecificationElement.elements("dataOutput")) { + String id = dataOutputElement.attribute("id"); + String itemSubjectRef = this.resolveName(dataOutputElement.attribute("itemSubjectRef")); + ItemDefinition itemDefinition = this.itemDefinitions.get(itemSubjectRef); + Data dataOutput = new Data(this.targetNamespace + ":" + id, itemDefinition); + ioSpecification.addOutput(dataOutput); + } + + for (Element inputSetElement : ioSpecificationElement.elements("inputSet")) { + for (Element dataInputRef : inputSetElement.elements("dataInputRefs")) { + DataRef dataRef = new DataRef(dataInputRef.getText()); + ioSpecification.addInputRef(dataRef); + } + } + + for (Element outputSetElement : ioSpecificationElement.elements("outputSet")) { + for (Element dataInputRef : outputSetElement.elements("dataOutputRefs")) { + DataRef dataRef = new DataRef(dataInputRef.getText()); + ioSpecification.addOutputRef(dataRef); + } + } + + return ioSpecification; + } + + protected DataInputAssociation parseDataInputAssociation(Element dataAssociationElement) { + String sourceRef = dataAssociationElement.element("sourceRef").getText(); + String targetRef = dataAssociationElement.element("targetRef").getText(); + + DataInputAssociation dataAssociation = new DataInputAssociation(sourceRef, targetRef); + + for (Element assigmentElement : dataAssociationElement.elements("assignment")) { + Expression from = this.expressionManager.createExpression(assigmentElement.element("from").getText()); + Expression to = this.expressionManager.createExpression(assigmentElement.element("to").getText()); + Assignment assignment = new Assignment(from, to); + dataAssociation.addAssignment(assignment); + } + + return dataAssociation; } /** @@ -654,7 +752,7 @@ public class BpmnParse extends Parse { String expression = serviceTaskElement.attributeNS(BpmnParser.ACTIVITI_BPMN_EXTENSIONS_NS, "expression"); String resultVariableName = serviceTaskElement.attributeNS(BpmnParser.ACTIVITI_BPMN_EXTENSIONS_NS, "resultVariableName"); String implementation = serviceTaskElement.attribute("implementation"); - String operationRef = serviceTaskElement.attribute("operationRef"); + String operationRef = this.resolveName(serviceTaskElement.attribute("operationRef")); List fieldDeclarations = parseFieldDeclarationsOnServiceTask(serviceTaskElement); if (type != null) { @@ -687,7 +785,25 @@ public class BpmnParse extends Parse { addError(operationRef + " does not exist" , serviceTaskElement); } else { Operation operation = this.operations.get(operationRef); - activity.setActivityBehavior(new WebServiceActivityBehavior(operation)); + WebServiceActivityBehavior webServiceActivityBehavior = new WebServiceActivityBehavior(operation); + + Element ioSpecificationElement = serviceTaskElement.element("ioSpecification"); + if (ioSpecificationElement != null) { + IOSpecification ioSpecification = this.parseIOSpecification(ioSpecificationElement); + webServiceActivityBehavior.setIoSpecification(ioSpecification); + } + + for (Element dataAssociationElement : serviceTaskElement.elements("dataInputAssociation")) { + DataInputAssociation dataAssociation = this.parseDataInputAssociation(dataAssociationElement); + webServiceActivityBehavior.addDataInputAssociation(dataAssociation); + } + + for (Element dataAssociationElement : serviceTaskElement.elements("dataOutputAssociation")) { + DataOutputAssociation dataAssociation = this.parseDataOutputAssociation(dataAssociationElement); + webServiceActivityBehavior.addDataOutputAssociation(dataAssociation); + } + + activity.setActivityBehavior(webServiceActivityBehavior); } } else { addError("'class', 'type', or 'expression' attribute is mandatory on serviceTask", serviceTaskElement); @@ -700,6 +816,13 @@ public class BpmnParse extends Parse { } } + private DataOutputAssociation parseDataOutputAssociation(Element dataAssociationElement) { + String targetRef = dataAssociationElement.element("targetRef").getText(); + Expression transformation = this.expressionManager.createExpression(dataAssociationElement.element("transformation").getText()); + DataOutputAssociation dataOutputAssociation = new DataOutputAssociation(targetRef, transformation); + return dataOutputAssociation; + } + protected void parseEmailServiceTask(ActivityImpl activity, Element serviceTaskElement, List fieldDeclarations) { validateFieldDeclarationsForEmail(serviceTaskElement, fieldDeclarations); activity.setActivityBehavior(instantiateAndHandleFieldDeclarations(MailActivityBehavior.class, fieldDeclarations)); @@ -1309,7 +1432,7 @@ public class BpmnParse extends Parse { if (itemSubjectRef != null) { ItemDefinition itemDefinition = itemDefinitions.get(itemSubjectRef); if (itemDefinition != null) { - Structure structure = itemDefinition.getStructure(); + StructureDefinition structure = itemDefinition.getStructureDefinition(); type = structure.getId(); } else { addError("Invalid itemDefinition reference: " + itemSubjectRef + " not found", propertyElement); @@ -1575,7 +1698,7 @@ public class BpmnParse extends Parse { return this; } - public void addStructure(Structure structure) { + public void addStructure(StructureDefinition structure) { this.structures.put(structure.getId(), structure); } @@ -1584,7 +1707,7 @@ public class BpmnParse extends Parse { } public void addOperation(OperationImplementation operationImplementation) { - this.operationImplementations.put(operationImplementation.getName(), operationImplementation); + this.operationImplementations.put(operationImplementation.getId(), operationImplementation); } public Boolean parseBooleanAttribute(String booleanText) { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/process/ScopeImpl.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/process/ScopeImpl.java index 6af42e6dd96ac30262f901119c11fd41ef5eabec..daadd27dd6c6edf615474fad5066cb5c94837afd 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/process/ScopeImpl.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/pvm/process/ScopeImpl.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.activiti.engine.impl.bpmn.IOSpecification; import org.activiti.engine.impl.pvm.PvmException; import org.activiti.engine.impl.pvm.PvmScope; import org.activiti.engine.impl.pvm.delegate.ExecutionListener; @@ -34,7 +35,8 @@ public abstract class ScopeImpl extends ProcessElementImpl implements PvmScope { protected List activities = new ArrayList(); protected Map namedActivities = new HashMap(); protected Map> executionListeners = new HashMap>(); - + protected IOSpecification ioSpecification; + public ScopeImpl(String id, ProcessDefinitionImpl processDefinition) { super(id, processDefinition); } @@ -111,4 +113,12 @@ public abstract class ScopeImpl extends ProcessElementImpl implements PvmScope { public List getActivities() { return activities; } + + public IOSpecification getIoSpecification() { + return ioSpecification; + } + + public void setIoSpecification(IOSpecification ioSpecification) { + this.ioSpecification = ioSpecification; + } } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/repository/ProcessDefinitionEntity.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/repository/ProcessDefinitionEntity.java index c7f0018dbf77e208fd51380b8ac4653a5e53e886..626023c0e8d067a896e5a8d4314044108cf72fc5 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/repository/ProcessDefinitionEntity.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/repository/ProcessDefinitionEntity.java @@ -15,6 +15,7 @@ package org.activiti.engine.impl.repository; import java.util.ArrayList; import java.util.Map; +import org.activiti.engine.impl.bpmn.IOSpecification; import org.activiti.engine.impl.cfg.ProcessEngineConfiguration; import org.activiti.engine.impl.db.DbSqlSession; import org.activiti.engine.impl.db.PersistentObject; diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Element.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Element.java index c0d49be4a98c4b23fa5966103441376b187d409b..a9ea054fba671216d13a00cf9bddd58f9b404ecf 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Element.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Element.java @@ -16,6 +16,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.activiti.engine.ActivitiException; import org.xml.sax.Attributes; @@ -107,6 +108,10 @@ public class Element { return null; } + public Set attributes() { + return attributeMap.keySet(); + } + public String attributeNS(String namespaceUri, String name) { return attribute(composeMapKey(namespaceUri, name)); } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Parse.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Parse.java index fd0d8898468ce9d6774adbdf6890f572a01f36db..d8222e8591ac2a7fab6b25765741baebf461b25e 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Parse.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/util/xml/Parse.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -28,6 +29,8 @@ import org.activiti.engine.impl.util.io.ResourceStreamSource; import org.activiti.engine.impl.util.io.StreamSource; import org.activiti.engine.impl.util.io.StringStreamSource; import org.activiti.engine.impl.util.io.UrlStreamSource; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; @@ -187,6 +190,11 @@ public class Parse extends DefaultHandler { SAXParserFactory saxParserFactory = parser.getSaxParserFactory(); saxParserFactory.setNamespaceAware(true); saxParserFactory.setValidating(true); + try { + saxParserFactory.setFeature("http://xml.org/sax/features/namespace-prefixes", true); + } catch (Exception e) { + LOGGER.warning(e.getMessage()); + } this.schemaResource = schemaResource; } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/DefaultVariableTypes.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/DefaultVariableTypes.java index d5f572b232e01fbfa90416905276b36a14ef8031..4ca40247d6f0326ff976c50b891dd641f3aa0ea8 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/DefaultVariableTypes.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/DefaultVariableTypes.java @@ -40,6 +40,7 @@ public class DefaultVariableTypes implements Serializable, VariableTypes { addType(new DoubleType()); addType(new ByteArrayType()); addType(new SerializableType()); + addType(new ItemType()); } public DefaultVariableTypes addType(VariableType type) { diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/ItemType.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/ItemType.java new file mode 100644 index 0000000000000000000000000000000000000000..1f626a7c71a6830591347f722ffa956f6726e925 --- /dev/null +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/variable/ItemType.java @@ -0,0 +1,46 @@ +/* Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.activiti.engine.impl.variable; + +import org.activiti.engine.impl.bpmn.ItemInstance; + +/** + * Type for {@link ItemInstance} + * + * @author Esteban Robles Luna + */ +public class ItemType implements VariableType { + + public String getTypeName() { + return "item"; + } + + public Object getValue(ValueFields valueFields) { + return null; + } + + public boolean isAbleToStore(Object value) { + if (value==null) { + return true; + } + return ItemInstance.class.isAssignableFrom(value.getClass()); + } + + public boolean isCachable() { + return false; + } + + public void setValue(Object value, ValueFields valueFields) { + } + +} diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/webservice/WSOperation.java b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/webservice/WSOperation.java index 5c62be8494d593bc80081b59fa3602c08d275fe0..15f1474103112c41714e9cfd6121e3c4a653d1ed 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/impl/webservice/WSOperation.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/impl/webservice/WSOperation.java @@ -28,15 +28,25 @@ public class WSOperation implements OperationImplementation { private static final Logger LOGGER = Logger.getLogger(WSOperation.class.getName()); + protected String id; + protected String name; protected WSService service; - public WSOperation(String operationName, WSService service) { + public WSOperation(String id, String operationName, WSService service) { + this.id = id; this.name = operationName; this.service = service; } + /** + * {@inheritDoc} + */ + public String getId() { + return this.id; + } + /** * {@inheritDoc} */ @@ -54,14 +64,7 @@ public class WSOperation implements OperationImplementation { } private Object[] getArguments(MessageInstance message) { - int fieldSize = message.getFieldSize(); - Object[] arguments = new Object[fieldSize]; - for (int i = 0; i < fieldSize; i++) { - String fieldName = message.getFieldNameAt(i); - Object argument = message.getFieldValue(fieldName); - arguments[i] = argument; - } - return arguments; + return message.getStructureInstance().toArray(); } private Object[] safeSend(Object[] arguments) { @@ -81,14 +84,7 @@ public class WSOperation implements OperationImplementation { private MessageInstance createResponseMessage(Object[] results, Operation operation) { MessageInstance message = operation.getOutMessage().createInstance(); - - int fieldSize = message.getFieldSize(); - for (int i = 0; i < fieldSize; i++) { - String fieldName = message.getFieldNameAt(i); - Object fieldValue = results[i]; - message.setFieldValue(fieldName, fieldValue); - } - + message.getStructureInstance().loadFrom(results); return message; } diff --git a/modules/activiti-engine/src/main/java/org/activiti/engine/repository/ProcessDefinition.java b/modules/activiti-engine/src/main/java/org/activiti/engine/repository/ProcessDefinition.java index b018287e9e09e8cd0ef702da541fadca764c3598..e76b6ee88464824ebba21f5cb65048a71ae50b8b 100644 --- a/modules/activiti-engine/src/main/java/org/activiti/engine/repository/ProcessDefinition.java +++ b/modules/activiti-engine/src/main/java/org/activiti/engine/repository/ProcessDefinition.java @@ -14,6 +14,7 @@ package org.activiti.engine.repository; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; +import org.activiti.engine.impl.bpmn.IOSpecification; import org.activiti.engine.runtime.ProcessInstance; /** Is an object structure representing an executable process composed of @@ -53,4 +54,7 @@ public interface ProcessDefinition { /** The deployment in which this process definition is contained. */ String getDeploymentId(); + + /** the io specification of the process definition */ + IOSpecification getIoSpecification(); } diff --git a/modules/activiti-mule/pom.xml b/modules/activiti-mule/pom.xml index 739ae324cac3ba91ddeb84e863a14b647e556210..6095bd1fc6e65006c8c77308757ea027c822b860 100644 --- a/modules/activiti-mule/pom.xml +++ b/modules/activiti-mule/pom.xml @@ -14,7 +14,7 @@ 5.0-SNAPSHOT - + @@ -24,7 +24,7 @@ - + maven-surefire-plugin @@ -34,7 +34,7 @@ - + @@ -53,28 +53,65 @@ test - org.mule.transports - mule-transport-cxf + org.mule.transports + mule-transport-cxf + + + org.slf4j + jcl104-over-slf4j + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + + - org.mule.tests - mule-tests-functional + org.mule.tests + mule-tests-functional + + + org.slf4j + jcl104-over-slf4j + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + slf4j-log4j12 + + + + org.slf4j + slf4j-jdk14 + + + commons-logging + commons-logging + + - commons-logging - commons-logging + org.springframework + spring-beans - org.springframework - spring-beans + com.h2database + h2 + test - - com.h2database - h2 - test - - + distro diff --git a/modules/activiti-mule/src/test/java/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.java b/modules/activiti-mule/src/test/java/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.java index ae7534bbcfc0c94e4708f3eef07e92d3118da266..42682e133d424a5b7d01def6406f0780aae72d59 100644 --- a/modules/activiti-mule/src/test/java/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.java +++ b/modules/activiti-mule/src/test/java/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.java @@ -3,20 +3,33 @@ package org.activiti.engine.test.bpmn.servicetask; import java.util.HashMap; import java.util.Map; -import org.activiti.engine.impl.bpmn.Message; +import org.activiti.engine.impl.bpmn.FieldBaseStructureInstance; +import org.activiti.engine.impl.bpmn.IOSpecification; +import org.activiti.engine.impl.bpmn.ItemDefinition; +import org.activiti.engine.impl.bpmn.ItemInstance; import org.activiti.engine.impl.bpmn.MessageInstance; +import org.activiti.engine.impl.bpmn.SimpleStructureDefinition; +import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; public class WebServiceUELTest extends AbstractWebServiceTaskTest { public void testWebServiceInvocationWithDataFlowUEL() throws Exception { + //TODO replace structure creation with a query to the repository + SimpleStructureDefinition simpleStructureDefinition = new SimpleStructureDefinition("structure-id"); + simpleStructureDefinition.setFieldName(0, "prefix", String.class); + simpleStructureDefinition.setFieldName(1, "suffix", String.class); + ItemDefinition itemDefinition = new ItemDefinition("definition-id", simpleStructureDefinition); + + ItemInstance itemInstance = itemDefinition.createInstance(); + FieldBaseStructureInstance structureInstance = (FieldBaseStructureInstance) itemInstance.getStructureInstance(); + structureInstance.setFieldValue("prefix", "The counter has the value "); + structureInstance.setFieldValue("suffix", ". Good news"); + Map variables = new HashMap(); - Message message = null; - MessageInstance processInput = message.createInstance(); - processInput.setFieldValue("prefix", "The counter has the value "); - processInput.setFieldValue("suffix", ". Good news"); - variables.put("dataInputOfProcess", processInput); + variables.put("dataInputOfProcess", itemInstance); ProcessInstance instance = processEngine.getRuntimeService().startProcessInstanceByKey( "webServiceInvocationWithDataFlowUEL", @@ -25,6 +38,7 @@ public class WebServiceUELTest extends AbstractWebServiceTaskTest { MessageInstance response = (MessageInstance) processEngine.getRuntimeService().getVariable(instance.getId(), "dataOutputOfProcess"); - assertEquals("The counter has the value -1. Good news", response.getFieldValue("prettyPrint")); + structureInstance = (FieldBaseStructureInstance) response.getStructureInstance(); + assertEquals("The counter has the value -1. Good news", structureInstance.getFieldValue("prettyPrint")); } } diff --git a/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceTaskTest.testWebServiceInvocationWithoutDataFlow.bpmn20.xml b/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceTaskTest.testWebServiceInvocationWithoutDataFlow.bpmn20.xml index cb69a02e460596d6b5289682de8368275eae8be1..1b55ca672312fc0557528df12dfe81588383cd62 100644 --- a/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceTaskTest.testWebServiceInvocationWithoutDataFlow.bpmn20.xml +++ b/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceTaskTest.testWebServiceInvocationWithoutDataFlow.bpmn20.xml @@ -19,7 +19,7 @@ + operationRef="tns:incOperation" /> @@ -32,18 +32,18 @@ - + - - incRequestMessage - incResponseMessage + + tns:incRequestMessage + tns:incResponseMessage - - + + - - + + \ No newline at end of file diff --git a/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.testWebServiceInvocationWithDataFlowUEL.bpmn20.xml b/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.testWebServiceInvocationWithDataFlowUEL.bpmn20.xml index a65cfc29ef057ea73313d989daf6467f0d712799..4a0643afef3af56358a76b16ef8dc066c6e761a5 100644 --- a/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.testWebServiceInvocationWithDataFlowUEL.bpmn20.xml +++ b/modules/activiti-mule/src/test/resources/org/activiti/engine/test/bpmn/servicetask/WebServiceUELTest.testWebServiceInvocationWithDataFlowUEL.bpmn20.xml @@ -25,7 +25,7 @@ --> - + dataInputOfProcess @@ -66,7 +66,7 @@ - {$dataOutputOfProcess.prettyPrint} + dataOutputOfProcess {$dataOutputOfServiceTask.prettyPrint} diff --git a/modules/activiti-mule/src/test/resources/org/activiti/test/mule/log4j.properties b/modules/activiti-mule/src/test/resources/org/activiti/test/mule/log4j.properties new file mode 100644 index 0000000000000000000000000000000000000000..b751cd16906744deb62c4e58eb6995e2eef2995f --- /dev/null +++ b/modules/activiti-mule/src/test/resources/org/activiti/test/mule/log4j.properties @@ -0,0 +1 @@ +log4j.rootCategory=INFO, S diff --git a/pom.xml b/pom.xml index f457712c671869db44bd0a21540a126caa59a838..e8fe743a02fab1362348f60c4ac02e493e93230b 100644 --- a/pom.xml +++ b/pom.xml @@ -225,6 +225,11 @@ mule-tests-functional ${mule.version} + + commons-lang + commons-lang + 2.4 + org.mybatis mybatis