/**
* Copyright 2011-2012 Universite Joseph Fourier, LIG, ADELE team
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package fr.imag.adele.apam.impl;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.imag.adele.apam.ApamManagers;
import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.Composite;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.Link;
import fr.imag.adele.apam.Specification;
import fr.imag.adele.apam.apform.ApformInstance;
import fr.imag.adele.apam.declarations.ComponentKind;
import fr.imag.adele.apam.declarations.InstanceDeclaration;
import fr.imag.adele.apam.declarations.references.components.VersionedReference;
public class InstanceImpl extends ComponentImpl implements Instance {
/**
* This class represents the Apam root instance.
*
* This is an APAM concept without mapping at the execution platform level, we build an special
* apform object to represent it.
*
*/
private static class SystemRootInstance extends BaseApformComponent<Instance, InstanceDeclaration> implements ApformInstance {
public SystemRootInstance(Implementation rootImplementation, String name) {
super(new InstanceDeclaration(VersionedReference.any(rootImplementation.getImplDeclaration().getReference()),name));
}
@Override
public Object getServiceObject() {
throw new UnsupportedOperationException("method not available in root instance");
}
@Override
public boolean remLink(Component destInst, String depName) {
throw new UnsupportedOperationException("method not available in root instance");
}
@Override
public void setApamComponent(Component apamComponent) {
throw new UnsupportedOperationException("method not available in root instance");
}
@Override
public boolean setLink(Component destInst, String depName) {
throw new UnsupportedOperationException("method not available in root instance");
}
@Override
public void setProperty(String attr, String value) {
throw new UnsupportedOperationException("method not available in root instance");
}
}
private static Logger logger = LoggerFactory.getLogger(InstanceImpl.class);
private static final long serialVersionUID = 1L;
private Implementation myImpl;
private Composite myComposite;
/**
* Builds a new Apam instance to represent the specified platform instance
* in the Apam model.
*/
protected InstanceImpl(Composite composite, ApformInstance apformInst) throws InvalidConfiguration {
super(apformInst);
if (composite == null) {
throw new InvalidConfiguration("Null parent while creating instance");
}
Implementation implementation = CST.componentBroker.getImpl(apformInst.getDeclaration().getImplementation().getName());
if (implementation == null) {
throw new InvalidConfiguration("Null implementation while creating instance");
}
/*
* reference the implementation and the enclosing composite
*/
myImpl = implementation;
myComposite = composite;
}
/**
* This is an special constructor only used for the root instance of the system
*/
protected InstanceImpl(Implementation rootImplementation, String name) throws InvalidConfiguration {
super(new SystemRootInstance(rootImplementation, name));
/*
* NOTE the root instance is automatically registered in the Apam model in a ad-hoc way that allows
* bootstraping the system
*/
myImpl = rootImplementation;
((ImplementationImpl) rootImplementation).addInst(this);
put(CST.NAME,name);
/*
* The top level of the hierarchy is closed by a self-loop
*/
myComposite = (Composite) this;
}
@Override
public final ApformInstance getApformInst() {
return (ApformInstance) getApformComponent();
}
@Override
public Composite getAppliComposite() {
return myComposite.getAppliComposite();
}
@Override
public final Composite getComposite() {
return myComposite;
}
@Override
public Component getGroup() {
return myImpl;
}
@Override
public Implementation getImpl() {
return myImpl;
}
@Override
public ComponentKind getKind() {
return ComponentKind.INSTANCE;
}
@Override
public Set<Component> getMembers() {
return Collections.emptySet();
}
@Override
public Object getServiceObject() {
return getApformInst().getServiceObject();
}
@Override
public Specification getSpec() {
return myImpl.getSpec();
}
@Override
public boolean isSharable() {
// return (!hasInvWires() || isShared());
return (invlinks.isEmpty() || isShared());
}
@Override
public void register(Map<String, String> initialproperties) throws InvalidConfiguration {
/*
* Opposite references from implementation and enclosing composite
*/
((ImplementationImpl) getImpl()).addInst(this);
((CompositeImpl) getComposite()).addContainInst(this);
/*
* Terminates the initialization, and computes properties
*/
finishInitialize(initialproperties);
/*
* Bind to the underlying execution platform instance
*/
getApformInst().setApamComponent(this);
/*
* Add to broker
*/
((ComponentBrokerImpl) CST.componentBroker).add(this);
/*
* Notify managers
*/
ApamManagers.notifyAddedInApam(this);
}
/**
* Change the owner (enclosing composite) of this instance.
*
*/
public void setOwner(Composite owner) {
CompositeImpl previousOwner = (CompositeImpl) getComposite();
if (owner == previousOwner) {
return;
}
previousOwner.removeInst(this);
this.myComposite = owner;
((CompositeImpl) owner).addContainInst(this);
/*
* Compute again the properties and relation definition,
* and removes the properties and links now invalid
*/
((ComponentImpl)this).finishInitialize(getAllPropertiesString()) ;
}
/**
* remove from ASM It deletes the wires, which deletes the isolated used
* instances, and transitively. It deleted the invWires, which removes the
* associated real relation :
*/
@Override
public void unregister() {
logger.debug("unregister instance " + this);
/*
* Remove from broker, and from its composites. After that, it is
* invisible.
*/
((ImplementationImpl) getImpl()).removeInst(this);
((CompositeImpl) getComposite()).removeInst(this);
/*
* Remove all incoming and outgoing wires (this deletes the associated
* references at the execution platform level)
*/
for (Link wire : invlinks) {
((LinkImpl) wire).remove();
}
/*
* Unbind from the underlying execution platform instance
*/
try {
getApformInst().setApamComponent(null);
} catch (InvalidConfiguration ignored) {
logger.error("error unregistering instance "+ this, ignored.getCause());
}
/*
* Do no remove the outgoing wires, in case a Thread is still here. If
* so, the relation will be resolved again ! Should only remove the
* invWire ! But weird: wired only in a direction ...
*/
for (Link wire : links) {
((LinkImpl) wire).remove();
}
}
// /**
// * returns the wires leading to that instance
// *
// */
// public Set<Link> getInvWires() {
// Set<Link> wires = new HashSet<Link> () ;
// for (Link link : invlinks) {
// if (link.isWire())
// wires.add(link) ;
// }
// return wires ;
// }
//
// // returns the wires leading to that instance
// public Set<Link> getWires() {
// Set<Link> wires = new HashSet<Link> () ;
// for (Link link : links) {
// if (link.isWire())
// wires.add(link) ;
// }
// return wires ;
// }
//
//
// /**
// * returns the wires from that instance
// *
// */
// public boolean hasWires() {
// for (Link link : links) {
// if (link.isWire())
// return true ;
// }
// return false ;
// }
//
// public boolean hasInvWires() {
// for (Link link : invlinks) {
// if (link.isWire())
// return true ;
// }
// return false ;
// }
}