/**
* <copyright>
* </copyright>
*
* $Id$
*/
package org.eclipse.etrice.generator.etricegen.impl;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import org.eclipse.emf.common.notify.NotificationChain;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import org.eclipse.emf.ecore.util.EObjectContainmentEList;
import org.eclipse.emf.ecore.util.EObjectResolvingEList;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.DataClass;
import org.eclipse.etrice.core.room.ProtocolClass;
import org.eclipse.etrice.core.room.RoomClass;
import org.eclipse.etrice.core.room.RoomModel;
import org.eclipse.etrice.generator.etricegen.ETriceGenPackage;
import org.eclipse.etrice.core.room.ActorRef;
import org.eclipse.etrice.core.room.Attribute;
import org.eclipse.etrice.core.room.SubSystemClass;
import org.eclipse.etrice.core.room.FreeTypedID;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.Message;
import org.eclipse.etrice.core.room.Operation;
import org.eclipse.etrice.core.room.ServiceImplementation;
import org.eclipse.etrice.core.room.TypedID;
import org.eclipse.etrice.generator.etricegen.ActorInstance;
import org.eclipse.etrice.generator.etricegen.ExpandedActorClass;
import org.eclipse.etrice.generator.etricegen.Root;
import org.eclipse.etrice.generator.etricegen.SubSystemInstance;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Root</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getSubSystems <em>Sub Systems</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getModels <em>Models</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getXpActorClasses <em>Xp Actor Classes</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getUsedDataClasses <em>Used Data Classes</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getUsedProtocolClasses <em>Used Protocol Classes</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getUsedActorClasses <em>Used Actor Classes</em>}</li>
* <li>{@link org.eclipse.etrice.generator.etricegen.impl.RootImpl#getUsedRoomModels <em>Used Room Models</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class RootImpl extends EObjectImpl implements Root {
/**
* The cached value of the '{@link #getSubSystems() <em>Sub Systems</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getSubSystems()
* @generated
* @ordered
*/
protected EList<SubSystemInstance> subSystems;
private class RoomClassComparator implements Comparator<RoomClass> {
@Override
public int compare(RoomClass o1, RoomClass o2) {
return o1.getName().compareTo(o2.getName());
}
}
private class RoomModelComparator implements Comparator<RoomModel> {
@Override
public int compare(RoomModel o1, RoomModel o2) {
return o1.getName().compareTo(o2.getName());
}
}
/**
* The cached value of the '{@link #getModels() <em>Models</em>}' reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getModels()
* @generated
* @ordered
*/
protected EList<RoomModel> models;
/**
* The cached value of the '{@link #getXpActorClasses() <em>Xp Actor Classes</em>}' containment reference list.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getXpActorClasses()
* @generated
* @ordered
*/
protected EList<ExpandedActorClass> xpActorClasses;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected RootImpl() {
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass() {
return ETriceGenPackage.Literals.ROOT;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList<SubSystemInstance> getSubSystems() {
if (subSystems == null) {
subSystems = new EObjectContainmentEList<SubSystemInstance>(SubSystemInstance.class, this, ETriceGenPackage.ROOT__SUB_SYSTEMS);
}
return subSystems;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList<RoomModel> getModels() {
if (models == null) {
models = new EObjectResolvingEList<RoomModel>(RoomModel.class, this, ETriceGenPackage.ROOT__MODELS);
}
return models;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public EList<ExpandedActorClass> getXpActorClasses() {
if (xpActorClasses == null) {
xpActorClasses = new EObjectContainmentEList<ExpandedActorClass>(ExpandedActorClass.class, this, ETriceGenPackage.ROOT__XP_ACTOR_CLASSES);
}
return xpActorClasses;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<DataClass> getUsedDataClasses() {
if (usedDataClasses==null) {
computeUsedClasses();
}
return usedDataClasses;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<ProtocolClass> getUsedProtocolClasses() {
if (usedProtocolClasses==null) {
computeUsedClasses();
}
return usedProtocolClasses;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<ActorClass> getUsedActorClasses() {
if (usedActorClasses==null) {
computeUsedClasses();
}
return usedActorClasses;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<RoomModel> getUsedRoomModels() {
if (usedRoomModels==null) {
computeUsedClasses();
}
return usedRoomModels;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<RoomModel> getReferencedModels(RoomClass cls) {
if (cls instanceof ExpandedActorClass)
cls = ((ExpandedActorClass)cls).getActorClass();
HashSet<DataClass> dataClasses = new HashSet<DataClass>();
HashSet<ProtocolClass> protocolClasses = new HashSet<ProtocolClass>();
HashSet<ActorClass> actorClasses = new HashSet<ActorClass>();
HashSet<RoomModel> models = new HashSet<RoomModel>();
if (cls instanceof DataClass) {
dataClasses.add((DataClass) cls);
}
else if (cls instanceof ProtocolClass) {
protocolClasses.add((ProtocolClass) cls);
}
else if (cls instanceof ActorClass) {
actorClasses.add((ActorClass) cls);
}
else if (cls instanceof SubSystemClass) {
SubSystemClass cc = (SubSystemClass) cls;
for (ActorRef ar : cc.getActorRefs()) {
actorClasses.add(ar.getType());
}
}
getReferencedClassesAndModels(dataClasses, protocolClasses,
actorClasses, models);
// remove own model
models.remove(cls.eContainer());
BasicEList<RoomModel> result = new BasicEList<RoomModel>(models);
Comparator<RoomModel> comp = new RoomModelComparator();
Collections.sort(result, comp);
return result;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public EList<ProtocolClass> getReferencedProtocols(ActorClass cls) {
if (cls instanceof ExpandedActorClass)
cls = ((ExpandedActorClass)cls).getActorClass();
HashSet<DataClass> dataClasses = new HashSet<DataClass>();
HashSet<ProtocolClass> protocolClasses = new HashSet<ProtocolClass>();
HashSet<ActorClass> actorClasses = new HashSet<ActorClass>();
HashSet<RoomModel> models = new HashSet<RoomModel>();
actorClasses.add(cls);
getReferencedClassesAndModels(dataClasses, protocolClasses,
actorClasses, models);
BasicEList<ProtocolClass> result = new BasicEList<ProtocolClass>(protocolClasses);
Comparator<RoomClass> comp = new RoomClassComparator();
Collections.sort(result, comp);
return result;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) {
switch (featureID) {
case ETriceGenPackage.ROOT__SUB_SYSTEMS:
return ((InternalEList<?>)getSubSystems()).basicRemove(otherEnd, msgs);
case ETriceGenPackage.ROOT__XP_ACTOR_CLASSES:
return ((InternalEList<?>)getXpActorClasses()).basicRemove(otherEnd, msgs);
}
return super.eInverseRemove(otherEnd, featureID, msgs);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case ETriceGenPackage.ROOT__SUB_SYSTEMS:
return getSubSystems();
case ETriceGenPackage.ROOT__MODELS:
return getModels();
case ETriceGenPackage.ROOT__XP_ACTOR_CLASSES:
return getXpActorClasses();
case ETriceGenPackage.ROOT__USED_DATA_CLASSES:
return getUsedDataClasses();
case ETriceGenPackage.ROOT__USED_PROTOCOL_CLASSES:
return getUsedProtocolClasses();
case ETriceGenPackage.ROOT__USED_ACTOR_CLASSES:
return getUsedActorClasses();
case ETriceGenPackage.ROOT__USED_ROOM_MODELS:
return getUsedRoomModels();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@SuppressWarnings("unchecked")
@Override
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case ETriceGenPackage.ROOT__SUB_SYSTEMS:
getSubSystems().clear();
getSubSystems().addAll((Collection<? extends SubSystemInstance>)newValue);
return;
case ETriceGenPackage.ROOT__MODELS:
getModels().clear();
getModels().addAll((Collection<? extends RoomModel>)newValue);
return;
case ETriceGenPackage.ROOT__XP_ACTOR_CLASSES:
getXpActorClasses().clear();
getXpActorClasses().addAll((Collection<? extends ExpandedActorClass>)newValue);
return;
case ETriceGenPackage.ROOT__USED_DATA_CLASSES:
getUsedDataClasses().clear();
getUsedDataClasses().addAll((Collection<? extends DataClass>)newValue);
return;
case ETriceGenPackage.ROOT__USED_PROTOCOL_CLASSES:
getUsedProtocolClasses().clear();
getUsedProtocolClasses().addAll((Collection<? extends ProtocolClass>)newValue);
return;
case ETriceGenPackage.ROOT__USED_ACTOR_CLASSES:
getUsedActorClasses().clear();
getUsedActorClasses().addAll((Collection<? extends ActorClass>)newValue);
return;
case ETriceGenPackage.ROOT__USED_ROOM_MODELS:
getUsedRoomModels().clear();
getUsedRoomModels().addAll((Collection<? extends RoomModel>)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID) {
switch (featureID) {
case ETriceGenPackage.ROOT__SUB_SYSTEMS:
getSubSystems().clear();
return;
case ETriceGenPackage.ROOT__MODELS:
getModels().clear();
return;
case ETriceGenPackage.ROOT__XP_ACTOR_CLASSES:
getXpActorClasses().clear();
return;
case ETriceGenPackage.ROOT__USED_DATA_CLASSES:
getUsedDataClasses().clear();
return;
case ETriceGenPackage.ROOT__USED_PROTOCOL_CLASSES:
getUsedProtocolClasses().clear();
return;
case ETriceGenPackage.ROOT__USED_ACTOR_CLASSES:
getUsedActorClasses().clear();
return;
case ETriceGenPackage.ROOT__USED_ROOM_MODELS:
getUsedRoomModels().clear();
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID) {
switch (featureID) {
case ETriceGenPackage.ROOT__SUB_SYSTEMS:
return subSystems != null && !subSystems.isEmpty();
case ETriceGenPackage.ROOT__MODELS:
return models != null && !models.isEmpty();
case ETriceGenPackage.ROOT__XP_ACTOR_CLASSES:
return xpActorClasses != null && !xpActorClasses.isEmpty();
case ETriceGenPackage.ROOT__USED_DATA_CLASSES:
return !getUsedDataClasses().isEmpty();
case ETriceGenPackage.ROOT__USED_PROTOCOL_CLASSES:
return !getUsedProtocolClasses().isEmpty();
case ETriceGenPackage.ROOT__USED_ACTOR_CLASSES:
return !getUsedActorClasses().isEmpty();
case ETriceGenPackage.ROOT__USED_ROOM_MODELS:
return !getUsedRoomModels().isEmpty();
}
return super.eIsSet(featureID);
}
private HashMap<String, DataClass> name2dc = new HashMap<String, DataClass>();
private BasicEList<DataClass> usedDataClasses = null;
private BasicEList<ProtocolClass> usedProtocolClasses = null;
private BasicEList<ActorClass> usedActorClasses = null;
private BasicEList<RoomModel> usedRoomModels = null;
private void computeUsedClasses() {
for (RoomModel mdl : getModels()) {
for (DataClass dc : mdl.getDataClasses()) {
name2dc.put(dc.getName(), dc);
}
}
// first we collect actor classes
HashSet<ActorClass> actorClasses = new HashSet<ActorClass>();
for (SubSystemInstance ci : getSubSystems()) {
TreeIterator<EObject> it = ci.eAllContents();
while (it.hasNext()) {
EObject obj = it.next();
if (obj instanceof ActorInstance) {
ActorClass ac = ((ActorInstance)obj).getActorClass();
actorClasses.add(ac);
}
}
}
HashSet<DataClass> dataClasses = new HashSet<DataClass>();
HashSet<ProtocolClass> protocolClasses = new HashSet<ProtocolClass>();
HashSet<RoomModel> models = new HashSet<RoomModel>();
getReferencedClassesAndModels(dataClasses, protocolClasses,
actorClasses, models);
usedDataClasses = new BasicEList<DataClass>(dataClasses);
usedProtocolClasses = new BasicEList<ProtocolClass>(protocolClasses);
usedActorClasses = new BasicEList<ActorClass>(actorClasses);
usedRoomModels = new BasicEList<RoomModel>(models);
}
private void getReferencedClassesAndModels(HashSet<DataClass> dataClasses,
HashSet<ProtocolClass> protocolClasses,
HashSet<ActorClass> actorClasses, HashSet<RoomModel> models) {
// add actor base classes
LinkedList<ActorClass> tmpAc = new LinkedList<ActorClass>(actorClasses);
for (ActorClass ac : tmpAc) {
while (ac.getBase()!=null) {
ac = ac.getBase();
actorClasses.add(ac);
}
}
// determine data and protocol classes used by actor classes
for (ActorClass ac : actorClasses) {
getInterfaceItemProtocolClasses(protocolClasses, ac.getIfPorts());
// ExtPorts are in the interface and thus already covered
getInterfaceItemProtocolClasses(protocolClasses, ac.getIntPorts());
getInterfaceItemProtocolClasses(protocolClasses, ac.getStrSAPs());
for (ServiceImplementation ispp : ac.getServiceImplementations()) {
protocolClasses.add(ispp.getSpp().getProtocol());
}
getInterfaceItemProtocolClasses(protocolClasses, ac.getIfSPPs());
getAttributeDataClasses(dataClasses, ac.getAttributes());
getOperationDataClasses(dataClasses, ac.getOperations());
}
// add protocol base classes
LinkedList<ProtocolClass> tmpPc = new LinkedList<ProtocolClass>(protocolClasses);
for (ProtocolClass pc : tmpPc) {
while (pc.getBase()!=null) {
pc = pc.getBase();
protocolClasses.add(pc);
}
}
// add data classes used by protocols
for (ProtocolClass pc : protocolClasses) {
for (Message m : pc.getIncomingMessages()) {
getTypedIdDataClasses(dataClasses, m.getArguments());
}
for (Message m : pc.getOutgoingMessages()) {
getTypedIdDataClasses(dataClasses, m.getArguments());
}
}
// add data class base classes and data class attribute and operation classes
boolean repeat = true;
do {
LinkedList<DataClass> tmpDc = new LinkedList<DataClass>(dataClasses);
for (DataClass dc : tmpDc) {
getAttributeDataClasses(dataClasses, dc.getAttributes());
getOperationDataClasses(dataClasses, dc.getOperations());
while (dc.getBase()!=null) {
dc = dc.getBase();
dataClasses.add(dc);
}
}
if (tmpDc.size()==dataClasses.size())
// nothing changed
repeat = false;
}
while (repeat);
// finally compute used models
for (DataClass dc : dataClasses) {
models.add((RoomModel) dc.eContainer());
}
for (ProtocolClass pc : protocolClasses) {
models.add((RoomModel) pc.eContainer());
}
for (ActorClass ac : actorClasses) {
models.add((RoomModel) ac.eContainer());
}
}
private void getInterfaceItemProtocolClasses(
HashSet<ProtocolClass> protocolClasses, EList<? extends InterfaceItem> items) {
for (InterfaceItem ii : items) {
protocolClasses.add(ii.getProtocol());
}
}
private void getOperationDataClasses(HashSet<DataClass> dataClasses,
EList<Operation> operations) {
for (Operation op : operations) {
if (op.getReturntype()!=null) {
DataClass dc = name2dc.get(op.getReturntype());
if (dc!=null)
dataClasses.add(dc);
}
getFreeTypedIdDataClasses(dataClasses, op.getArguments());
}
}
private void getTypedIdDataClasses(HashSet<DataClass> dataClasses,
EList<TypedID> arguments) {
for (TypedID tid : arguments) {
if (tid.getType().getType()!=null)
dataClasses.add(tid.getType().getType());
}
}
private void getFreeTypedIdDataClasses(HashSet<DataClass> dataClasses,
EList<FreeTypedID> arguments) {
for (FreeTypedID tid : arguments) {
DataClass dc = name2dc.get(tid.getType());
if (dc!=null)
dataClasses.add(dc);
}
}
private void getAttributeDataClasses(HashSet<DataClass> dataClasses,
EList<Attribute> attributes) {
for (Attribute attr : attributes) {
if (attr.getType().getType()!=null)
dataClasses.add(attr.getType().getType());
}
}
} //RootImpl