/*
* JBoss, Home of Professional Open Source
* Copyright 2008-11, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.savara.bpmn2.parser.choreo;
import java.util.logging.Logger;
import javax.xml.bind.JAXBElement;
import org.savara.bpmn2.internal.parser.choreo.BPMN2ChoreographyParserUtil;
import org.savara.bpmn2.internal.parser.choreo.rules.BPMN2ParserContext;
import org.savara.bpmn2.internal.parser.choreo.rules.BPMN2ParserRule;
import org.savara.bpmn2.internal.parser.choreo.rules.DefaultBPMN2ParserContext;
import org.savara.bpmn2.internal.parser.choreo.rules.ParserRuleFactory;
import org.savara.bpmn2.internal.parser.choreo.rules.Scope;
import org.savara.bpmn2.model.TChoreography;
import org.savara.bpmn2.model.TImport;
import org.savara.bpmn2.model.TItemDefinition;
import org.savara.bpmn2.model.TMessage;
import org.savara.bpmn2.model.TRootElement;
import org.savara.bpmn2.model.util.BPMN2ModelUtil;
import org.savara.common.model.annotation.Annotation;
import org.savara.common.model.annotation.AnnotationDefinitions;
import org.savara.protocol.model.util.TypeSystem;
import org.savara.protocol.util.FeedbackHandlerProxy;
import org.savara.protocol.util.ProtocolUtils;
import org.scribble.common.logging.Journal;
import org.scribble.common.resource.Content;
import org.scribble.protocol.ProtocolContext;
import org.scribble.protocol.model.Block;
import org.scribble.protocol.model.DataType;
import org.scribble.protocol.model.ModelProperties;
import org.scribble.protocol.model.Protocol;
import org.scribble.protocol.model.ProtocolModel;
import org.scribble.protocol.model.TypeImport;
import org.scribble.protocol.model.TypeImportList;
import org.scribble.protocol.parser.AnnotationProcessor;
import org.scribble.protocol.parser.ProtocolParser;
/**
* This class provides the model parser for the BPMN2 notation.
*
*/
public class BPMN2ChoreographyProtocolParser implements ProtocolParser {
private static final String BPMN_FILE_EXTENSION = "bpmn";
private static Logger logger = Logger.getLogger(BPMN2ChoreographyProtocolParser.class.getName());
public boolean isSupported(Content content) {
return(content.hasExtension(BPMN_FILE_EXTENSION));
}
public ProtocolModel parse(ProtocolContext context, Content content, Journal journal)
throws java.io.IOException {
ProtocolModel ret=null;
java.io.InputStream is=content.getInputStream();
org.savara.bpmn2.model.TDefinitions defns=BPMN2ModelUtil.deserialize(is);
is.close();
Scope scope=BPMN2ChoreographyParserUtil.createScope(defns);
BPMN2ChoreographyParserUtil.initializeScope(scope, defns);
BPMN2ParserContext parserContext=
new DefaultBPMN2ParserContext(new FeedbackHandlerProxy(journal), scope);
for (JAXBElement<? extends TRootElement> elem : defns.getRootElement()) {
if (elem.getDeclaredType() == TChoreography.class) {
TChoreography choreo=(TChoreography)elem.getValue();
ProtocolModel pm=new ProtocolModel();
// Construct the choreography behaviour
Protocol p=new Protocol();
p.setName(choreo.getName());
p.setBlock(new Block());
pm.setProtocol(p);
initialize(pm, defns);
// Create annotation to link the protocol to the source choreography
Annotation pann=new Annotation(AnnotationDefinitions.PROTOCOL);
pann.getProperties().put(AnnotationDefinitions.NAMESPACE_PROPERTY,
defns.getTargetNamespace());
p.getAnnotations().add(pann);
// Create annotation to link the protocol to the source choreography
Annotation scann=new Annotation(AnnotationDefinitions.SOURCE_COMPONENT);
scann.getProperties().put(AnnotationDefinitions.ID_PROPERTY,
choreo.getId());
p.getAnnotations().add(scann);
p.getProperties().put(ModelProperties.URI, choreo.getId());
// Push scope when processing the choreography
parserContext.pushScope();
BPMN2ChoreographyParserUtil.initializeScope(parserContext.getScope(), choreo);
// Process the flow element list
BPMN2ParserRule rule=ParserRuleFactory.getParserRule(choreo);
rule.parse(parserContext, choreo, p.getBlock());
parserContext.popScope();
// Localise the role introductions to the inner most
// block within which their behaviour exists
ProtocolUtils.localizeRoleIntroductions(pm);
ret = pm;
break;
}
}
return(ret);
}
public void setAnnotationProcessor(AnnotationProcessor ap) {
// Not required
}
protected void initialize(ProtocolModel pm, org.savara.bpmn2.model.TDefinitions defns) {
java.util.Map<String, String> nsprefix=new java.util.HashMap<String, String>();
java.util.List<String> defaultprefix=new java.util.Vector<String>();
java.util.Map<String, String> nslocation=new java.util.HashMap<String, String>();
for (JAXBElement<? extends TRootElement> elem : defns.getRootElement()) {
if (elem.getDeclaredType() == TMessage.class) {
TMessage message=(TMessage)elem.getValue();
if (message.getItemRef() == null) {
logger.severe("No item definition set for message '"+message.getName()+"'");
continue;
}
TItemDefinition itemdefn=getItemDefinition(message.getItemRef().getLocalPart(), defns);
if (itemdefn == null) {
logger.severe("No item definition found for message '"+message.getName()+"'");
continue;
}
if (itemdefn.getStructureRef() == null) {
logger.severe("Item definition has no structure ref for message '"+message.getName()+"'");
continue;
}
// Store namespace - and if prefix is not set, use a default, but ensure
// only one default prefix is used per namespace uri
String prefix=itemdefn.getStructureRef().getPrefix();
if (prefix == null || prefix.trim().length() == 0) {
if (!defaultprefix.contains(itemdefn.getStructureRef().getNamespaceURI())) {
prefix = "defns"+nsprefix.size();
defaultprefix.add(itemdefn.getStructureRef().getNamespaceURI());
} else {
prefix = null;
}
}
if (prefix != null) {
nsprefix.put(prefix, itemdefn.getStructureRef().getNamespaceURI());
}
// Create the type import
TypeImport ti=new TypeImport();
ti.setName(message.getName());
DataType dt=new DataType();
dt.setDetails(itemdefn.getStructureRef().toString());
ti.setDataType(dt);
TypeImportList tilist=new TypeImportList();
tilist.setFormat(TypeSystem.XSD);
String location=null;
for (TImport imp : defns.getImport()) {
if (imp.getNamespace().equals(itemdefn.getStructureRef().getNamespaceURI())) {
if (imp.getLocation() != null) {
location = imp.getLocation();
}
break;
}
}
tilist.setLocation(location);
if (location != null && prefix != null) {
nslocation.put(prefix, location);
}
tilist.getTypeImports().add(ti);
pm.getImports().add(tilist);
}
}
for (String prefix : nsprefix.keySet()) {
String ns=nsprefix.get(prefix);
String location=nslocation.get(prefix);
Annotation pann=new Annotation(AnnotationDefinitions.TYPE);
pann.getProperties().put(AnnotationDefinitions.PREFIX_PROPERTY,
prefix);
pann.getProperties().put(AnnotationDefinitions.NAMESPACE_PROPERTY,
ns);
if (location != null) {
pann.getProperties().put(AnnotationDefinitions.LOCATION_PROPERTY,
location);
}
pm.getProtocol().getAnnotations().add(pann);
}
}
protected TItemDefinition getItemDefinition(String id, org.savara.bpmn2.model.TDefinitions defns) {
for (JAXBElement<? extends TRootElement> elem : defns.getRootElement()) {
if (elem.getDeclaredType() == TItemDefinition.class) {
TItemDefinition itemdefn=(TItemDefinition)elem.getValue();
if (itemdefn.getId().equals(id)) {
return(itemdefn);
}
}
}
return(null);
}
}