Package fr.imag.adele.apam.impl

Source Code of fr.imag.adele.apam.impl.RelationDefinitionImpl

package fr.imag.adele.apam.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.Component;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.RelationDefinition;
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.MissingPolicy;
import fr.imag.adele.apam.declarations.RelationDeclaration;
import fr.imag.adele.apam.declarations.RequirerInstrumentation;
import fr.imag.adele.apam.declarations.ResolvePolicy;
import fr.imag.adele.apam.declarations.references.ResolvableReference;
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.SpecificationReference;
import fr.imag.adele.apam.util.ApamFilter;

public class RelationDefinitionImpl implements RelationDefinition {

  static Logger logger = LoggerFactory.getLogger(ApamResolverImpl.class);

  /**
   * The effective declaration used to build this relation,
   */
  private final RelationDeclaration declaration;

  // Relationship name
  private final String identifier;

  // Target definition (resource or component reference)
  private final ResolvableReference targetDefinition;

  // Source type for this relation (Spec, implem, instance)
  private final ComponentKind sourceKind;

  // Target type for this relation (Spec, implem, instance)
  private final ComponentKind targetKind;

  // TODO // The reference to the associated component ??
  // private final Component component;

  /**
   * The set of constraints that must be satisfied by the target component
   * implementation. Filters are set only if static (i.e. there is no
   * substitutions into filters)
   */
  private final Set<String> implementationConstraints = new HashSet<String>();
  private Set<ApamFilter> implementationConstraintFilters; // = new
  // HashSet<ApamFilter>();
  private boolean isStaticImplemConstraints;

  /**
   * The set of constraints that must be satisfied by the target component
   * instance
   */
  private final Set<String> instanceConstraints = new HashSet<String>();
  private Set<ApamFilter> instanceConstraintFilters; // = new
  // HashSet<ApamFilter>();
  private boolean isStaticInstConstraints;

  /**
   * The list of preferences to choose among candidate service provider
   * implementation
   */
  private final List<String> implementationPreferences = new ArrayList<String>();
  private List<ApamFilter> implementationPreferenceFilters; // = new
  // ArrayList<ApamFilter>();
  private boolean isStaticImplemPreferences = false;

  /**
   * The list of preferences to choose among candidate service provider
   * instances
   */
  private final List<String> instancePreferences = new ArrayList<String>();
  private List<ApamFilter> instancePreferenceFilters; // = new
  // ArrayList<ApamFilter>();
  private boolean isStaticInstPreferences = false;

  // Whether this relation is declared explicitly as multiple
  private final boolean isMultiple;

  private final CreationPolicy create;

  private final ResolvePolicy resolve;

  // The policy to handle unresolved dependencies
  private final MissingPolicy missingPolicy;

  // The exception to throw for the exception missing policy
  private final String missingException;

  // Whether a resolution error must trigger a backtrack in the architecture
  private final boolean mustHide;

  // true if this is a dynamic relation : a field multiple, or a dynamic
  // message
  private final boolean isDynamic;

  // If this is a Wire definition. Can be overloaded. Null if unknown.
  private boolean isWire;

  // Injected. Can be overloaded. Null if unknown.
  private boolean isInjected;

  /*
   * Component can be null; in that case filters are not substituted.
   */
  public RelationDefinitionImpl(RelationDeclaration declaration) {

    this.declaration = declaration;
    this.identifier = declaration.getIdentifier();
    this.sourceKind = (declaration.getSourceKind() == null) ? ComponentKind.INSTANCE : declaration.getSourceKind();
    this.targetKind = (declaration.getTargetKind() == null) ? ComponentKind.INSTANCE : declaration.getTargetKind();
    this.targetDefinition = declaration.getTarget();

    // computing isDynamic, isWire, hasField.
    // NOTE the relation declaration is already refined and overridden so
    // we have access to all the information from all levels above
    this.isWire = false;
    this.isInjected = false;

    boolean hasCallbacks = false;

    for (RequirerInstrumentation injection : declaration.getInstrumentations()) {

      if (injection instanceof RequirerInstrumentation.MessageConsumerCallback) {
        hasCallbacks = true;
      }

      if (injection instanceof RequirerInstrumentation.RequiredServiceField) {
        this.isInjected = true;
        if (((RequirerInstrumentation.RequiredServiceField) injection).isWire()) {
          this.isWire = true;
        }
      }
    }

    // Flags
    this.isMultiple = declaration.isMultiple();
    if (declaration.getCreationPolicy() == null) {
      this.create = hasCallbacks ? CreationPolicy.EAGER : CreationPolicy.LAZY;
    } else {
      this.create = declaration.getCreationPolicy();
    }

    this.resolve = declaration.getResolvePolicy() == null ? ResolvePolicy.EXTERNAL : declaration.getResolvePolicy();
    this.missingPolicy = declaration.getMissingPolicy();
    this.missingException = declaration.getMissingException();

    this.mustHide = (declaration.isHide() == null) ? false : declaration.isHide();
    this.isDynamic = declaration.isMultiple() || (this.create == CreationPolicy.EAGER);

    // Constraints
    this.implementationConstraints.addAll(declaration.getImplementationConstraints());
    this.instanceConstraints.addAll(declaration.getInstanceConstraints());
    this.implementationPreferences.addAll(declaration.getImplementationPreferences());
    this.instancePreferences.addAll(declaration.getInstancePreferences());

    // Check constraint syntax and compute booleans isStaticxxxx
    initializeRelation();
  }

  public RelationDefinitionImpl(ResolvableReference target, ComponentKind sourceKind, ComponentKind targetKind, Set<String> constraints, List<String> preferences) {
    // The minimum info for a find.
    this.declaration = null;
    this.identifier = "";
    this.targetDefinition = target;
    this.isMultiple = false;
    this.create = CreationPolicy.LAZY;
    this.resolve = ResolvePolicy.EXTERNAL;
    this.sourceKind = (sourceKind == null) ? ComponentKind.INSTANCE : sourceKind;
    this.targetKind = (targetKind == null) ? ComponentKind.INSTANCE : targetKind;

    isDynamic = false;
    isWire = false;
    isInjected = false;
    mustHide = false;
    missingException = null;
    missingPolicy = null;

    if (constraints != null) {
      if (targetKind == ComponentKind.IMPLEMENTATION) {
        implementationConstraints.addAll(constraints);
      }
      instanceConstraints.addAll(constraints);
    }
    if (preferences != null) {
      if (targetKind == ComponentKind.IMPLEMENTATION) {
        implementationPreferences.addAll(constraints);
      }
      instancePreferences.addAll(preferences);
    }

    // Check constraint syntax and compute filter and booleans isStaticxxxx
    initializeRelation();
  }

  @Override
  public CreationPolicy getCreation() {
    return create;
  }

  public RelationDeclaration getDeclaration() {
    return declaration;
  }

  public Set<ApamFilter> getImplementationConstraintFilters() {
    return Collections.unmodifiableSet(implementationConstraintFilters);
  }

  /**
   * Get the constraints that need to be satisfied by the implementation that
   * resolves the reference
   */
  @Override
  public Set<String> getImplementationConstraints() {
    return Collections.unmodifiableSet(implementationConstraints);
  }

  // Get the resource provider preferences
  @Override
  public List<String> getImplementationPreferences() {
    return Collections.unmodifiableList(implementationPreferences);
  }

  public List<ApamFilter> getImplementationpreferencfeFilters() {
    return Collections.unmodifiableList(implementationPreferenceFilters);
  }

  public Set<ApamFilter> getInstanceConstraintFilters() {
    return Collections.unmodifiableSet(instanceConstraintFilters);
  }

  // Get the constraints that need to be satisfied by the instance that
  // resolves the reference
  @Override
  public Set<String> getInstanceConstraints() {
    return Collections.unmodifiableSet(instanceConstraints);
  }

  public List<ApamFilter> getInstancePreferenceFilters() {
    return Collections.unmodifiableList(instancePreferenceFilters);
  }

  // Get the instance provider preferences
  @Override
  public List<String> getInstancePreferences() {
    return Collections.unmodifiableList(instancePreferences);
  }

  // Get the exception associated with the missing policy
  @Override
  public String getMissingException() {
    return missingException;
  }

  // Get the policy associated with this relation
  @Override
  public MissingPolicy getMissingPolicy() {
    return missingPolicy;
  }

  // Get the id of the relation in the declaring component declaration
  @Override
  public String getName() {
    return identifier;
  }

  /*
   * return the component corresponding to the sourceKind.
   */
  @Override
  public Component getRelSource(Component base) {
    Component source = base;
    while (source != null) {
      if (source.getKind() == getSourceKind()) {
        return source;
      }
      source = source.getGroup();
    }
    return null;
  }

  @Override
  public ResolvePolicy getResolve() {
    return resolve;
  }

  @Override
  public ComponentKind getSourceKind() {
    return sourceKind;
  }

  /**
   * Get the reference to the required resource
   */
  @Override
  public ResolvableReference getTarget() {
    return targetDefinition;
  }

  @Override
  public ComponentKind getTargetKind() {
    return targetKind;
  }

  @Override
  public boolean hasConstraints() {
    return !implementationConstraints.isEmpty() || !instanceConstraints.isEmpty();
  }

  /**
   * To be called before any use of this relation.
   *
   * @param component
   *            the component source on which is defined this relation
   */
  private void initializeRelation() {
    // Check if there are substitutions, and build filters
    ApamFilter f;
    isStaticImplemConstraints = true;
    isStaticInstConstraints = true;
    isStaticImplemPreferences = true;
    isStaticInstPreferences = true;

    for (String c : implementationConstraints) {
      implementationConstraintFilters = new HashSet<ApamFilter>();
      if (ApamFilter.isSubstituteFilter(c, null)) {
        isStaticImplemConstraints = false;
        implementationConstraintFilters = null;
        break;
      }
      f = ApamFilter.newInstanceApam(c, null);
      if (f != null) {
        implementationConstraintFilters.add(f);
      }
    }

    for (String c : instanceConstraints) {
      instanceConstraintFilters = new HashSet<ApamFilter>();
      if (ApamFilter.isSubstituteFilter(c, null)) {
        isStaticInstConstraints = false;
        instanceConstraintFilters = null;
        break;
      }
      f = ApamFilter.newInstanceApam(c, null);
      if (f != null) {
        instanceConstraintFilters.add(f);
      }
    }

    for (String c : implementationPreferences) {
      implementationPreferenceFilters = new ArrayList<ApamFilter>();
      if (ApamFilter.isSubstituteFilter(c, null)) {
        isStaticImplemPreferences = false;
        implementationPreferenceFilters = null;
        break;
      }
      f = ApamFilter.newInstanceApam(c, null);
      if (f != null) {
        implementationPreferenceFilters.add(f);
      }
    }

    for (String c : instancePreferences) {
      instancePreferenceFilters = new ArrayList<ApamFilter>();
      if (ApamFilter.isSubstituteFilter(c, null)) {
        isStaticInstPreferences = false;
        instancePreferenceFilters = null;
        break;
      }
      f = ApamFilter.newInstanceApam(c, null);
      if (f != null) {
        instancePreferenceFilters.add(f);
      }
    }
  }

  @Override
  public boolean isDynamic() {
    return isDynamic;
  }

  /**
   * Whether an error resolving a relation matching this policy should trigger
   * a backtrack in resolution
   */
  @Override
  public boolean isHide() {
    return mustHide;
  }

  @Override
  public boolean isInjected() {
    return isInjected;
  }

  @Override
  public boolean isMultiple() {
    return isMultiple;
  }

  @Override
  public boolean isRelation() {
    return !identifier.isEmpty();
  }

  public boolean isStaticImplemConstraints() {
    return isStaticImplemConstraints;
  }

  public boolean isStaticImplemPreferences() {
    return isStaticImplemPreferences;
  }

  public boolean isStaticInstConstraints() {
    return isStaticInstConstraints;
  }

  public boolean isStaticInstPreferences() {
    return isStaticInstPreferences;
  }

  // return !mngImplementationConstraintFilters.isEmpty()
  // || !mngInstanceConstraintFilters.isEmpty()
  // || !implementationConstraintFilters.isEmpty()
  // || !instanceConstraintFilters.isEmpty();

  @Override
  public boolean isWire() {
    return isWire;
  }

  /**
   * Provided a client instance, checks if its relation "clientDep", matches
   * another relation: "compoDep".
   *
   * matches only based on same name (same resource or same component). If
   * client cardinality is multiple, compo cardinallity must be multiple too.
   * No provision for the client constraints or characteristics (missing,
   * eager)
   *
   * @param compoInst
   *            the composite instance containing the client
   * @param compoDep
   *            the relation that matches or not
   * @param clientDep
   *            the client relation we are trying to resolve
   * @return
   */
  @Override
  public boolean matchRelation(Instance compoInst, RelationDefinition compoDep) {
    // RelToResolve rel = new RelToResolveImpl (inst, relDef) ;
    // return rel.matchRelation(inst) ;
    // }
    if (compoDep == null) {
      return false;
    }

    if (compoDep.getTargetKind() != getTargetKind()) {
      return false;
    }

    if (compoDep.getSourceKind() != getSourceKind()) {
      return false;
    }

    // Look for same relation: the same specification, the same
    // implementation or same resource name
    // Constraints are not taken into account
    boolean multiple = isMultiple();

    // if same nature (spec, implem, internface ... make a direct
    // comparison.
    if (compoDep.getTarget().getClass().equals(getTarget().getClass())) {
      if (compoDep.getTarget().equals(getTarget())) {
        if (!multiple || compoDep.isMultiple()) {
          return true;
        }
      }
    }

    // Look for a compatible relation.
    // Stop at the first relation matching only based on same name (same
    // resource or same component)
    // No provision for : cardinality, constraints or characteristics
    // (missing, eager)

    // Look if the client requires one of the resources provided by the
    // specification
    if (compoDep.getTarget() instanceof SpecificationReference) {
      Specification spec = CST.apamResolver.findSpecByName(compoInst, ((SpecificationReference) compoDep.getTarget()).getName());
      if ((spec != null) && spec.getDeclaration().getProvidedResources().contains(getTarget()) && (!multiple || compoDep.isMultiple())) {
        return true;
      }
    }

    // If the composite has a relation toward an implementation
    // and the client requires a resource provided by that implementation
    else {
      if (compoDep.getTarget() instanceof ImplementationReference) {
        String implName = ((ImplementationReference<?>) compoDep.getTarget()).getName();
        Implementation impl = CST.apamResolver.findImplByName(compoInst, implName);
        if (impl != null) {
          // The client requires the specification implemented by that
          // implementation
          if (getTarget() instanceof SpecificationReference) {
            String clientReqSpec = ((SpecificationReference) getTarget()).getName();
            if (impl.getSpec().getName().equals(clientReqSpec) && (!multiple || compoDep.isMultiple())) {
              return true;
            }
          } else {
            // The client requires a resource provided by that
            // implementation
            if (impl.getImplDeclaration().getProvidedResources().contains(getTarget()) && (!multiple || compoDep.isMultiple())) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  // public static LinkImpl createLink ()

  /**
   * Checks if this relation can refine the specified declaration for refinement or override.
   * Matching can be based on the name of the declaring component or one of its ancestor groups
   *
   */
  public boolean refines(ComponentReference<?>group, RelationDeclaration relation) {
    return this.declaration != null ? this.declaration.refines(group,relation) : false;
  }

  /**
   * Checks if this contextual relation definition applies to the specified source
   */
  public boolean  appliesTo(ComponentReference<?> source) {
    return this.declaration != null ? this.declaration.appliesTo(source) : false;
  }
 
  /**
   * Get the effective result of refining this relation by the specified partial declaration
   */
  public RelationDeclaration refinedBy(RelationDeclaration refinement) {
    return this.declaration != null ? this.declaration.refinedBy(refinement) : refinement;
  }

  @Override
  public String toString() {
    StringBuffer ret = new StringBuffer();
    // ret.append("resolving ");

    if (isRelation()) {
      ret.append("relation " + getName() + " towards ");
    }

    if (isMultiple) {
      ret.append("multiple ");
    }

    ret.append(getTargetKind());

    if (getTarget() instanceof ComponentReference<?>) {
      ret.append(" of" + getTarget());
    } else {
      ret.append(" providing " + getTarget());
    }

    // ret.append(" from " + linkSource);
    ret.append(" (creation = " + create + ", resolve = " + resolve + ", missing policy = " + this.missingPolicy + ")");

    return ret.toString();
  }

}
TOP

Related Classes of fr.imag.adele.apam.impl.RelationDefinitionImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.