/**
* 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.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import fr.imag.adele.apam.ApamManagers;
import fr.imag.adele.apam.ApamResolver;
import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.Composite;
import fr.imag.adele.apam.CompositeType;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.RelToResolve;
import fr.imag.adele.apam.RelationDefinition;
import fr.imag.adele.apam.RelationManager;
import fr.imag.adele.apam.Resolved;
import fr.imag.adele.apam.Specification;
import fr.imag.adele.apam.declarations.ComponentKind;
import fr.imag.adele.apam.declarations.CreationPolicy;
import fr.imag.adele.apam.declarations.ImplementationDeclaration;
import fr.imag.adele.apam.declarations.RelationPromotion;
import fr.imag.adele.apam.declarations.ResolvePolicy;
import fr.imag.adele.apam.declarations.references.components.ComponentReference;
import fr.imag.adele.apam.declarations.references.components.ImplementationReference;
import fr.imag.adele.apam.declarations.references.components.InstanceReference;
import fr.imag.adele.apam.declarations.references.components.SpecificationReference;
import fr.imag.adele.apam.declarations.references.resources.InterfaceReference;
import fr.imag.adele.apam.declarations.references.resources.MessageReference;
public class ApamResolverImpl implements ApamResolver {
private APAMImpl apam;
static Logger logger = LoggerFactory.getLogger(ApamResolverImpl.class);
/**
* The current state of the resolver. The resolver can be temporarily
* disabled, for instance for waiting for the installation of required
* managers;
*
*/
private boolean enabled = false;
/**
* A description of the condition that must be met to enable the resolver
* again.
*/
private String condition = "resolver startup";
/**
* If the resolver is disabled, the time at which it will be automatically
* enabled, even if the condition is not met. This is not an delay, but the
* actual future time.
*/
private long maxDisableTime = 0L;
public ApamResolverImpl(APAMImpl theApam) {
this.apam = theApam;
}
/**
* Impl is either unused or deployed (and therefore also unused). It becomes
* embedded in compoType. If unused, remove from unused list.
*
* @param compoType
* @param impl
*/
private static void deployedImpl(Component source, Component comp, boolean deployed) {
// We take care only of implementations
if (!(comp instanceof Implementation)) {
return;
}
Implementation impl = (Implementation) comp;
// it was not deployed
if (!deployed && impl.isUsed()) {
logger.info(" : selected " + impl);
return;
}
CompositeType compoType;
if (source instanceof Instance) {
compoType = ((Instance) source).getComposite().getCompType();
} else if (source instanceof Implementation) {
compoType = ((Implementation) source).getInCompositeType().iterator().next();
} else {
logger.error("Should not call deployedImpl on a source Specification " + source);
// TODO in which composite to put it. Still in root ?
return;
}
((CompositeTypeImpl) compoType).deploy(impl);
// it is deployed or was never used so far
if (impl.isUsed()) {
logger.info(" : logically deployed " + impl);
} else {// it was unused so far.
((ComponentImpl) impl).setFirstDeployed(compoType);
if (deployed) {
logger.info(" : deployed " + impl);
} else {
logger.info(" : was here, unused " + impl);
}
}
}
/**
* Verifies if the resolver is enabled. If it is disabled blocks the calling
* thread waiting for the enable condition.
*/
private synchronized void checkEnabled() {
while (!this.enabled) {
try {
/*
* Verify if the disable timeout has expired, in that case
* simply enable the resolver again.
*/
long currentTime = System.currentTimeMillis();
if (currentTime > maxDisableTime) {
logger.debug("APAM RESOLVER resuming resolution, condition did not happen: " + condition);
enable();
return;
}
logger.debug("APAM RESOLVER waiting for: " + condition);
wait(this.maxDisableTime - currentTime);
} catch (InterruptedException ignored) {
}
}
}
/**
* Disables the resolver until the specified condition is met. If the
* condition is not signaled before the specified timeout, the resolver will
* be automatically enabled.
*/
public synchronized void disable(String condition, long timeout) {
logger.debug("Resolver disabled waiting for "+condition);
this.enabled = false;
this.condition = condition;
this.maxDisableTime = System.currentTimeMillis() + timeout;
}
/**
* Enables the resolver after the condition is met
*/
public synchronized void enable() {
logger.debug("Resolver enabled");
this.enabled = true;
this.condition = null;
this.maxDisableTime = 0L;
this.notifyAll();
}
private Component findByName(Component client, ComponentReference<?> targetComponent, ComponentKind targetKind) {
if (client == null) {
client = CompositeImpl.getRootInstance();
// hummmm patch .... TODO
if (targetComponent.getName().equals(CST.ROOT_COMPOSITE_TYPE)) {
return CompositeTypeImpl.getRootCompositeType();
}
}
// CompositeType compoType = CompositeTypeImpl.getRootCompositeType();
RelationDefinition rel = new RelationDefinitionImpl(targetComponent, client.getKind(), targetKind, null, null);
Resolved<?> res = resolveLink(client, rel);
if (res == null) {
return null;
}
return res.singletonResolved;
}
@Override
public Component findComponentByName(Component client, String name) {
Component ret = findImplByName(client, name);
if (ret != null) {
return ret;
}
ret = findSpecByName(client, name);
if (ret != null) {
return ret;
}
return findInstByName(client, name);
}
@Override
public Implementation findImplByName(Component client, String implName) {
return (Implementation) findByName(client, new ImplementationReference<ImplementationDeclaration>(implName), ComponentKind.IMPLEMENTATION);
}
@Override
public Instance findInstByName(Component client, String instName) {
return (Instance) findByName(client, new InstanceReference(instName), ComponentKind.INSTANCE);
}
@Override
public Specification findSpecByName(Component client, String specName) {
return (Specification) findByName(client, new SpecificationReference(specName), ComponentKind.SPECIFICATION);
}
/**
* Get the subset of the links of a composite that can satisfy a promotion for the specified source and relation
* inside the composite.
*
* NOTE IMPORTANT this method may trigger resolution of the composite's relation
*/
@SuppressWarnings("unchecked")
private <T extends Component> Resolved<T> getPromotionCandidates(Instance source, RelToResolve relation, RelationDefinition compositeRelation) {
Set<Component> candidates = source.getComposite().getLinkDests(compositeRelation.getName());
/*
* It there is no candidates, force resolution of the composite's relation
*/
if (candidates.isEmpty()) {
resolveLink(source.getComposite(), compositeRelation);
candidates = source.getComposite().getLinkDests(compositeRelation.getName());
}
/*
* Select the candidates that match the relation constraints
*/
return (Resolved<T>) relation.getResolved(candidates,true);
}
/**
* Look if a promotion is explicitly declared for the specified client and relation, and returns the result
* of promoting the relation
*
*/
private <T extends Component> Resolved<T> checkExplicitPromotion(Instance client, RelToResolve relation) {
Resolved<T> promotionResult = null;
search:
for (RelationPromotion promotion : client.getComposite().getCompType().getCompoDeclaration().getPromotions()) {
/*
* check if the relation to resolve matches the identifier of the promoted relation
*/
if (!promotion.getContentRelation().getIdentifier().equals(relation.getName())) {
continue;
}
/*
* check if the source of the promoted relation matches the client (or one of its ancestor groups)
*/
String source = promotion.getContentRelation().getDeclaringComponent().getName();
Component matching = null;
Component ancestor = client;
while (matching == null && ancestor != null) {
if (ancestor.getName().equals(source)) {
matching = ancestor;
}
ancestor = ancestor.getGroup();
}
/*
* If we find a matching explicit promotion try to resolve using the matched composite relation
*/
if (matching != null) {
RelationDefinition compositeRelation = client.getComposite().getRelation(promotion.getCompositeRelation().getIdentifier());
/*
* Validate the source's and composite's relations are compatible.
*
* NOTE This is already validated at build time, but we do the tests again at runtime
*/
if (!relation.getRelationDefinition().matchRelation(client,compositeRelation)) {
logger.error("Promotion is invalid. relation " + relation.getName() + " of component " + client.getName() + " does not match the composite relation " + compositeRelation);
continue search;
}
Resolved<T> candidates = getPromotionCandidates(client, relation, compositeRelation);
if (candidates != null && !candidates.isEmpty()) {
/*
* Create the promotion links and return
*/
updateModel(client, relation, candidates, relation.hasConstraints() || compositeRelation.hasConstraints(), true);
/*
* NOTE IMPORTAN SPECIAL CASE for relations with cardinality multiple, we allow merging the result of
* several promotions
*/
if (relation.isMultiple()) {
promotionResult = candidates.merge(promotionResult);
continue search;
}
else {
promotionResult = candidates;
break search;
}
}
}
}
return promotionResult;
}
/**
* Look if a relation defined in the composite matches implicitly the specified relation, and tries to perform
* an implicit promotion
*/
private <T extends Component> Resolved<T> checkImplicitPromotion(Instance client, RelToResolve relation) {
Resolved<T> promotionResult = null;
search:
for (RelationDefinition compositeRelation : client.getComposite().getRelations()) {
if (!relation.getRelationDefinition().matchRelation(client,compositeRelation)) {
continue search;
}
Resolved<T> candidates = getPromotionCandidates(client, relation, compositeRelation);
if (candidates != null && !candidates.isEmpty()) {
/*
* Create the promotion links and return
*/
updateModel(client, relation, candidates, relation.hasConstraints() || compositeRelation.hasConstraints(), true);
/*
* NOTE IMPORTAN SPECIAL CASE for relations with cardinality multiple, we allow merging the result of
* several promotions
*/
if (relation.isMultiple()) {
promotionResult = candidates.merge(promotionResult);
continue search;
}
else {
promotionResult = candidates;
break search;
}
}
}
return promotionResult;
}
/**
* Performs a complete resolution of the relation, or resolution.
*
* The managers is asked to find the "right" component.
*
* @param client
* the instance calling implem (and where to create
* implementation ans instances if needed). Cannot be null.
* @param relToResolve
* a relation declaration containing the type and name of the
* relation target. It can be -the specification Name (new
* SpecificationReference (specName)) -an implementation name
* (new ImplementationRefernece (name) -an interface name (new
* InterfaceReference (interfaceName)) -a message name (new
* MessageReference (dataTypeName))
* @return the component(s) if resolved, null otherwise
*/
private <T extends Component> Resolved<T> resolveByManagers(RelToResolve relToResolve) {
/*
* Get the list of external managers.
*
* NOTE that we invoke getSelectionPath on all managers (even if
* resolve policy is specified EXTERNAL). In this way, managers can
* influence resolution, by adding constraints, even if they do not
* perform resolution themselves.
*
*/
SortedSet<RelationManager> externalManagers = new TreeSet<RelationManager>(ApamManagers.getRelationManagers().comparator());
for (RelationManager relationManager : ApamManagers.getRelationManagers()) {
if (relationManager.beginResolving(relToResolve))
externalManagers.add(relationManager);
}
// Compute filters once for all, and make it final
((RelToResolveImpl) relToResolve).computeFilters();
/*
* Get the list of all managers
*/
List<RelationManager> selectionPath = new ArrayList<RelationManager>();
selectionPath.add(0, apam.getApamMan());
selectionPath.add(0, apam.getUpdateMan());
if (apam.getApamMan() == null) {
throw new RuntimeException("Error while get of ApamMan");
}
if (apam.getUpdateMan() == null) {
throw new RuntimeException("Error while get of UpdateMan");
}
/*
* If resolve = exist or internal, only predefined managers must be called
*/
boolean resolveExternal = (relToResolve.getResolve() == ResolvePolicy.EXTERNAL);
if (resolveExternal) {
selectionPath.addAll(externalManagers);
}
if (!relToResolve.isRelation()) { // It is a find
logger.info("Looking for " + relToResolve.getTargetKind() + " " + relToResolve.getTarget().getName());
} else {
logger.info("Resolving " + relToResolve);
}
Resolved<T> res ;
String mess = "";
for (RelationManager manager : selectionPath) {
if (manager == null) {
throw new RuntimeException("Manager is null, SelectionPath " ) ; //+ selectionPath);
}
if (manager.getName() == null) {
throw new RuntimeException("Manager : " + manager + ", manager name is null");
}
mess += manager.getName() + " ";
logger.debug("Calling manager "+manager.getName());
res = resolveOneManager(manager, relToResolve, mess) ;
if (res != null)
return res ;
}
//All managers have been tried. No solution found
logger.debug(mess + " : not found");
return null;
}
@SuppressWarnings("unchecked")
private <T extends Component> Resolved<T> resolveOneManager (RelationManager manager, RelToResolve relToResolve, String mess) {
Resolved<T> resolved = (Resolved<T>) manager.resolve(relToResolve);
logger.debug("resolveOneManager(...), manager resolve returns "+(resolved==null?null:resolved.toString()));
if (resolved == null || resolved.isEmpty()) {
return null;
}
/*
* This manager succeeded to find a solution If an unused or deployed
* implementation. Can be into singleton or in toInstantiate if an
* instance is required
*/
Component source = relToResolve.getLinkSource();
boolean deployed = !manager.getName().equals(CST.APAMMAN) && !manager.getName().equals(CST.UPDATEMAN) ;
Component depl = (resolved.toInstantiate != null) ? resolved.toInstantiate : resolved.singletonResolved;
deployedImpl(source, depl, deployed);
/*
* If an implementation is returned as "toInstantiate" it has to be instantiated
*/
if (resolved.toInstantiate != null) {
if (relToResolve.getTargetKind() != ComponentKind.INSTANCE) {
logger.error(mess + "Invalid Resolved value. toInstantiate is set, but target kind is not an Instance");
return null;
}
/*
* If resolveExist, we cannot instantiate.
*/
if (relToResolve.getResolve() == ResolvePolicy.EXIST) {
logger.error(mess + "resolve=\"exist\" but no valid instance of " + resolved.toInstantiate + " are found. Resolve failed.");
return null;
}
/*
* This external manager returned a non instantiable implem (ApamMan does not do that).
* Try this manager again but with a constraint avoiding to find the same implem.
*/
if (!resolved.toInstantiate.isInstantiable()) {
logger.debug(mess + "Implementation non-instantiable " + resolved.toInstantiate + " was found, but no valid instance. Resolve failed.");
relToResolve.getMngImplementationConstraints().add("(!(name = " + resolved.toInstantiate.getName() + "))") ;
((RelToResolveImpl)relToResolve).computeFilters();
return resolveOneManager(manager, relToResolve, mess);
}
Composite compo = (source instanceof Instance) ? ((Instance) source).getComposite() : CompositeImpl.getRootInstance();
Instance inst = resolved.toInstantiate.createInstance(compo, null);
if (inst == null) {
/*
* Failed to be instantiated.
* Flag instantiateFails is turned to "true" in createInstance.
* Instantiation will not be attempted again on this implem.
*/
logger.error(mess + "Failed creating instance. " + resolved.toInstantiate + " turned to non-instantiable.");
//try to resolve again from beginning but prohibits this implementation (for external managers like OBRMan)
relToResolve.getMngImplementationConstraints().add("(!(name = " + resolved.toInstantiate.getName() + "))") ;
((RelToResolveImpl)relToResolve).computeFilters();
return resolveOneManager(manager, relToResolve, mess);
}
if (!relToResolve.matchRelationConstraints(inst)) {
logger.debug(mess + " Instantiated instance " + inst + " does not match the constraints");
((ComponentBrokerImpl)CST.componentBroker).disappearedComponent(inst);
return null ;
}
logger.info(mess + "Instantiated " + inst);
if (relToResolve.isMultiple()) {
Set<Instance> insts = new HashSet<Instance>();
insts.add(inst);
return (Resolved<T>) new Resolved<Instance>(insts);
} else {
return (Resolved<T>) new Resolved<Instance>(inst);
}
} //end instantiating
/*
* We have the solution, including the instance if an instance is required.
* But because managers can be third party, we cannot trust them.
* We have to check if the result is correct.
*/
if (relToResolve.isMultiple()) {
if (resolved.setResolved == null || resolved.setResolved.isEmpty()) {
logger.info(mess + "manager " + manager + " returned an empty result. Should be null.");
return null ;
}
if (((Component) resolved.setResolved.iterator().next()).getKind() != relToResolve.getTargetKind()) {
logger.error(mess + "Manager " + manager + " returned objects of the bad type for relation " + relToResolve);
return null ;
}
logger.info(mess + "Selected : " + resolved.setResolved);
return resolved;
}
// Result is a singleton
if (resolved.singletonResolved == null) {
logger.info(mess + "manager " + manager + " returned an empty result. ");
return null ;
}
if (resolved.singletonResolved.getKind() != relToResolve.getTargetKind()) {
logger.error(mess + "Manager " + manager + " returned objects of the bad type for relation " + relToResolve);
return null ;
}
logger.info(mess + "Selected : " + resolved.singletonResolved);
return resolved;
}
@Override
public Instance resolveImpl(Component client, Implementation impl, Set<String> constraints, List<String> preferences) {
if (client == null) {
client = CompositeImpl.getRootInstance();
}
@SuppressWarnings("rawtypes")
// RelToResolve dep = new RelToResolveImpl(new
// ImplementationReference(impl.getName()), client.getKind(),
// ComponentKind.INSTANCE, constraints, preferences);
RelationDefinition dep = new RelationDefinitionImpl(new ImplementationReference(impl.getName()), client.getKind(), ComponentKind.INSTANCE, constraints, preferences);
Resolved<?> resolve = resolveLink(client, dep);
if (resolve == null) {
return null;
}
return (Instance) resolve.setResolved;
}
@SuppressWarnings("unchecked")
@Override
public Set<Instance> resolveImpls(Component client, Implementation impl, Set<String> constraints) {
if (client == null) {
client = CompositeImpl.getRootInstance();
}
@SuppressWarnings("rawtypes")
// RelToResolve dep = new RelToResolveImpl(new
// ImplementationReference(impl.getName()), client.getKind(),
// ComponentKind.INSTANCE, constraints, null);
RelationDefinition dep = new RelationDefinitionImpl(new ImplementationReference(impl.getName()), client.getKind(), ComponentKind.INSTANCE, constraints, null);
Resolved<?> resolve = resolveLink(client, dep);
if (resolve == null) {
return null;
}
return (Set<Instance>) resolve.setResolved;
}
/**
* The central method for the resolver.
*/
@Override
public Resolved<?> resolveLink(Component source2, RelationDefinition rel) {
/*
* verify the resolver is actually ready to work (all managers are
* present)
*/
checkEnabled();
if (source2 == null || rel == null) {
logger.error("missing client or relation ");
return null;
}
/*
* If manual, the resolution must fail silently
*/
boolean createManual = rel.getCreation() == CreationPolicy.MANUAL;
if (createManual) {
return null;
}
Component source = rel.getRelSource(source2);
if (source == null) {
logger.error("Component source not at the right level; found " + source2 + " expected " + rel.getSourceKind());
return null;
}
/*
* Creates an relToResolve only considering the relation. Not completely initialized.
*/
RelToResolve relToResolve = new RelToResolveImpl(source, rel);
Resolved<Component> resolved = null;
/*
* If the source is an instance, verify if there is explicit promotions declared in the composite
*
* TODO When an explicit promotion is declared, we perform resolution inside the composite if the
* promotion fails. This is not very intuitive but is more resilient, to discuss which is the good
* specification.
*/
if (source instanceof Instance) {
resolved = checkExplicitPromotion((Instance) source, relToResolve);
}
/*
* If the source is not an instance or there is no explicit promotion, delegate to managers
*/
if (resolved == null) {
/*
* Delegate resolution to managers and update the model
*/
resolved = this.resolveByManagers(relToResolve);
if (resolved != null) {
updateModel(source, relToResolve, resolved, relToResolve.hasConstraints(),false);
}
/*
* As a last resort try implicit promotion
*
* NOTE Notice that we recreate the relation to resolve from the declarations, to be sure
* that we ignore all constraints that could be added by the managers during the first try
*/
if (resolved == null && source instanceof Instance) {
resolved = checkImplicitPromotion((Instance) source,new RelToResolveImpl(source,rel));
}
else if (resolved != null && source instanceof Instance && relToResolve.isMultiple()) {
/*
* TODO For relations with cardinality multiple, we try to merge all available targets,
* so we merge the managers' result with the implicit promotions. This is not very intuitive
* but is more resilient, to discuss which is the good specification.
*/
resolved = resolved.merge(checkImplicitPromotion((Instance) source, relToResolve));
}
}
return handleFailure(relToResolve,resolved);
}
/**
* Updates the model to create all the links corresponding to the resolution result
*/
private void updateModel(Component source, RelToResolve relation, Resolved<?> resolutionResult, boolean hasConstraints, boolean isPromotion) {
if (resolutionResult == null || resolutionResult.isEmpty()) {
return;
}
if (resolutionResult.singletonResolved != null) {
source.createLink(resolutionResult.singletonResolved, relation, hasConstraints, isPromotion);
}
else {
for (Component target : resolutionResult.setResolved) {
source.createLink(target, relation, hasConstraints, isPromotion);
}
}
}
private Resolved<?> handleFailure(RelToResolve relToResolve, Resolved<?> result) {
/*
* If managers could not resolve and relation cannot be promoted, give a
* chance to failure manager
*/
if (result == null || result.isEmpty()) {
result = apam.getFailedResolutionManager().resolve(relToResolve);
}
/*
* If failure manager could not recover, just give up
*/
if (result == null || result.isEmpty()) {
if (relToResolve.getRelationDefinition().getName().isEmpty())
logger.error("Failed to resolve " + relToResolve.getRelationDefinition().getTarget().getName() + " from " + relToResolve.getLinkSource() );
else
logger.error("Failed to resolve " + relToResolve.getRelationDefinition().getTarget().getName() + " from " + relToResolve.getLinkSource() + "(relation " + relToResolve.getRelationDefinition().getName() + ")");
return null;
}
return result;
}
/**
* An APAM client instance requires to be wired with one or all the
* instances that satisfy the relation. WARNING : in case of interface or
* message relation , since more than one specification can implement the
* same interface, any specification implementing at least the provided
* interface (technical name of the interface) will be considered
* satisfactory. If found, the instance(s) are bound is returned.
*
* @param source
* the instance that requires the specification
* @param depName
* the relation name. Field for atomic; spec name for complex
* dep, type for composite.
* @return
*/
@Override
public Resolved<?> resolveLink(Component source, String depName) {
if ((depName == null) || (source == null)) {
logger.error("missing client or relation name");
return null;
}
// Get the relation
RelationDefinition relDef = source.getRelation(depName);
if (relDef == null) {
logger.error("Relation declaration invalid or not found " + depName);
return null;
}
return resolveLink(source, relDef);
}
@Override
public Implementation resolveSpecByInterface(Component client, String interfaceName, Set<String> constraints, List<String> preferences) {
RelationDefinition dep = new RelationDefinitionImpl(new InterfaceReference(interfaceName), client.getKind(), ComponentKind.IMPLEMENTATION, constraints, preferences);
return resolveSpecByResource(client, dep);
}
@Override
public Implementation resolveSpecByMessage(Component client, String messageName, Set<String> constraints, List<String> preferences) {
RelationDefinition dep = new RelationDefinitionImpl(new MessageReference(messageName), client.getKind(), ComponentKind.IMPLEMENTATION, constraints, preferences);
return resolveSpecByResource(client, dep);
}
/**
* First looks for the specification defined by its name, and then resolve
* that specification. Returns the implementation that implement the
* specification and that satisfies the constraints.
*
* @param compoType
* : the implementation to return must either be visible from
* compoType, or be deployed.
* @param specName
* @param constraints
* . The constraints to satisfy. They must be all satisfied.
* @param preferences
* . If more than one implementation satisfies the constraints,
* returns the one that satisfies the maximum number of
* preferences, taken in the order, and stopping at the first
* failure.
* @return
*/
@Override
public Implementation resolveSpecByName(Instance client, String specName, Set<String> constraints, List<String> preferences) {
if (client == null) {
client = CompositeImpl.getRootInstance();
}
RelationDefinition dep = new RelationDefinitionImpl(new SpecificationReference(specName), client.getKind(), ComponentKind.IMPLEMENTATION, constraints, preferences);
return resolveSpecByResource(client, dep);
}
/**
* First looks for the specification defined by its interface, and then
* resolve that specification. Returns the implementation that implement the
* specification and that satisfies the constraints.
*
* @param compoType
* : the implementation to return must either be visible from
* compoType, or be deployed.
* @param interfaceName
* . The full name of one of the interfaces of the specification.
* WARNING : different specifications may share the same
* interface.
* @param interfaces
* . The complete list of interface of the specification. At most
* one specification can be selected.
* @param constraints
* . The constraints to satisfy. They must be all satisfied.
* @param preferences
* . If more than one implementation satisfies the constraints,
* returns the one that satisfies the maximum number of
* preferences, taken in the order, and stopping at the first
* failure.
* @return
*/
public Implementation resolveSpecByResource(Component client, RelationDefinition relDef) {
if (relDef.getTargetKind() != ComponentKind.IMPLEMENTATION) {
logger.error("Invalid target type for resolveSpecByResource. Implemntation expected, found : " + relDef.getTargetKind());
return null;
}
Resolved<?> resolve = resolveLink(client, relDef);
if (resolve == null) {
return null;
}
if (resolve.singletonResolved != null) {
return (Implementation) resolve.singletonResolved;
}
return (Implementation) resolve.setResolved.iterator().next();
}
@Override
public void updateComponent(String componentName) {
Implementation impl = CST.componentBroker.getImpl(componentName);
if (impl == null) {
logger.error("Unknown component " + componentName);
return;
}
UpdateMan.updateComponent(impl);
}
}