/*
* 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.model.change;
import org.savara.contract.model.Contract;
import org.savara.common.logging.FeedbackHandler;
import org.savara.protocol.util.JournalProxy;
import org.scribble.protocol.model.*;
import org.scribble.protocol.util.ProtocolModelUtil;
import org.scribble.protocol.util.RunUtil;
/**
* Model change utilities.
*/
public class ModelChangeUtils {
/**
* This method adds any contracts associated with roles defined in the
* supplied conversation.
*
* @param context The context
* @param conv The conversation
* @param root Whether this is the root conversation
*/
@SuppressWarnings("unchecked")
//public static void addContracts(ModelChangeContext context, Protocol conv, boolean root) {
public static void addContract(ModelChangeContext context, Role role, Contract contract) {
java.util.Map<String,Contract> contracts=(java.util.Map<String,Contract>)
context.getProperties().get(Contract.class.getName());
if (contracts == null) {
contracts = new java.util.HashMap<String, Contract>();
context.getProperties().put(Contract.class.getName(), contracts);
}
if (role != null && contract != null) {
addRoleContract(role, contract, contracts);
}
}
// NOTE: Return all the roles defined in the scope of this conversation
// Would be better to incrementally add contracts for roles, as defined
// in their own scope, but need to refactor how blocks are dealt with
// first - which is different in some cases, so not straightforward.
protected static java.util.List<Role> getRoles(final Protocol conv) {
final java.util.List<Role> roles=new java.util.Vector<Role>();
conv.visit(new AbstractModelObjectVisitor() {
public boolean process(ModelObject obj) {
boolean ret=true;
if (obj instanceof Introduces) {
roles.addAll(((Introduces)obj).getIntroducedRoles());
} else if (obj instanceof Protocol &&
obj != conv) {
ret = false;
}
return(ret);
}
});
return(roles);
}
/**
* This method initializes the contract associated with the supplied role.
*
* @param role The role
* @param contract The contract
* @param contracts The map of roles to contracts
*/
protected static void addRoleContract(Role role, Contract contract, java.util.Map<String,Contract> contracts) {
if (role != null && contract != null) {
contracts.put(role.getName(), contract);
}
}
/**
* This method removes the contract associated with the supplied role.
*
* @param role The role
* @param contracts The map of roles to contracts
*/
protected static void removeRoleContract(Role role, java.util.Map<String,Contract> contracts) {
if (role != null) {
contracts.remove(role.getName());
}
}
/**
* This method removes any contracts associated with roles defined in the
* supplied conversation.
*
* @param context The context
* @param conv The conversation
* @param root Whether this is the root conversation
*/
@SuppressWarnings("unchecked")
public static void removeContracts(ModelChangeContext context, Protocol conv, boolean root) {
java.util.Map<String,Contract> contracts=(java.util.Map<String,Contract>)
context.getProperties().get(Contract.class.getName());
if (contracts != null) {
if (conv.getLocatedRole() != null && root) {
removeRoleContract(conv.getLocatedRole(), contracts);
}
// Get list of roles
java.util.List<Role> roles=getRoles(conv);
for (Role r : roles) {
removeRoleContract(r, contracts);
}
}
}
/**
* This method returns the contract associated with the supplied role.
*
* @param contezt The context
* @param roleName The role name
* @return The contract, or null if not found
*/
@SuppressWarnings("unchecked")
public static Contract getContract(ModelChangeContext context, Role role) {
Contract ret=null;
if (context.getProperties().containsKey(Contract.class.getName())) {
java.util.Map<String,Contract> contracts=
(java.util.Map<String,Contract>)
context.getProperties().get(Contract.class.getName());
ret = contracts.get(role.getName());
/*
if (ret == null) {
ret = (Contract)role.getProperties().get(Contract.class.getName());
}
*/
}
return(ret);
}
/**
* This method updates the role mapping based on the supplied list of
* declaration bindings.
*
* @param context The context
* @param run The run construct
*/
@SuppressWarnings("unchecked")
public static void pushRoleContractMapping(ModelChangeContext context,
Run run, FeedbackHandler journal) {
if (context.getProperties().containsKey(Contract.class.getName())) {
java.util.Map<String,Contract> contracts=
(java.util.Map<String,Contract>)
context.getProperties().get(Contract.class.getName());
// Store protocol against mapped role
//Protocol defn=run.getProtocol();
Protocol defn=RunUtil.getInnerProtocol(run.getEnclosingProtocol(),
run.getProtocolReference());
if (run.getEnclosingProtocol().getLocatedRole() != null &&
defn != null && defn.getLocatedRole() != null) {
Contract c=contracts.remove(run.getEnclosingProtocol().getLocatedRole().getName());
if (c != null) {
contracts.put(defn.getLocatedRole().getName(), c);
}
}
if (defn == null) {
// Check if protocol import defined for protocol
ProtocolImport pi=ProtocolModelUtil.getProtocolImport(run.getModel(),
run.getProtocolReference());
if (pi == null) {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' not found within model or in import statements", run.getProperties());
} else {
ProtocolModel pm=context.getProtocolContext().getProtocolModel(pi,
new JournalProxy(journal));
if (pm != null) {
defn = pm.getProtocol();
} else {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' could not be loaded from location '"+pi.getLocation()+"'",
run.getProperties());
}
}
}
if (defn != null) {
if (defn.getParameterDefinitions().size() ==
run.getParameters().size()) {
for (int i=0; i < run.getParameters().size(); i++) {
Parameter p=run.getParameters().get(i);
ParameterDefinition pd=defn.getParameterDefinitions().get(i);
Contract c=contracts.remove(p.getName());
if (c != null) {
contracts.put(pd.getName(), c);
}
}
} else {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' is expecting a different number of parameters",
run.getProperties());
}
}
}
}
/**
* This method resets the role mapping based on the supplied list of
* declaration bindings.
*
* @param context The context
* @param run The run construct
*/
@SuppressWarnings("unchecked")
public static void popRoleContractMapping(ModelChangeContext context,
Run run, FeedbackHandler journal) {
if (context.getProperties().containsKey(Contract.class.getName())) {
java.util.Map<String,Contract> contracts=
(java.util.Map<String,Contract>)
context.getProperties().get(Contract.class.getName());
// Store protocol against mapped role
//Protocol defn=run.getProtocol();
Protocol defn=RunUtil.getInnerProtocol(run.getEnclosingProtocol(),
run.getProtocolReference());
if (run.getEnclosingProtocol().getLocatedRole() != null &&
defn != null && defn.getLocatedRole() != null) {
Contract c=contracts.remove(defn.getLocatedRole().getName());
if (c != null) {
contracts.put(run.getEnclosingProtocol().getLocatedRole().getName(), c);
}
}
if (defn == null) {
// Check if protocol import defined for protocol
ProtocolImport pi=ProtocolModelUtil.getProtocolImport(run.getModel(),
run.getProtocolReference());
if (pi == null) {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' not found within model or in import statements", run.getProperties());
} else {
ProtocolModel pm=context.getProtocolContext().getProtocolModel(pi,
new JournalProxy(journal));
if (pm != null) {
defn = pm.getProtocol();
} else {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' could not be loaded from location '"+pi.getLocation()+"'",
run.getProperties());
}
}
}
if (defn != null) {
if (defn.getParameterDefinitions().size() ==
run.getParameters().size()) {
for (int i=0; i < run.getParameters().size(); i++) {
Parameter p=run.getParameters().get(i);
ParameterDefinition pd=defn.getParameterDefinitions().get(i);
Contract c=contracts.remove(pd.getName());
if (c != null) {
contracts.put(p.getName(), c);
}
}
} else {
journal.error("Referenced protocol '"+run.getProtocolReference().getName()+
"' is expecting a different number of parameters",
run.getProperties());
}
}
}
}
}