KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jbpm > bpel > xml > BpelReader


1 package org.jbpm.bpel.xml;
2
3 import java.io.ByteArrayInputStream JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.util.Arrays JavaDoc;
6 import java.util.HashMap JavaDoc;
7 import java.util.HashSet JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.List JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.Set JavaDoc;
12
13 import javax.wsdl.Definition;
14 import javax.wsdl.Message;
15 import javax.wsdl.Operation;
16 import javax.wsdl.OperationType;
17 import javax.wsdl.PortType;
18 import javax.wsdl.WSDLException;
19 import javax.wsdl.xml.WSDLReader;
20 import javax.xml.namespace.QName JavaDoc;
21 import javax.xml.parsers.DocumentBuilder JavaDoc;
22 import javax.xml.transform.Transformer JavaDoc;
23 import javax.xml.transform.TransformerException JavaDoc;
24 import javax.xml.transform.dom.DOMResult JavaDoc;
25 import javax.xml.transform.dom.DOMSource JavaDoc;
26
27 import org.apache.commons.collections.Predicate;
28 import org.apache.commons.collections.iterators.FilterIterator;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.w3c.dom.Attr JavaDoc;
32 import org.w3c.dom.Document JavaDoc;
33 import org.w3c.dom.Element JavaDoc;
34 import org.w3c.dom.Node JavaDoc;
35 import org.xml.sax.InputSource JavaDoc;
36 import org.xml.sax.SAXException JavaDoc;
37
38 import org.jbpm.bpel.data.def.ElementTypeInfo;
39 import org.jbpm.bpel.data.def.MessageTypeInfo;
40 import org.jbpm.bpel.data.def.SchemaTypeInfo;
41 import org.jbpm.bpel.data.def.Snippet;
42 import org.jbpm.bpel.data.def.VariableDefinition;
43 import org.jbpm.bpel.data.def.VariableTypeInfo;
44 import org.jbpm.bpel.data.def.Snippet.Use;
45 import org.jbpm.bpel.def.Activity;
46 import org.jbpm.bpel.def.AlarmHandler;
47 import org.jbpm.bpel.def.BpelDefinition;
48 import org.jbpm.bpel.def.CompositeActivity;
49 import org.jbpm.bpel.def.FaultHandler;
50 import org.jbpm.bpel.def.Import;
51 import org.jbpm.bpel.def.ImportsDefinition;
52 import org.jbpm.bpel.def.MessageHandler;
53 import org.jbpm.bpel.def.Scope;
54 import org.jbpm.bpel.def.ScopeHandler;
55 import org.jbpm.bpel.def.Import.Type;
56 import org.jbpm.bpel.service.def.Correlation;
57 import org.jbpm.bpel.service.def.CorrelationSetDefinition;
58 import org.jbpm.bpel.service.def.Correlations;
59 import org.jbpm.bpel.service.def.PartnerLinkDefinition;
60 import org.jbpm.bpel.service.def.Receiver;
61 import org.jbpm.bpel.service.def.Correlation.Initiate;
62 import org.jbpm.bpel.timer.def.Alarm;
63 import org.jbpm.bpel.wsdl.def.PartnerLinkType;
64 import org.jbpm.bpel.wsdl.def.Property;
65 import org.jbpm.bpel.wsdl.def.PropertyAlias;
66 import org.jbpm.bpel.wsdl.def.PartnerLinkType.Role;
67 import org.jbpm.bpel.wsdl.util.WsdlUtil;
68 import org.jbpm.bpel.xml.util.NodeUtil;
69 import org.jbpm.jpdl.par.ProcessArchive;
70 import org.jbpm.jpdl.xml.Problem;
71
72 import com.ibm.wsdl.util.xml.DOMUtils;
73
74 /**
75  * @author Juan Cantú
76  * @author Alejandro Guízar
77  * @version $Revision: 1.27 $ $Date: 2005/06/23 20:45:04 $
78  */

79 public class BpelReader {
80   
81   private Map JavaDoc activityReaders;
82   private DocumentBuilder JavaDoc builder;
83   private Transformer JavaDoc bpelUpgrader;
84   private ProblemHandler problemHandler = new ProblemCollector();
85   
86   private static final BpelReader INSTANCE = new BpelReader();
87   private static final String JavaDoc BPEL_1_1_TEMPLATE = "bpel-1-1-converter.xsl";
88   private static final Log log = LogFactory.getLog(BpelReader.class);
89
90   protected BpelReader() {
91     initializeActivityParsers();
92     builder = NodeUtil.getDocumentBuilder();
93     bpelUpgrader = NodeUtil.createUpgrader(BpelReader.class.getResource(BPEL_1_1_TEMPLATE));
94   }
95   
96   /**
97    * Reads the bpel definition from the given input source
98    * @param input the input source where the bpel archive is located
99    * @param processDefinition
100    */

101   public void read(BpelDefinition processDefinition, InputSource JavaDoc input) {
102     try {
103       //parse bpel document using an error handler that collects validation problems
104
String JavaDoc location = input.getSystemId();
105       ErrorHandlerAdapter validationHandler = new ErrorHandlerAdapter(getProblemHandler());
106       builder.setErrorHandler(validationHandler);
107       Document JavaDoc bpelDocument = builder.parse(input);
108       if( !validationHandler.hasErrors() ) {
109         ImportWsdlLocator wsdlLocator = null;
110         if (location != null) {
111           wsdlLocator = new ImportWsdlLocator(location);
112           wsdlLocator.setProblemHandler(getProblemHandler());
113           processDefinition.setLocation(location);
114         }
115         read(processDefinition, bpelDocument.getDocumentElement(), wsdlLocator);
116       }
117     }
118     catch (SAXException JavaDoc e) {
119       getProblemHandler().add(
120           new Problem( Problem.LEVEL_ERROR, "bpel document contains invalid xml", e) );
121     }
122     catch (IOException JavaDoc e) {
123       getProblemHandler().add(
124           new Problem( Problem.LEVEL_ERROR, "bpel document is not readable", e) );
125     }
126   }
127
128   /**
129    * Reads the bpel definition from the given process archive
130    * @param archive the process archive where the definition is located
131    * @param processDefinition
132    */

133   public void read(BpelDefinition processDefinition, ProcessArchive archive) {
134     String JavaDoc location = processDefinition.getLocation();
135     byte[] bpelEntry = archive.removeEntry(location);
136     if (bpelEntry == null) {
137       getProblemHandler().add(
138           new Problem(Problem.LEVEL_ERROR, "bpel document not found") );
139       return;
140     }
141     try {
142       ErrorHandlerAdapter validationHandler = new ErrorHandlerAdapter(getProblemHandler());
143       builder.setErrorHandler(validationHandler);
144       Document JavaDoc bpelDocument = builder.parse(new ByteArrayInputStream JavaDoc(bpelEntry));
145       if( !validationHandler.hasErrors() ) {
146         ImportWsdlLocator wsdlLocator = new ArchiveWsdlLocator(location, archive);
147         wsdlLocator.setProblemHandler(getProblemHandler());
148         read(processDefinition, bpelDocument.getDocumentElement(), wsdlLocator);
149       }
150     }
151     catch (SAXException JavaDoc e) {
152       getProblemHandler().add(
153           new Problem( Problem.LEVEL_ERROR, "bpel document contains invalid xml", e) );
154     }
155     catch (IOException JavaDoc e) {
156       getProblemHandler().add(
157           new Problem( Problem.LEVEL_ERROR, "bpel document is not readable", e) );
158     }
159   }
160   
161   protected void read(BpelDefinition process, Element JavaDoc processElem, ImportWsdlLocator wsdlLocator) {
162     if (!BpelConstants.NS_BPWS.equals(processElem.getNamespaceURI())) {
163       //a transformation needs to be applied to the document
164
Document JavaDoc newProcessDoc = builder.newDocument();
165       ErrorListenerAdapter transformHandler = new ErrorListenerAdapter(getProblemHandler());
166       bpelUpgrader.setErrorListener(transformHandler);
167       try {
168         bpelUpgrader.transform(
169             new DOMSource JavaDoc(processElem.getOwnerDocument()), new DOMResult JavaDoc(newProcessDoc));
170       }
171       catch (TransformerException JavaDoc e) {
172         transformHandler.error(e);
173       }
174       //if transformation caused errors, stop reading
175
if(transformHandler.hasErrors()) return;
176       log.debug("upgraded bpel document: " + process.getLocation());
177       processElem = newProcessDoc.getDocumentElement();
178     }
179
180     // get attributes in the process element, including query language
181
readTopLevelAttributes(processElem, process);
182     // read imported documents
183
ImportsDefinition imports = process.getImports();
184     readImports(processElem, imports, wsdlLocator);
185     // if our wsdl locator has errors, stop reading
186
if( wsdlLocator.hasErrors() ) return;
187     
188     try {
189       // registration gets the query language from the process definition
190
registerPropertyAliases(imports);
191       // finally read the top-level scope
192
readScope(processElem, process.getScope());
193     }
194     catch(BpelException e) {
195       getProblemHandler().add( new Problem(Problem.LEVEL_ERROR, "bpel process is invalid.", e) );
196     }
197   }
198   
199   public void registerPropertyAliases(ImportsDefinition importsDef) {
200     List JavaDoc imports = importsDef.getImports();
201     // easy way out (necessary)
202
if (imports == null) return;
203     // get the process-level query language
204
BpelDefinition process = (BpelDefinition) importsDef.getProcessDefinition();
205     String JavaDoc queryLanguage = process != null ? process.getQueryLanguage() : BpelConstants.URN_XPATH_1_0;
206     // register property aliases in each wsdl document
207
for (int i = 0, n = imports.size(); i < n; i++) {
208       Import imp = (Import) imports.get(i);
209       if (imp.getType().equals(Type.WSDL)) {
210         registerPropertyAliases(importsDef, (Definition) imp.getDocument(), queryLanguage);
211       }
212     }
213   }
214   
215   private void registerPropertyAliases(ImportsDefinition importsDef, Definition def, String JavaDoc queryLanguage) {
216     // first deal with local extensibility elements...
217
Iterator JavaDoc extensionIt = def.getExtensibilityElements().iterator();
218     while (extensionIt.hasNext()) {
219       Object JavaDoc extension = extensionIt.next();
220       if (extension instanceof PropertyAlias) {
221         PropertyAlias alias = (PropertyAlias) extension;
222         // parse query
223
Snippet query = alias.getQuery();
224         if (query.getLanguage() == null) {
225           query.setLanguage(queryLanguage);
226         }
227         try {
228           query.parseScript();
229         }
230         catch(BpelException e) {
231           Problem problem = new Problem(Problem.LEVEL_ERROR,
232               "unable to parse property alias query", e);
233           problem.setResource(def.getDocumentBaseURI());
234           getProblemHandler().add(problem);
235         }
236         // move property alias to message
237
MessageTypeInfo message = importsDef.getMessageTypeInfo(alias.getMessage().getQName());
238         message.addPropertyAlias(alias);
239       }
240     }
241     // ...then deal with imported definitions
242
Iterator JavaDoc importsIter = def.getImports().values().iterator();
243     while (importsIter.hasNext()) {
244       List JavaDoc imports = (List JavaDoc) importsIter.next();
245       for (int i = 0, n = imports.size(); i < n; i++) {
246         javax.wsdl.Import imp = (javax.wsdl.Import) imports.get(i);
247         registerPropertyAliases(importsDef, imp.getDefinition(), queryLanguage);
248       }
249     }
250   }
251   
252   
253   // process properties //////////////////////////////////////////////////////////////
254

255   public void readTopLevelAttributes(Element JavaDoc processElem, BpelDefinition process) {
256     // name & namespace
257
process.setName(processElem.getAttribute(BpelConstants.ATTR_NAME));
258     process.setTargetNamespace(processElem.getAttribute(BpelConstants.ATTR_TARGET_NAMESPACE));
259     // query & expression language
260
process.setQueryLanguage(NodeUtil.getAttribute(processElem, BpelConstants.ATTR_QUERY_LANGUAGE));
261     process.setExpressionLanguage(NodeUtil.getAttribute(processElem, BpelConstants.ATTR_EXPRESSION_LANGUAGE));
262     // suppress join failure
263
Attr JavaDoc suppressAttr = processElem.getAttributeNode(BpelConstants.ATTR_SUPPRESS_JOIN_FAILURE);
264     Boolean JavaDoc suppressValue = readTBoolean(suppressAttr, Boolean.FALSE);
265     process.getScope().setSuppressJoinFailure(suppressValue);
266     // abstract process
267
Attr JavaDoc abstractAttr = processElem.getAttributeNode(BpelConstants.ATTR_ABSTRACT_PROCESS);
268     Boolean JavaDoc abstractValue = readTBoolean(abstractAttr, Boolean.FALSE);
269     process.setAbstractProcess(abstractValue.booleanValue());
270     // enable instance compensation
271
Attr JavaDoc compensationAttr = processElem.getAttributeNode(BpelConstants.ATTR_INSTANCE_COMPENSATION);
272     Boolean JavaDoc compensationValue = readTBoolean(compensationAttr, Boolean.FALSE);
273     process.setEnableInstanceCompensation(compensationValue.booleanValue());
274   }
275   
276   public void readImports(Element JavaDoc processElem, ImportsDefinition imports,
277       ImportWsdlLocator wsdlLocator) {
278     Iterator JavaDoc importElemIt = NodeUtil.getElements(processElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_IMPORT);
279     while (importElemIt.hasNext()) {
280       Import imp = readImport((Element JavaDoc) importElemIt.next());
281       if (Import.Type.WSDL.equals(imp.getType())) {
282         readWsdlDocument(imp, wsdlLocator);
283       }
284       imports.addImport(imp);
285     }
286   }
287   
288   public Import readImport(Element JavaDoc importElem) {
289     Import imp = new Import();
290     imp.setNamespace(importElem.getAttribute(BpelConstants.ATTR_NAMESPACE));
291     imp.setLocation(importElem.getAttribute(BpelConstants.ATTR_LOCATION));
292     imp.setType(Import.Type.valueOf(importElem.getAttribute(BpelConstants.ATTR_IMPORT_TYPE)));
293     return imp;
294   }
295   
296   public void readWsdlDocument(Import imp, ImportWsdlLocator wsdlLocator) {
297     String JavaDoc location = imp.getLocation();
298     wsdlLocator.resolveBaseURI(location);
299     WSDLReader reader = WsdlUtil.getFactory().newWSDLReader();
300     // read imported WSDL document
301
Definition def;
302     try {
303       log.debug("read wsdl document: " + location);
304       def = reader.readWSDL(wsdlLocator);
305       // validate the definitions belong to the import's namespace
306
if (!def.getTargetNamespace().equals(imp.getNamespace())) {
307         Problem problem = new Problem(Problem.LEVEL_ERROR,
308             "imported definitions do not belong to the import's namespace");
309         problem.setResource(def.getDocumentBaseURI());
310         getProblemHandler().add(problem);
311       }
312       imp.setDocument(def);
313     }
314     catch (WSDLException e) {
315       Problem problem = new Problem(Problem.LEVEL_ERROR, "could not read wsdl document", e);
316       problem.setResource(location);
317       getProblemHandler().add(problem);
318     }
319   }
320
321   
322   // general properties //////////////////////////////////////////////////////////////
323

324   public Boolean JavaDoc readTBoolean(Attr JavaDoc attribute, Boolean JavaDoc defaultValue) {
325     if (attribute == null) {
326       return defaultValue;
327     }
328     String JavaDoc text = attribute.getValue();
329     return Boolean.valueOf( BpelConstants.YES.equalsIgnoreCase(text) );
330   }
331   
332   public Snippet readExpression(Element JavaDoc enclosingElement, CompositeActivity parent, Use use) {
333     // expression
334
Snippet expr = new Snippet();
335     expr.setText(DOMUtils.getChildCharacterData(enclosingElement));
336     expr.setNamespaces(NodeUtil.getNamespaceDeclarations(enclosingElement));
337     expr.setUse(use);
338     // language
339
String JavaDoc language = NodeUtil.getAttribute(enclosingElement, BpelConstants.ATTR_EXPRESSION_LANGUAGE);
340     if (language == null) {
341       BpelDefinition process = parent.getBpelDefinition();
342       if (use == Use.EXPRESSION || use == Use.JOIN_CONDITION) {
343         language = process.getExpressionLanguage();
344       }
345       else if (use == Use.QUERY || use == Use.PROPERTY_ALIAS) {
346         language = process.getQueryLanguage();
347       }
348     }
349     expr.setLanguage(language);
350     // parsing
351
try {
352       expr.parseScript();
353       return expr;
354     }
355     catch (BpelException e) {
356       getProblemHandler().add(
357           new Problem( Problem.LEVEL_ERROR, "unable to read expression.", e) );
358       return null;
359     }
360   }
361   
362   public Snippet readExpression(Element JavaDoc enclosingElement, CompositeActivity parent) {
363     return readExpression(enclosingElement, parent, Use.EXPRESSION);
364   }
365   
366   // scope definition properties //////////////////////////////////////////////////////////////
367

368   public void readScope(Element JavaDoc scopeElem, Scope scope) {
369     // variables
370
Element JavaDoc variablesElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_VARIABLES );
371     if (variablesElem != null ) scope.setVariables ( readVariables(variablesElem, scope) );
372     
373     // partner links
374
Element JavaDoc partnerLinksElem = NodeUtil.getElement( scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_PARTNER_LINKS );
375     if (partnerLinksElem != null ) scope.setPartnerLinks( readPartnerLinks(partnerLinksElem, scope) );
376     
377     // correlation sets
378
Element JavaDoc setsElem = NodeUtil.getElement( scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SETS );
379     if (setsElem != null ) scope.setCorrelationSets( readCorrelationSets(setsElem, scope) );
380     
381     // activity
382
Element JavaDoc activityElem = getActivityElement(scopeElem);
383     readActivity(activityElem, scope);
384     
385     // fault handlers
386
Element JavaDoc faultHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_FAULT_HANDLERS );
387     if( faultHandlerElem != null ) readFaultHandlers(faultHandlerElem, scope);
388     
389     // compensation handler
390
Element JavaDoc compHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_COMPENSATION_HANDLER );
391     if( compHandlerElem != null ) readHandler(compHandlerElem, scope, Scope.COMPENSATION);
392     
393     // event handlers
394
Element JavaDoc eventHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_EVENT_HANDLERS );
395     if( eventHandlerElem != null ) readEventHandlers(eventHandlerElem, scope);
396     
397     // termination handler
398
Element JavaDoc termHandlerElem = NodeUtil.getElement(scopeElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_TERMINATION_HANDLER );
399     if( termHandlerElem != null ) readHandler(termHandlerElem, scope, Scope.TERMINATION);
400   }
401  
402   public void readHandler(Element JavaDoc element, Scope scope, Scope.HandlerType type) {
403     ScopeHandler handler = new ScopeHandler();
404     scope.setHandler(type, handler);
405     Element JavaDoc activityElement = getActivityElement(element);
406     handler.setActivity(readActivity(activityElement, handler));
407   }
408   
409   public void readFaultHandlers(Element JavaDoc faultHandlerElem, Scope scope) {
410     //load catchAll
411
Element JavaDoc catchAllElem = NodeUtil.getElement(faultHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CATCH_ALL );
412     if( catchAllElem != null ) {
413       readHandler(catchAllElem, scope, Scope.CATCH_ALL);
414     }
415     
416     Iterator JavaDoc catchElemIt = NodeUtil.getElements(faultHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CATCH);
417     while (catchElemIt.hasNext()) {
418       Element JavaDoc catchElement = (Element JavaDoc) catchElemIt.next();
419       readFaultHandler( catchElement, scope );
420     }
421   }
422   
423   public void readFaultHandler(Element JavaDoc catchElement, Scope scope) {
424     FaultHandler faultHandler = new FaultHandler();
425     scope.addFaultHandler(faultHandler);
426     Element JavaDoc activityElement = getActivityElement(catchElement);
427     faultHandler.setActivity(readActivity(activityElement, faultHandler));
428     
429     /*These valid configurations for a faultHandler are:
430      *-Catching faults without data:
431      * (faultName)
432      *-Catching faults with data:
433      * (faultName AND (elementType OR messageType)) , faultVariable?
434      * (faultVariable AND (elementType OR messageType))*/

435     
436     String JavaDoc faultNameStr = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_NAME);
437     if( faultNameStr != null) {
438       QName JavaDoc faultName = NodeUtil.getQName(faultNameStr, catchElement);
439       faultHandler.setFaultName(faultName);
440     }
441     String JavaDoc variableName = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_VARIABLE);
442     boolean hasName = faultHandler.getFaultName() != null;
443     if( variableName == null && !hasName) {
444       getProblemHandler().add(
445           new LocalizedProblem( Problem.LEVEL_ERROR,
446               "catch must specify either a faultName or a faultVariable", catchElement ) );
447       return;
448     }
449     VariableTypeInfo faultTypeInfo = null;
450     ImportsDefinition imports = scope.getBpelDefinition().getImports();
451     String JavaDoc faultMessageType = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_MESSAGE_TYPE);
452     String JavaDoc faultElement = NodeUtil.getAttribute(catchElement, BpelConstants.ATTR_FAULT_ELEMENT);
453     if( faultMessageType != null ) {
454       //fault message type
455
if(faultElement != null) {
456         getProblemHandler().add(
457             new LocalizedProblem( Problem.LEVEL_ERROR,
458                 "faultMessageType and faultElement can't be both present", catchElement ) );
459       }
460       faultTypeInfo = getMessageTypeInfo(catchElement, faultMessageType, imports);
461     }
462     else if( faultElement != null ) {
463       //fault element
464
faultTypeInfo = getElementTypeInfo(catchElement, faultElement, imports);
465     }
466     
467     if(variableName != null) {
468       //faultVariable
469
if(faultTypeInfo == null) {
470         throw new BpelException("catch must specify either a faultMessageType or a faultElement", catchElement);
471       }
472       VariableDefinition variable = new VariableDefinition(variableName);
473       variable.setTypeInfo(faultTypeInfo);
474       faultHandler.setFaultVariable(variable);
475     }
476   }
477   
478   public void readEventHandlers(Element JavaDoc eventHandlerElem, Scope scope) {
479     //onEvents
480
Iterator JavaDoc eventElemIt = NodeUtil.getElements(eventHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_ON_EVENT);
481     while (eventElemIt.hasNext()) {
482       Element JavaDoc eventElem = (Element JavaDoc) eventElemIt.next();
483       MessageHandler handler = new MessageHandler();
484       scope.addMessageHandler(handler);
485       //read variable if message type is present (support for bpel 1.1)
486
String JavaDoc messageType = NodeUtil.getAttribute(eventElem, BpelConstants.ATTR_MESSAGE_TYPE);
487       if(messageType != null) {
488         VariableDefinition variable = new VariableDefinition();
489         // name
490
String JavaDoc name = NodeUtil.getAttribute(eventElem, BpelConstants.ATTR_VARIABLE);
491         variable.setName(name);
492         // type info
493
VariableTypeInfo typeInfo = getMessageTypeInfo(eventElem, messageType, scope.getBpelDefinition().getImports());
494         variable.setTypeInfo(typeInfo);
495         handler.setVariableDefinition(variable);
496       }
497       //correlation sets
498
Element JavaDoc setsElem = NodeUtil.getElement( eventElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SETS );
499       if (setsElem != null ) handler.setCorrelationSets( readCorrelationSets(setsElem, scope) );
500       //activity
501
Element JavaDoc activityElem = getActivityElement(eventElem);
502       readActivity(activityElem, handler);
503       //message attributes
504
Receiver receiver = readReceiver(eventElem, handler);
505       receiver.setInboundMessageActivity( handler );
506       handler.setReceiver(receiver);
507     }
508     //onAlarms
509
Iterator JavaDoc alarmElemIt = NodeUtil.getElements(eventHandlerElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_ON_ALARM);
510     while (alarmElemIt.hasNext()) {
511       AlarmHandler handler = new AlarmHandler();
512       scope.addAlarmHandler(handler);
513       Element JavaDoc alarmElem = (Element JavaDoc) alarmElemIt.next();
514       Element JavaDoc activityElem = getActivityElement(alarmElem);
515       readActivity(activityElem, handler);
516       Alarm alarm = readAlarm(alarmElem, handler);
517       alarm.setAlarmActivity(handler);
518       handler.setAlarm(alarm);
519     }
520   }
521   
522   public Map JavaDoc readVariables(Element JavaDoc variablesElem, CompositeActivity parent) {
523     Map JavaDoc variables = new HashMap JavaDoc();
524     ImportsDefinition imports = parent.getBpelDefinition().getImports();
525     Iterator JavaDoc variableElemIt = NodeUtil.getElements(variablesElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_VARIABLE);
526     while (variableElemIt.hasNext()) {
527       Element JavaDoc variableElem = (Element JavaDoc) variableElemIt.next();
528       VariableDefinition variable = readVariable(variableElem, imports);
529       String JavaDoc variableName = variable.getName();
530       if( variables.containsKey(variableName) ) {
531         getProblemHandler().add(
532             new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", variableElem ) );
533       }
534       else {
535         variables.put(variableName, variable);
536       }
537     }
538     return variables;
539   }
540   
541   public VariableDefinition readVariable(Element JavaDoc variableElem, ImportsDefinition imports) {
542     VariableDefinition variable = new VariableDefinition();
543     // name
544
String JavaDoc name = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_NAME);
545     variable.setName(name);
546     // type info
547
VariableTypeInfo typeInfo = getTypeInfo(variableElem, imports);
548     variable.setTypeInfo(typeInfo);
549     return variable;
550   }
551    
552   private VariableTypeInfo getTypeInfo(Element JavaDoc variableElem, ImportsDefinition imports) {
553     VariableTypeInfo typeInfo;
554     
555     String JavaDoc type = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_TYPE);
556     String JavaDoc messageType = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_MESSAGE_TYPE);
557     String JavaDoc element = NodeUtil.getAttribute(variableElem, BpelConstants.ATTR_ELEMENT);
558
559     if (messageType != null) {
560       if (type != null || element != null) {
561         getProblemHandler().add(
562             new LocalizedProblem( Problem.LEVEL_ERROR, "more than one type specifier is used", variableElem ) );
563       }
564       typeInfo = getMessageTypeInfo(variableElem, messageType, imports);
565     }
566     
567     else if (type != null) {
568       if (element != null) {
569         getProblemHandler().add(
570             new LocalizedProblem( Problem.LEVEL_ERROR, "more than one type specifier is used", variableElem ) );
571       }
572       typeInfo = getSchemaTypeInfo(variableElem, type, imports);
573     }
574     else if (element != null) {
575       typeInfo = getElementTypeInfo(variableElem, element, imports);
576     }
577     else {
578       throw new BpelException("no type specifier is used", variableElem);
579     }
580     return typeInfo;
581   }
582   
583   private MessageTypeInfo getMessageTypeInfo(Element JavaDoc parent, String JavaDoc messageType, ImportsDefinition imports) {
584     QName JavaDoc qname = NodeUtil.getQName(messageType, parent);
585     MessageTypeInfo typeInfo = imports.getMessageTypeInfo(qname);
586     if (typeInfo == null) {
587       throw new BpelException("message type " + messageType + " not found", parent);
588     }
589     return typeInfo;
590   }
591   
592   private ElementTypeInfo getElementTypeInfo(Element JavaDoc parent, String JavaDoc elementType, ImportsDefinition imports) {
593     QName JavaDoc qname = NodeUtil.getQName(elementType, parent);
594     ElementTypeInfo typeInfo = imports.getElementTypeInfo(qname);
595     if (typeInfo == null) {
596       throw new BpelException("element type " + elementType + " not found", parent);
597     }
598     return typeInfo;
599   }
600
601   private SchemaTypeInfo getSchemaTypeInfo(Element JavaDoc parent, String JavaDoc schemaType, ImportsDefinition imports) {
602     QName JavaDoc qname = NodeUtil.getQName(schemaType, parent);
603     SchemaTypeInfo typeInfo = imports.getSchemaTypeInfo(qname);
604     if (typeInfo == null) {
605       throw new BpelException("schema type " + schemaType + " not found", parent);
606     }
607     return typeInfo;
608   }
609   
610   // service properties //////////////////////////////////////////////////////////////
611

612   public Map JavaDoc readCorrelationSets(Element JavaDoc setsElem, CompositeActivity superState) {
613     Map JavaDoc correlationSets = new HashMap JavaDoc();
614     ImportsDefinition imports = superState.getBpelDefinition().getImports();
615     Iterator JavaDoc setElemIt = NodeUtil.getElements(setsElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION_SET);
616     while (setElemIt.hasNext()) {
617       Element JavaDoc setElem = (Element JavaDoc) setElemIt.next();
618       CorrelationSetDefinition set = readCorrelationSet(setElem, imports);
619       String JavaDoc setName = set.getName();
620       if (correlationSets.containsKey(setName)) {
621         getProblemHandler().add(
622             new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", setElem ) );
623       }
624       else {
625         correlationSets.put(setName, set);
626       }
627     }
628     return correlationSets;
629   }
630   
631   public CorrelationSetDefinition readCorrelationSet(Element JavaDoc setElem, ImportsDefinition imports) {
632     CorrelationSetDefinition set = new CorrelationSetDefinition();
633     // properties
634
String JavaDoc[] propertyNames = setElem.getAttribute(BpelConstants.ATTR_PROPERTIES).split("\\s");
635     for (int p = 0; p < propertyNames.length; p++) {
636       String JavaDoc propertyName = propertyNames[p];
637       Property property = imports.getProperty(NodeUtil.getQName(propertyName, setElem));
638       if (property == null) {
639         throw new BpelException("property not found: " + propertyName, setElem);
640       }
641       set.addProperty(property);
642     }
643     // name
644
set.setName(setElem.getAttribute(BpelConstants.ATTR_NAME));
645     return set;
646   }
647   
648   public Map JavaDoc readPartnerLinks(Element JavaDoc partnerLinksElem, CompositeActivity parent) {
649     Map JavaDoc partnerLinks = new HashMap JavaDoc();
650     Iterator JavaDoc partnerLinkElemIt = NodeUtil.getElements(partnerLinksElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_PARTNER_LINK);
651     while (partnerLinkElemIt.hasNext()) {
652       Element JavaDoc partnerLinkElem = (Element JavaDoc) partnerLinkElemIt.next();
653       PartnerLinkDefinition partnerLink = readPartnerLink(partnerLinkElem, parent);
654       String JavaDoc plinkName = partnerLink.getName();
655       if ( partnerLinks.containsKey(plinkName) ) {
656         getProblemHandler().add(
657             new LocalizedProblem( Problem.LEVEL_ERROR, "duplicate local name", partnerLinkElem ) );
658       }
659       else {
660         partnerLinks.put(plinkName, partnerLink);
661       }
662     }
663     return partnerLinks;
664   }
665   
666   public PartnerLinkDefinition readPartnerLink(Element JavaDoc partnerLinkElem, CompositeActivity parent) {
667     PartnerLinkDefinition partnerLink = new PartnerLinkDefinition();
668     // partner link type
669
String JavaDoc typeName = partnerLinkElem.getAttribute(BpelConstants.ATTR_PARTNER_LINK_TYPE);
670     QName JavaDoc typeQName = NodeUtil.getQName(typeName, partnerLinkElem);
671     PartnerLinkType type = parent.getBpelDefinition().getImports().getPartnerLinkType(typeQName);
672     if (type == null) {
673       throw new BpelException("partner link type not found", partnerLinkElem);
674     }
675     partnerLink.setPartnerLinkType(type);
676     
677     String JavaDoc myRoleName = NodeUtil.getAttribute(partnerLinkElem, BpelConstants.ATTR_MY_ROLE);
678     String JavaDoc partnerRoleName = NodeUtil.getAttribute(partnerLinkElem, BpelConstants.ATTR_PARTNER_ROLE);
679     
680     // first role
681
boolean partnerRoleIsFirst;
682     Role role = type.getFirstRole();
683     String JavaDoc roleName = role.getName();
684     if (roleName.equals(myRoleName)) {
685       partnerLink.setMyRole(role);
686       partnerRoleIsFirst = false;
687     }
688     else if (roleName.equals(partnerRoleName)) {
689       partnerLink.setPartnerRole(role);
690       partnerRoleIsFirst = true;
691     }
692     else {
693       throw new BpelException("neither myRole nor partnerRole match the first role", partnerLinkElem);
694     }
695     // second role
696
role = type.getSecondRole();
697     if (role != null) {
698       roleName = role.getName();
699       if (partnerRoleIsFirst) {
700         if (!roleName.equals(myRoleName)) {
701           throw new BpelException("partnerRole matches the first role, " +
702               "but myRole does not match the second one", partnerLinkElem);
703         }
704         partnerLink.setMyRole(role);
705       }
706       else {
707         if (!roleName.equals(partnerRoleName)) {
708           throw new BpelException("myRole matches the first role, " +
709               "but partnerRole does not match the second one", partnerLinkElem);
710         }
711         partnerLink.setPartnerRole(role);
712       }
713     }
714     else if (partnerRoleIsFirst ? myRoleName != null : partnerRoleName != null) {
715       throw new BpelException("both myRole and partnerRole are specified, " +
716           "but there is only one role", partnerLinkElem);
717     }
718     // FIXME id should be set by the database
719
partnerLink.setId(partnerLink.hashCode());
720     // name
721
partnerLink.setName(partnerLinkElem.getAttribute(BpelConstants.ATTR_NAME));
722     return partnerLink;
723   }
724   
725   public Receiver readReceiver(Element JavaDoc receiverElem, CompositeActivity parent) {
726     Receiver receiver = new Receiver();
727     // partner link
728
String JavaDoc plinkName = receiverElem.getAttribute( BpelConstants.ATTR_PARTNER_LINK );
729     PartnerLinkDefinition partnerLink = parent.findPartnerLink(plinkName);
730     if (partnerLink == null) {
731       getProblemHandler().add(
732           new LocalizedProblem( Problem.LEVEL_ERROR, "partner link not found", receiverElem ) );
733       return null;
734     }
735     receiver.setPartnerLink( partnerLink );
736     // port type
737
PortType portType = getPortType(receiverElem, partnerLink.getMyRole());
738     // operation
739
Operation operation = getOperation(receiverElem, portType);
740     receiver.setOperation( operation );
741     // variable
742
VariableDefinition variable = getVariable(receiverElem, BpelConstants.ATTR_VARIABLE, parent,
743         operation.getInput().getMessage());
744     receiver.setVariable( variable );
745     // message exchange: if the attribute is not specified then its value is taken to be empty
746
receiver.setMessageExchange(receiverElem.getAttribute(BpelConstants.ATTR_MESSAGE_EXCHANGE));
747     // correlations
748
Element JavaDoc correlationsElement = NodeUtil.getElement(receiverElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATIONS );
749     if (correlationsElement != null) {
750       receiver.setCorrelations(readCorrelations(correlationsElement, parent, variable));
751     }
752     // FIXME id should be generated by the database
753
receiver.setId(receiver.hashCode());
754     return receiver;
755   }
756
757   public Correlations readCorrelations(Element JavaDoc correlationsElem, CompositeActivity parent, VariableDefinition variable) {
758     Correlations correlations = new Correlations();
759     Iterator JavaDoc correlationElemIt = NodeUtil.getElements(correlationsElem, BpelConstants.NS_BPWS, BpelConstants.ELEM_CORRELATION);
760     while (correlationElemIt.hasNext()) {
761       Correlation correlation = readCorrelation((Element JavaDoc) correlationElemIt.next(), parent);
762       checkVariableProperties(variable, correlation.getSet());
763       correlations.addCorrelation(correlation);
764     }
765     return correlations;
766   }
767   
768   public Correlation readCorrelation(Element JavaDoc correlationElem, CompositeActivity parent) {
769     Correlation correlation = new Correlation();
770     // correlation set
771
CorrelationSetDefinition set = parent.findCorrelationSet(correlationElem.getAttribute(BpelConstants.ATTR_SET));
772     if (set == null) {
773       throw new BpelException("correlation set not found", correlationElem);
774     }
775     correlation.setSet(set);
776     // initiate mode
777
correlation.setInitiate(Initiate.valueOf(NodeUtil.getAttribute(correlationElem, BpelConstants.ATTR_INITIATE)));
778     return correlation;
779   }
780   
781   PortType getPortType(Element JavaDoc serviceElem, Role role) {
782     PortType implicitPortType = role.getPortType();
783     String JavaDoc portTypeName = NodeUtil.getAttribute(serviceElem, BpelConstants.ATTR_PORT_TYPE );
784     if (portTypeName != null) {
785       QName JavaDoc portTypeQName = NodeUtil.getQName(portTypeName, serviceElem);
786       if ( !portTypeQName.equals(implicitPortType.getQName()) )
787         getProblemHandler().add(
788             new LocalizedProblem( Problem.LEVEL_ERROR,
789                 "port type does not match the port type expected by the partner link", serviceElem) );
790     }
791     return implicitPortType;
792   }
793
794   Operation getOperation(Element JavaDoc serviceElem, PortType portType) {
795     String JavaDoc operationName = serviceElem.getAttribute( BpelConstants.ATTR_OPERATION );
796     Operation op;
797     try {
798       op = portType.getOperation( operationName, null, null );
799     }
800     catch (RuntimeException JavaDoc e) {
801       throw new BpelException("overloaded operations are not supported", serviceElem);
802     }
803     if (op == null) {
804       throw new BpelException("operation not found", serviceElem);
805     }
806     OperationType opType = op.getStyle();
807     if (opType.equals(OperationType.SOLICIT_RESPONSE) ||
808         opType.equals(OperationType.NOTIFICATION)) {
809       getProblemHandler().add(
810           new LocalizedProblem( Problem.LEVEL_ERROR,
811               "operation style not supported: " + opType, serviceElem) );
812     }
813     return op;
814   }
815   
816   VariableDefinition getVariable(Element JavaDoc serviceElem, String JavaDoc variableAttr, CompositeActivity parent,
817       Message operationMessage) {
818     // get variable name
819
String JavaDoc variableName = NodeUtil.getAttribute(serviceElem, variableAttr );
820     if (variableName == null) {
821       throw new BpelException(variableAttr + " attribute is missing", serviceElem);
822     }
823     // find variable
824
VariableDefinition variable = parent.findVariable(variableName);
825     if( variable == null ) {
826       throw new BpelException(variableAttr + " not found", serviceElem);
827     }
828     // validate type
829
else if( !variable.getTypeInfo().getName().equals(operationMessage.getQName()) ) {
830       getProblemHandler().add(
831           new LocalizedProblem(Problem.LEVEL_ERROR, "type of " + variableAttr +
832               " is not applicable for the operation", serviceElem) );
833     }
834     
835     return variable;
836   }
837   
838   void checkVariableProperties(VariableDefinition variable, CorrelationSetDefinition set) {
839     Set JavaDoc msgProperties = new HashSet JavaDoc();
840     Map JavaDoc aliases = variable.getTypeInfo().getPropertyAliases();
841     if (aliases != null) {
842       Iterator JavaDoc aliasIt = aliases.values().iterator();
843       while (aliasIt.hasNext()) {
844         PropertyAlias alias = (PropertyAlias) aliasIt.next();
845         msgProperties.add(alias.getProperty());
846       }
847     }
848     Iterator JavaDoc setPropertyIt = set.getProperties().iterator();
849     while (setPropertyIt.hasNext()) {
850       Property setProperty = (Property) setPropertyIt.next();
851       if (!msgProperties.contains(setProperty)) {
852         getProblemHandler().add(
853             new Problem( Problem.LEVEL_ERROR, "property " + setProperty.getQName() +
854             " does not appear in variable " + variable.getName()) );
855       }
856     }
857   }
858   
859   // alarm properties //////////////////////////////////////////////////////////////
860

861   public Alarm readAlarm(Element JavaDoc element, CompositeActivity parent) {
862     Alarm alarm = new Alarm();
863     Element JavaDoc repeatElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_REPEAT);
864     if(repeatElement != null) {
865       alarm.setRepeatEvery(readExpression(repeatElement, parent));
866       alarm.setAlarmKind(Alarm.AlarmKind.CYCLIC);
867     }
868     
869     Element JavaDoc forElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_FOR);
870     if(forElement != null) {
871       alarm.setFor(readExpression(forElement, parent));
872       
873       if(!Alarm.AlarmKind.CYCLIC.equals(alarm.getAlarmKind())) {
874         alarm.setAlarmKind(Alarm.AlarmKind.DURATION);
875       }
876     }
877     
878     Element JavaDoc untilElement = NodeUtil.getElement(element, BpelConstants.NS_BPWS, BpelConstants.ELEM_UNTIL);
879     if(untilElement != null) {
880       alarm.setUntil(readExpression(untilElement, parent));
881       
882       if(!Alarm.AlarmKind.CYCLIC.equals(alarm.getAlarmKind())) {
883         alarm.setAlarmKind(Alarm.AlarmKind.DEADLINE);
884       }
885     }
886     
887     if(alarm.getAlarmKind() == null)
888       getProblemHandler().add(
889           new LocalizedProblem( Problem.LEVEL_ERROR, "alarm expression is missing", element ) );
890     
891     return alarm;
892   }
893
894   // child activities //////////////////////////////////////////////////////////////
895

896   public Activity readActivity(Element JavaDoc activityElem, CompositeActivity parent) {
897     String JavaDoc name = activityElem.getLocalName();
898     ActivityReader parser = (ActivityReader) activityReaders.get(name);
899     if (parser == null) {
900       throw new BpelException("no reader registered for activity", activityElem);
901     }
902     return parser.read(activityElem, parent);
903   }
904
905   protected Element JavaDoc getActivityElement(Element JavaDoc parent) {
906     for (Node JavaDoc child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
907       if (ActivityElementPredicate.evaluate(child)) {
908         return (Element JavaDoc) child;
909       }
910     }
911     return null;
912   }
913   
914   protected Iterator JavaDoc getActivityElements(Element JavaDoc parent) {
915     return new FilterIterator(NodeUtil.getNodes(parent), new ActivityElementPredicate());
916   }
917   
918   public ActivityReader getActivityReader(String JavaDoc name) {
919     return (ActivityReader) activityReaders.get(name);
920   }
921   
922   public void registerActivityReader(String JavaDoc name, ActivityReader reader) {
923     reader.setBpelReader(this);
924     activityReaders.put(name, reader);
925   }
926
927   protected void initializeActivityParsers() {
928     activityReaders = new HashMap JavaDoc();
929     registerActivityReader(BpelConstants.ELEM_RECEIVE, new ReceiveReader());
930     registerActivityReader(BpelConstants.ELEM_REPLY, new ReplyReader());
931     registerActivityReader(BpelConstants.ELEM_INVOKE, new InvokeReader());
932     registerActivityReader(BpelConstants.ELEM_EMPTY, new EmptyReader());
933     registerActivityReader(BpelConstants.ELEM_ASSIGN, new AssignReader());
934     registerActivityReader(BpelConstants.ELEM_THROW, new ThrowReader());
935     registerActivityReader(BpelConstants.ELEM_EXIT, new ExitReader());
936     registerActivityReader(BpelConstants.ELEM_WAIT, new WaitReader());
937     registerActivityReader(BpelConstants.ELEM_SEQUENCE, new SequenceReader());
938     registerActivityReader(BpelConstants.ELEM_SWITCH, new SwitchReader());
939     registerActivityReader(BpelConstants.ELEM_WHILE, new WhileReader());
940     registerActivityReader(BpelConstants.ELEM_PICK, new PickReader());
941     registerActivityReader(BpelConstants.ELEM_FLOW, new FlowReader());
942     registerActivityReader(BpelConstants.ELEM_SCOPE, new ScopeReader());
943     registerActivityReader(BpelConstants.ELEM_COMPENSATE, new CompensateReader());
944     registerActivityReader(BpelConstants.ELEM_VALIDATE, new ValidateReader());
945   }
946   
947   protected ProblemHandler getProblemHandler() {
948     if(problemHandler == null) {
949       problemHandler = new DefaultProblemHandler();
950     }
951     return problemHandler;
952   }
953   
954   public void setProblemHandler(ProblemHandler problemHandler) {
955     this.problemHandler = problemHandler;
956   }
957
958   public static BpelReader getInstance() {
959     return INSTANCE;
960   }
961
962   private static class ActivityElementPredicate implements Predicate {
963     
964     private static final Set JavaDoc activityNames = new HashSet JavaDoc(Arrays.asList(BpelConstants.BPEL_2_ACTIVITIES));
965   
966     /** {@inheritDoc} */
967     public boolean evaluate(Object JavaDoc arg) {
968       return evaluate((Node JavaDoc) arg);
969     }
970     
971     static boolean evaluate(Node JavaDoc node) {
972       // the node is an element
973
return node.getNodeType() == Node.ELEMENT_NODE
974       // in the BPEL namespace
975
&& BpelConstants.NS_BPWS.equals(node.getNamespaceURI())
976       // and in the activities space
977
&& activityNames.contains(node.getLocalName());
978     }
979   }
980 }
981
Popular Tags