/* * JBoss, Home of Professional Open Source * Copyright 2008, 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.protocol.util; import java.util.logging.Logger; import org.savara.common.model.annotation.Annotation; import org.savara.common.model.annotation.AnnotationDefinitions; import org.scribble.protocol.model.Activity; import org.scribble.protocol.model.Block; import org.scribble.protocol.model.DefaultVisitor; import org.scribble.protocol.model.Introduces; import org.scribble.protocol.model.ModelObject; import org.scribble.protocol.model.ModelProperties; import org.scribble.protocol.model.Parameter; import org.scribble.protocol.model.ParameterDefinition; import org.scribble.protocol.model.Protocol; import org.scribble.protocol.model.ProtocolModel; import org.scribble.protocol.model.Role; import org.scribble.protocol.model.Run; import org.scribble.protocol.util.RoleUtil; import org.scribble.protocol.util.RunUtil; /** * This class defines a set of protocol related utility functions. */ public final class ProtocolUtils { private static final Logger LOG=Logger.getLogger(ProtocolUtils.class.getName()); /** * This method calculates the start and end position of a supplied DOM element, within * the supplied text contents, and sets the values on the supplied ModelObject. * * @param obj The ModelObject to be initialized * @param contents The text contents * @param elem The DOM element to be located in the text */ public static void setStartAndEndPosition(ModelObject obj, String contents, org.w3c.dom.Element elem) { if (contents != null) { org.w3c.dom.NodeList nl=elem.getOwnerDocument().getElementsByTagName(elem.getNodeName()); int elempos=-1; for (int i=0; elempos == -1 && i < nl.getLength(); i++) { if (nl.item(i) == elem) { elempos = i; } } if (elempos != -1) { int startpos=-1; for (int i=0; i <= elempos; i++) { int val1=contents.indexOf("<"+elem.getNodeName()+">", startpos+1); int val2=contents.indexOf("<"+elem.getNodeName()+" ", startpos+1); if (val1 == -1 && val2 != -1) { startpos = val2; } else if (val1 != -1 && val2 == -1) { startpos = val1; } else if (val1 == -1 && val2 == -1) { // TODO: Error condition break; } else if (val1 > val2) { startpos = val2; } else { startpos = val1; } } if (startpos != -1) { //obj.getSource().setStartPosition(startpos); obj.getProperties().put(ModelProperties.START_LOCATION, startpos); // Check if single node int p1=contents.indexOf('>', startpos); if (p1 != -1 && contents.charAt(p1-1) == '/') { //obj.getSource().setEndPosition(p1); obj.getProperties().put(ModelProperties.END_LOCATION, p1); } else { org.w3c.dom.NodeList enl=elem.getElementsByTagName(elem.getNodeName()); int endpos=startpos; String nodetxt="</"+elem.getNodeName()+">"; for (int i=0; endpos != -1 && i <= enl.getLength(); i++) { endpos = contents.indexOf(nodetxt, endpos+1); } if (endpos != -1) { //obj.getSource().setEndPosition(endpos+nodetxt.length()-1); obj.getProperties().put(ModelProperties.END_LOCATION, endpos+nodetxt.length()-1); } } } } } } /** * This method finds a prefix associated with a supplied namespace using the * type annotation information associated with a protocol model. * * @param model The model * @param namespace The namespace * @return The prefix, or null if not found */ public static String getNamespacePrefix(ProtocolModel model, String namespace) { Annotation annotation=null; if (namespace == null || namespace.trim().length() == 0) { return(""); } if (model != null && model.getProtocol() != null) { annotation = AnnotationDefinitions.getAnnotationWithProperty( model.getProtocol().getAnnotations(), AnnotationDefinitions.TYPE, AnnotationDefinitions.NAMESPACE_PROPERTY, namespace); } return(annotation == null ? null : (String)annotation.getProperties().get(AnnotationDefinitions.PREFIX_PROPERTY)); } /** * This method ensures that all introduced roles are declared at * the most local block where their behaviour is defined. * * @param pm The protocol model */ public static void localizeRoleIntroductions(ProtocolModel pm) { final java.util.List<Role> unused=new java.util.ArrayList<Role>(); pm.visit(new DefaultVisitor() { public boolean start(Protocol p) { java.util.Iterator<Activity> iter=p.getBlock().getContents().iterator(); while (iter.hasNext()) { Activity act=iter.next(); if (act instanceof Introduces) { Introduces rl=(Introduces)act; for (int i=rl.getIntroducedRoles().size()-1; i >= 0; i--) { Role r=rl.getIntroducedRoles().get(i); Block b=RoleUtil.getEnclosingBlock(p, r, false); if (b == null) { // Report unused role unused.add(r); } else if (b != p.getBlock()) { Introduces innerrl=null; if (b.size() > 0 && b.get(0) instanceof Introduces && ((Introduces)b.get(0)).getIntroducer().equals(rl.getIntroducer())) { innerrl = (Introduces)b.get(0); } else { innerrl = new Introduces(); innerrl.setIntroducer(rl.getIntroducer()); b.getContents().add(0, innerrl); } rl.getIntroducedRoles().remove(r); innerrl.getIntroducedRoles().add(r); } } if (rl.getIntroducedRoles().size() == 0) { iter.remove(); } } else { break; } } return (true); } }); for (Role role : unused) { if (role.getParent() instanceof Introduces) { // Locate introduces Introduces introduces=(Introduces)role.getParent(); Protocol protocol=introduces.getEnclosingProtocol(); locateRoleIntroductionWithinRun(protocol, role, introduces.getIntroducer()); introduces.getIntroducedRoles().remove(role); if (introduces.getIntroducedRoles().size() == 0) { ((Block)introduces.getParent()).remove(introduces); } } } } protected static void locateRoleIntroductionWithinRun(Protocol protocol, final Role role, final Role introducer) { // Find run constructs that use the role protocol.visit(new DefaultVisitor() { public void accept(Run elem) { Parameter p=elem.getParameter(role.getName()); if (p != null) { // Remove role parameter elem.getParameters().remove(p); Protocol target=RunUtil.getInnerProtocol(elem.getEnclosingProtocol(), elem.getProtocolReference()); if (target == null) { // Error LOG.severe("Failed to find inner protocol '" +elem.getProtocolReference()+"'"); } else { // Remove role as parameter ParameterDefinition pd=target.getParameterDefinition(role.getName()); if (pd != null) { target.getParameterDefinitions().remove(pd); } else { LOG.severe("Failed to find parameter definition for role '" +role.getName()+"'"); } // Find enclosing block in target protocol Block b=RoleUtil.getEnclosingBlock(target, role, false); if (b == null) { // Find run constructs locateRoleIntroductionWithinRun(target, role, introducer); // Check if should add to existing Introduces } else if (b.size() > 0 && b.get(0) instanceof Introduces && ((Introduces)b.get(0)).getIntroducer().equals(introducer)) { ((Introduces)b.get(0)).getIntroducedRoles().add(new Role(role)); // Create new Introduces } else { Introduces intro=new Introduces(); intro.setIntroducer(new Role(introducer)); intro.getIntroducedRoles().add(new Role(role)); b.getContents().add(0, intro); } } } } }); } }