blob: 11fcad7e782662858a5ba2042a8966cdc1114e92 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* CONTRIBUTORS:
* Thomas Schuetz and Henrik Rentz-Reichert (initial contribution)
*
*******************************************************************************/
package org.eclipse.etrice.core.scoping;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.etrice.core.fsm.fSM.InSemanticsRule;
import org.eclipse.etrice.core.fsm.fSM.MessageFromIf;
import org.eclipse.etrice.core.fsm.fSM.OutSemanticsRule;
import org.eclipse.etrice.core.fsm.fSM.SemanticsRule;
import org.eclipse.etrice.core.fsm.scoping.FSMScopeProvider;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerClass;
import org.eclipse.etrice.core.room.ActorRef;
import org.eclipse.etrice.core.room.BindingEndPoint;
import org.eclipse.etrice.core.room.CompoundProtocolClass;
import org.eclipse.etrice.core.room.ExternalPort;
import org.eclipse.etrice.core.room.InMessageHandler;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.LogicalSystem;
import org.eclipse.etrice.core.room.Message;
import org.eclipse.etrice.core.room.MessageHandler;
import org.eclipse.etrice.core.room.OutMessageHandler;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.PortClass;
import org.eclipse.etrice.core.room.PortOperation;
import org.eclipse.etrice.core.room.ProtocolClass;
import org.eclipse.etrice.core.room.RefSAPoint;
import org.eclipse.etrice.core.room.RelaySAPoint;
import org.eclipse.etrice.core.room.SAP;
import org.eclipse.etrice.core.room.SPP;
import org.eclipse.etrice.core.room.SPPoint;
import org.eclipse.etrice.core.room.StructureClass;
import org.eclipse.etrice.core.room.SubProtocol;
import org.eclipse.etrice.core.room.SubSystemClass;
import org.eclipse.etrice.core.room.SubSystemRef;
import org.eclipse.etrice.core.room.util.RoomHelpers;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.SimpleScope;
import com.google.inject.Inject;
/**
* This class contains custom scoping description.
*
* see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping
* on how and when to use it
*
*/
public class RoomScopeProvider extends FSMScopeProvider {
@Inject
private RoomHelpers roomHelpers;
/**
* first container of type {@link ActorClass}
* @param obj
* @return ActorClass container
*/
private ActorClass getActorClass(EObject obj) {
EObject ctx = obj.eContainer();
while (!(ctx instanceof ActorClass) && ctx.eContainer()!=null)
ctx = ctx.eContainer();
if (ctx instanceof ActorClass)
return (ActorClass) ctx;
return null;
}
/**
* first container of type {@link ActorClass}
* @param obj
* @return ActorClass container
*/
private ActorContainerClass getActorContainerClass(EObject obj) {
EObject ctx = obj.eContainer();
while (!(ctx instanceof ActorContainerClass) && ctx.eContainer()!=null)
ctx = ctx.eContainer();
if (ctx instanceof ActorContainerClass)
return (ActorContainerClass) ctx;
return null;
}
/**
* first container of type {@link StructureClass}
* @param obj
* @return StructureClass container
*/
private StructureClass getStructureClass(EObject obj) {
EObject ctx = obj.eContainer();
while (!(ctx instanceof StructureClass) && ctx.eContainer()!=null)
ctx = ctx.eContainer();
if (ctx instanceof StructureClass)
return (StructureClass) ctx;
return null;
}
/**
* return a list of base classes of an {@link ActorClass}, parent classes first.
* The list includes the class itself
* @param ac
* @return
*/
private LinkedList<ActorClass> getBaseClasses(ActorClass ac) {
LinkedList<ActorClass> classes = new LinkedList<ActorClass>();
if (ac!=null) {
classes.addFirst(ac);
while (ac.getActorBase()!=null) {
if (ac==ac.getBase())
// avoid endless loop - circularity in class hierarchy detected elsewhere
break;
ac = ac.getActorBase();
classes.addFirst(ac);
}
}
return classes;
}
/**
* return a list of base classes of an {@link ProtocolClass}, parent classes first.
* The list includes the class itself
* @param pc
* @return
*/
private LinkedList<ProtocolClass> getBaseClasses(ProtocolClass pc) {
LinkedList<ProtocolClass> classes = new LinkedList<ProtocolClass>();
classes.addFirst(pc);
while (pc.getBase()!=null) {
pc = pc.getBase();
classes.addFirst(pc);
}
return classes;
}
/**
* returns a flat list of Message scopes for a {@link MessageFromIf}
* @param mfi - the message from interface
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_MessageFromIf_message(MessageFromIf mfi, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
InterfaceItem item = (InterfaceItem) mfi.getFrom();
if (item!=null) {
ProtocolClass protocol = null;
boolean conjugated = false;
if (item instanceof Port && ((Port)item).getProtocol() instanceof ProtocolClass) {
protocol = (ProtocolClass) ((Port)item).getProtocol();
conjugated = ((Port)item).isConjugated();
}
else if (item instanceof SAP) {
protocol = ((SAP)item).getProtocol();
conjugated = true;
}
else if (item instanceof SPP) {
protocol = ((SPP)item).getProtocol();
conjugated = false;
}
if (protocol!=null)
for (Message msg : conjugated?roomHelpers.getAllMessages(protocol,false):roomHelpers.getAllMessages(protocol,true)) {
scopes.add(EObjectDescription.create(msg.getName(), msg));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of Port scopes for a {@link MessageFromIf}
* @param mfi - the message from interface
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_MessageFromIf_port(MessageFromIf mfi, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorClass ac = getActorClass(mfi);
for (Port p : ac.getInternalPorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
for (ExternalPort p : ac.getExternalPorts()) {
scopes.add(EObjectDescription.create(p.getInterfacePort().getName(), p.getInterfacePort()));
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of InterfaceItem scopes for a {@link MessageFromIf}
* @param mfi - the message from interface
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_MessageFromIf_from(MessageFromIf mfi, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorClass ac = getActorClass(mfi);
List<InterfaceItem> items = roomHelpers.getAllInterfaceItems(ac);
for (InterfaceItem item : items) {
scopes.add(EObjectDescription.create(item.getName(), item));
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of ActorRef scopes for a {@link BindingEndPoint}
* @param ep - the endpoint
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_BindingEndPoint_actorRef(BindingEndPoint ep, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
StructureClass sc = getStructureClass(ep);
if (sc instanceof ActorClass) {
LinkedList<ActorClass> classes = getBaseClasses((ActorClass)sc);
for (ActorClass a : classes) {
for (ActorRef ar : a.getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
}
else if (sc instanceof SubSystemClass){
for (ActorRef ar : ((SubSystemClass) sc).getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
else {
LogicalSystem ls = (LogicalSystem) sc;
for (SubSystemRef ssr : ls.getSubSystems()) {
scopes.add(EObjectDescription.create(ssr.getName(), ssr));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of Port scopes for a {@link BindingEndPoint}
* @param ep - the endpoint
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_BindingEndPoint_port(BindingEndPoint ep, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
StructureClass sc = getStructureClass(ep);
if (ep.getActorRef() == null){
if (sc instanceof ActorClass) {
ActorClass ac = (ActorClass) sc;
// for all super classes (including this class)
LinkedList<ActorClass> classes = getBaseClasses(ac);
for (ActorClass a : classes) {
// collect internal and relay ports, i.e.
// structure ports not in interface (internal)
for (Port p : a.getInternalPorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
// interface ports not in structure (relay)
for (Port p : a.getRelayPorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
}
}
else if (sc instanceof SubSystemClass) {
SubSystemClass ssc = (SubSystemClass) sc;
for (Port p : ssc.getRelayPorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
}
}
else {
// all ports in the sub actor's interface
if (ep.getActorRef() instanceof ActorRef) {
ActorClass ac = ((ActorRef)ep.getActorRef()).getType();
LinkedList<ActorClass> classes = getBaseClasses(ac);
for (ActorClass a : classes) {
for (Port p : a.getInterfacePorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
}
}
else {
SubSystemClass ssc = ((SubSystemRef)ep.getActorRef()).getType();
for (Port p : ssc.getRelayPorts()) {
scopes.add(EObjectDescription.create(p.getName(), p));
}
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of SubProtocol scopes for a {@link BindingEndPoint}
* @param ep - the endpoint
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_BindingEndPoint_sub(BindingEndPoint ep, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
if (ep.getPort()!=null) {
if (ep.getPort().getProtocol() instanceof CompoundProtocolClass) {
CompoundProtocolClass pc = (CompoundProtocolClass) ep.getPort().getProtocol();
for (SubProtocol sub : pc.getSubProtocols()) {
scopes.add(EObjectDescription.create(sub.getName(), sub));
}
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of Message scopes for a {@link InSemanticsRule}
* @param sr - the semantics rule for incoming messages
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_SemanticsRule_msg(SemanticsRule sr, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ProtocolClass pc = roomHelpers.getProtocolClass(sr);
LinkedList<ProtocolClass> classes = getBaseClasses(pc);
for (ProtocolClass bpc : classes) {
if (sr instanceof InSemanticsRule)
for (Message m : bpc.getIncomingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
if (sr instanceof OutSemanticsRule)
for (Message m : bpc.getOutgoingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of ActorRef scopes for a {@link RefSAPoint}
* @param pt
* @param ref
* @return a list of scopes
*/
public IScope scope_RefSAPoint_ref(RefSAPoint pt, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorContainerClass acc = getActorContainerClass(pt);
if (acc instanceof ActorClass) {
LinkedList<ActorClass> classes = getBaseClasses((ActorClass) acc);
for (ActorClass a : classes) {
for (ActorRef ar : a.getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
}
else {
for (ActorRef ar : acc.getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of SPP scopes for a {@link RelaySAPoint}
* @param pt
* @param ref
* @return a list of scopes
*/
public IScope scope_RelaySAPoint_relay(RelaySAPoint pt, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorClass ac = getActorClass(pt);
LinkedList<ActorClass> classes = getBaseClasses(ac);
for (ActorClass a : classes) {
for (SPP spp : a.getServiceProvisionPoints()) {
scopes.add(EObjectDescription.create(spp.getName(), spp));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of ActorRef scopes for a {@link SPPoint}
* @param pt
* @param ref
* @return a list of scopes
*/
public IScope scope_SPPoint_actorRef(SPPoint pt, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorContainerClass acc = getActorContainerClass(pt);
if (acc instanceof ActorClass) {
LinkedList<ActorClass> classes = getBaseClasses((ActorClass)acc);
for (ActorClass a : classes) {
for (ActorRef ar : a.getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
}
else {
for (ActorRef ar : acc.getActorRefs()) {
scopes.add(EObjectDescription.create(ar.getName(), ar));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of SPP scopes for a {@link SPPoint}
* @param pt
* @param ref
* @return a list of scopes
*/
public IScope scope_SPPoint_service(SPPoint pt, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
if (pt.getRef()!=null) {
if (pt.getRef() instanceof ActorRef) {
ActorClass ac = ((ActorRef)pt.getRef()).getType();
LinkedList<ActorClass> classes = getBaseClasses(ac);
for (ActorClass a : classes) {
for (SPP spp : a.getServiceProvisionPoints()) {
scopes.add(EObjectDescription.create(spp.getName(), spp));
}
}
}
else if (pt.getRef() instanceof SubSystemRef) {
SubSystemClass ssc = ((SubSystemRef)pt.getRef()).getType();
for (SPP spp : ssc.getServiceProvisionPoints()) {
scopes.add(EObjectDescription.create(spp.getName(), spp));
}
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
public IScope scope_MessageHandler_msg(MessageHandler handler, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ProtocolClass pc = roomHelpers.getProtocolClass(handler);
if (pc!=null) {
if (handler instanceof InMessageHandler)
for (Message m : pc.getIncomingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
if (handler instanceof OutMessageHandler)
for (Message m : pc.getOutgoingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
public IScope scope_PortOperation_sendsMsg(PortOperation op, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
PortClass pcls = (PortClass) op.eContainer();
ProtocolClass pc = roomHelpers.getProtocolClass(op);
if (pc!=null) {
if (pcls==pc.getConjugated())
for (Message m : pc.getIncomingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
else
for (Message m : pc.getOutgoingMessages()) {
scopes.add(EObjectDescription.create(m.getName(), m));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/*
* we prefer loose scoping here and rely on validation for meaningful error messages
*
* returns a flat list of ActorClass scopes for a {@link ActorRef}
* @param ar - the actor reference
* @param ref - not used
* @return a list of scopes
*/
// public IScope scope_ActorRef_type(ActorRef ar, EReference ref) {
// ActorClass ac = getActorClass(ar);
// IScope scope = delegateGetScope(ar, ref);
// return new FilteringScope(scope, new ActorRefFilter(ac));
// }
/**
* returns a flat list of Port scopes for a {@link ExternalPort}
* @param ep - the external port
* @param ref - not used
* @return a list of scopes
*/
public IScope scope_ExternalPort_ifport(ExternalPort ep, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
ActorClass ac = getActorClass(ep);
for (Port ip : ac.getInterfacePorts()) {
scopes.add(EObjectDescription.create(ip.getName(), ip));
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}
/**
* returns a flat list of Port scopes for a {@link ExternalPort}
* @param ar - the external port
* @param ref - not used
* @return a list of scopes
*/
// public IScope scope_ActorInstance_segments(ActorInstance ai, EReference ref) {
// final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
//
// if (ai.getSegments().isEmpty()) {
// // context is my ActorContainerClass
// ActorContainerClass acc = getActorContainerClass(ai);
// for (ActorRef ar : acc.getActorRefs()) {
// scopes.add(EObjectDescription.create(ar.getName(), ar));
// }
// }
// else {
// // context is actor class of last segment
// ActorClass ac = ai.getSegments().get(ai.getSegments().size()-1).getType();
// for (ActorRef ar : ac.getActorRefs()) {
// scopes.add(EObjectDescription.create(ar.getName(), ar));
// }
// }
//
// return new SimpleScope(IScope.NULLSCOPE, scopes);
// }
/*
public IScope scope_ChoicePointCaseRef_case(ChoicePointCaseRef cr, EReference ref) {
final List<IEObjectDescription> scopes = new ArrayList<IEObjectDescription>();
if (cr.getCp()!=null) {
for (ChoicePointCase cas : cr.getCp().getCases()) {
scopes.add(EObjectDescription.create(cas.getName(), cas));
}
}
return new SimpleScope(IScope.NULLSCOPE, scopes);
}*/
}