Package fr.imag.adele.apam.manager.conflict

Source Code of fr.imag.adele.apam.manager.conflict.ContentManager$GrantScope

/**
* 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.manager.conflict;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
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.Composite;
import fr.imag.adele.apam.Implementation;
import fr.imag.adele.apam.Instance;
import fr.imag.adele.apam.Link;
import fr.imag.adele.apam.RelToResolve;
import fr.imag.adele.apam.declarations.CompositeDeclaration;
import fr.imag.adele.apam.declarations.GrantDeclaration;
import fr.imag.adele.apam.declarations.OwnedComponentDeclaration;
import fr.imag.adele.apam.declarations.PropertyDefinition;
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.impl.ComponentImpl.InvalidConfiguration;
import fr.imag.adele.apam.impl.CompositeImpl;
import fr.imag.adele.apam.impl.FailedResolutionManager;
import fr.imag.adele.apam.impl.InstanceImpl;
import fr.imag.adele.apam.impl.PendingRequest;

/**
* This class is responsible for solving conflicts over owned instances of a
* composite
*
* @author vega
*
*/
public class ContentManager {

  @SuppressWarnings("unused")
  private final static Logger logger = LoggerFactory
      .getLogger(ContentManager.class);

  /**
   * verifies if a component matches the specified grant source
   */
  private static boolean match(GrantDeclaration grant, Component source) {
   
    ComponentReference<?> grantSource = grant.getRelation().getDeclaringComponent();
    while (source != null) {

      if (source.getDeclaration().getReference().equals(grantSource)) {
        return true;
      }

      source = source.getGroup();
    }

    return false;
  }

 
  /**
   * verifies if the requested resolution matches the specified grant
   */
  private static boolean match(GrantDeclaration grant, PendingRequest request) {
    return   request.getRelation().getName().equals(grant.getRelation().getIdentifier()) &&
        match(grant, request.getSource());
  }

  /**
   * verifies if a link matches the specified grant
   */
  private static boolean match(GrantDeclaration grant, Link link) {
    return  link.getName().equals(grant.getRelation().getIdentifier()) &&
        match(grant, link.getSource());
  }



  /**
   * A back reference to the conflict manager
   */
  private ConflictManager manager;

  /**
   * The declaration of the composite type
   *
   * NOTE currently declarations are read-only, so we can safely navigate this
   * information without any thread synchronization
   */
  private final CompositeDeclaration declaration;

  /**
   * The managed composite
   */
  private final Composite composite;

  /**
   * The instances that are owned by this content manager. This is a subset of
   * the contained instances of the composite.
   */
  private final Map<OwnedComponentDeclaration, Set<Instance>> owned;

  /**
   * The current state of the composite
   */
  private String state;

  /**
   * The instance that holds the state of the content manager. This instance
   * is automatically created inside the composite at start of content
   * manager.
   */
  private Instance stateHolder;

  /**
   * The property used for holding the state
   */
  private String stateProperty;

  /**
   * The active grant in the current state
   */
  private final Map<OwnedComponentDeclaration, GrantDeclaration> granted;


  /**
   * Initializes the content manager
   */
  public ContentManager(ConflictManager manager, Composite composite) {

    this.manager    = manager;
    this.composite     = composite;
    this.declaration  = composite.getCompType().getCompoDeclaration();

    /*
     * Initialize state information
     */

    this.stateHolder   = null;
    this.stateProperty  = null;
    this.state       = null;

    /*
     * Initialize ownership information
     */
    owned   = new HashMap<OwnedComponentDeclaration, Set<Instance>>();
    granted = new HashMap<OwnedComponentDeclaration, GrantDeclaration>();
    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {
      owned.put(ownedDeclaration, new HashSet<Instance>());
    }

  }

  /**
   * Accord ownership of the specified instance to this composite
   */
  public void accordOwnership(Instance instance) {

    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {

      /*
       * find matching declaration
       */
      boolean matchType = false;

      if (ownedDeclaration.getComponent() instanceof SpecificationReference) {
        matchType = instance.getSpec().getDeclaration().getReference().equals(ownedDeclaration.getComponent());
      }

      if (ownedDeclaration.getComponent() instanceof ImplementationReference<?>) {
        matchType = instance.getImpl().getDeclaration().getReference().equals(ownedDeclaration.getComponent());
      }

      if (!matchType) {
        continue;
      }

      String property     = ownedDeclaration.getProperty() != null ? ownedDeclaration.getProperty().getIdentifier() : null;
      String propertyValue  = property != null ? instance.getProperty(property) : null;
     
      boolean matchProperty   = property == null || (propertyValue != null && ownedDeclaration.getValues().contains(propertyValue));

      if (!matchProperty) {
        continue;
      }

      /*
       * get ownership
       */
      ((InstanceImpl) instance).setOwner(getComposite());

      /*
       * register owned instance
       */
      synchronized (owned) {
        owned.get(ownedDeclaration).add(instance);
      }

      /*
       * preempt previous users of the instance and give access to
       * currently granted waiting requests
       */
      preempt(ownedDeclaration, instance);

    }
  }

  /**
   * The composite is removed
   */
  public synchronized void dispose() {

    stateHolder = null;
    state     = null;

    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {
      owned.get(ownedDeclaration).clear();
    }

  }

  /**
   * The composite managed by this content manager
   */
  public Composite getComposite() {
    return composite;
  }

  /**
   * The list of potential ownership's conflict between this content manager
   * and the one specified in the parameter
   *
   */
  public Set<OwnedComponentDeclaration> getConflictingDeclarations(ContentManager that) {

    Set<OwnedComponentDeclaration> conflicts = new HashSet<OwnedComponentDeclaration>();

    for (OwnedComponentDeclaration thisDeclaration : declaration.getOwnedComponents()) {

      ComponentReference<?> thisSpecification = thisDeclaration.getComponent();
      String thisProperty   = thisDeclaration.getProperty() != null ? thisDeclaration.getProperty().getIdentifier() : null;
      Set<String> theseValues = new HashSet<String>(thisDeclaration.getValues());

      /*
       * Ownership declarations are conflicting if they refer to the same
       * specification, with different properties or with the same values
       * for the same property
       */

      boolean hasConflict = false;
      for (OwnedComponentDeclaration thatDeclaration : that.declaration.getOwnedComponents()) {

        ComponentReference<?> thatSpecification = thatDeclaration.getComponent();
        String thatProperty = thatDeclaration.getProperty() != null ? thatDeclaration.getProperty().getIdentifier() : null;
        Set<String> thoseValues = new HashSet<String>(thatDeclaration.getValues());

        if (!thisSpecification.equals(thatSpecification)) {
          continue;
        }

        if (thisProperty == null || thatProperty == null || !thisProperty.equals(thatProperty) ||
          !Collections.disjoint(theseValues, thoseValues)) {
          hasConflict = true;
        }

      }

      if (hasConflict) {
        conflicts.add(thisDeclaration);
      }

    }

    return conflicts;
  }

  /**
   * Get the current grant for the specified ownership declaration
   */
  private GrantDeclaration getCurrentGrant(OwnedComponentDeclaration ownedDeclaration) {
    synchronized (granted) {
      return granted.get(ownedDeclaration);
    }
  }

  /**
   * The declaration of the owned instances
   */
  public Set<OwnedComponentDeclaration> getOwned() {
    return declaration.getOwnedComponents();
  }

  /**
   * Get a thread safe (stack contained) copy of the current list of instances
   * owned for the specified ownership declaration
   */
  private Collection<Instance> getOwned(OwnedComponentDeclaration ownedDeclaration) {
    synchronized (owned) {
      return new ArrayList<Instance>(owned.get(ownedDeclaration));
    }
  }

  /**
   * Whether the specified instance is currently owned by this composite
   */
  public boolean owns(Instance instance) {

    if (!instance.getComposite().equals(getComposite())) {
      return false;
    }

    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {
      if (getOwned(ownedDeclaration).contains(instance)) {
        return true;
      }
    }

    return false;

  }

  /**
   * Preempt access to the specified instance from all clients that no longer
   * hold the grant
   *
   */
  private void preempt(OwnedComponentDeclaration ownedDeclaration, Instance ownedInstance) {

    assert this.owns(ownedInstance);

    GrantDeclaration grant = getCurrentGrant(ownedDeclaration);
    for (Link incoming : ownedInstance.getInvLinks()) {
      if (grant != null && !match(grant, incoming)) {
        incoming.remove();
      }
    }

    /*
     * Wake pending request that could be satisfied by the new grant
     */
    manager.getFailureManager().resolveWaitingRequests(new GrantScope(grant), ownedInstance);

  }

  /**
   * A condition to wakeup only the subset of waiting request concerned by a grant change
   */
  private static class GrantScope implements FailedResolutionManager.Scope {

    private final GrantDeclaration  grant;
   
    public GrantScope(GrantDeclaration grant) {
      this.grant = grant;
    }
   
    @Override
    public boolean concerns(PendingRequest request) {
      return grant != null && ContentManager.match(grant, request);
    }
   
  }
  /**
   * Verifies all the effects of a property change in the contained instances
   *
   */
  public void propertyChanged(Instance instance, String property) {

    assert instance.getComposite().equals(getComposite());

    boolean stateChanged = false;
    String newState = null;

    synchronized (this) {
      if (stateHolder != null && stateHolder.equals(instance&& stateProperty.equals(property)) {
        stateChanged = true;
        newState = stateHolder.getProperty(stateProperty);
      }
    }

    if (stateChanged) {
      stateChanged(newState);
    }

  }

  /**
   * Updates the contents of this composite when a contained instance is
   * removed from APAM
   *
   */
  public void removedInstance(Instance instance) {

    assert instance.getComposite().equals(getComposite());

    /*
     * update state
     */
    synchronized (this) {
      if (instance == stateHolder) {
        stateHolder = null;
      }
    }

    /*
     * update list of owned instances
     */
    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {
      synchronized (owned) {
        owned.get(ownedDeclaration).remove(instance);
      }
    }
  }

  /**
   * Revokes ownership of the specified instance
   *
   */
  public void revokeOwnership(Instance instance) {

    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {
      synchronized (owned) {
        owned.get(ownedDeclaration).remove(instance);
      }
    }

    ((InstanceImpl) instance).setOwner(CompositeImpl.getRootAllComposites());
  }

  /**
   * Preempt access to the owned instances from their current clients, and
   * give it to the requests satisfying the new grant
   */
  private void setCurrentGrant(OwnedComponentDeclaration ownedDeclaration, GrantDeclaration newGrant) {

    /*
     * change current grant
     */
    synchronized (granted) {
      if (newGrant != null) {
        granted.put(ownedDeclaration, newGrant);
      } else {
        granted.remove(ownedDeclaration);
      }
    }

    /*
     * preempt all clients that do not satisfy the new grant
     */
    for (Instance ownedInstance : getOwned(ownedDeclaration)) {
      preempt(ownedDeclaration, ownedInstance);
    }

  }

  /**
   * Whether this composite requests ownership of the specified instance
   */
  public boolean shouldOwn(Instance instance) {

    /*
     * Iterate over all ownership declarations and verify if the instance
     * matches the specified condition
     */
    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {

      boolean matchType = false;

      if (ownedDeclaration.getComponent() instanceof SpecificationReference) {
        matchType = instance.getSpec().getDeclaration().getReference().equals(ownedDeclaration.getComponent());
      }

      if (ownedDeclaration.getComponent() instanceof ImplementationReference<?>) {
        matchType = instance.getImpl().getDeclaration().getReference().equals(ownedDeclaration.getComponent());
      }

      String property     = ownedDeclaration.getProperty() != null ? ownedDeclaration.getProperty().getIdentifier() : null;
      String propertyValue  = property != null ? instance.getProperty(property) : null;
      boolean matchProperty   = property == null || (propertyValue != null && ownedDeclaration.getValues().contains(propertyValue));

      if (matchType && matchProperty) {
        return true;
      }
    }

    return false;
  }

  /**
   * Activates the content manager
   */
  public synchronized void start() throws InvalidConfiguration {

    /*
     * Initialize state information
     */

    this.stateHolder   = null;
    this.stateProperty  = null;
    this.state       = null;

    if (declaration.getStateProperty() != null) {

      PropertyDefinition.Reference propertyReference = declaration.getStateProperty();

      /*
       * Get the component that defines the property, notice that this may
       * deploy the implementation if not yet installed
       */
      Component implementation = CST.apamResolver.findComponentByName(composite.getMainInst(), propertyReference.getDeclaringComponent().getName());

      /*
       * In case the implementation providing the state is not available
       * signal an error.
       */
      if (implementation == null  || !(implementation instanceof Implementation)) {
        throw new InvalidConfiguration("Invalid state declaration, implementation can not be found "+
                propertyReference.getDeclaringComponent().getName());
      }

      /*
       * Eagerly instantiate an instance to hold the state.
       *
       * In case the main instance can be used to hold state we avoid
       * creating additional objects.
       */
      if (composite.getMainInst() != null  && composite.getMainInst().getImpl().equals(implementation)) {
        this.stateHolder = composite.getMainInst();
      } else {
        this.stateHolder = ((Implementation) implementation).createInstance(composite, null);
      }

      /*
       * Get the property used to handle the state
       */
      PropertyDefinition propertyDefinition = implementation.getDeclaration().getPropertyDefinition(propertyReference);

      /*
       * In case the property providing the state is not defined signal an
       * error.
       */
      if (propertyDefinition == null) {
        throw new InvalidConfiguration("Invalid state declaration, property not defined "+ propertyReference.getIdentifier());
      }

      this.stateProperty = propertyDefinition.getName();

      /*
       * compute the initial state of the composite
       */
      this.state = this.stateHolder.getProperty(this.stateProperty);

    }

    /*
     * Initialize ownership information
     */

    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {

      /*
       * Compute the current grant based on the initial state
       */
      for (GrantDeclaration grant : ownedDeclaration.getGrants()) {
        if (state != null && grant.getStates().contains(state)) {
          granted.put(ownedDeclaration, grant);
        }
      }
    }

  }

  /**
   * Handle state changes in the composite
   */
  private void stateChanged(String newState) {

    /*
     * Change state
     */
    synchronized (this) {
      this.state = newState;
    }

    /*
     * Reevaluate grants
     */
    for (OwnedComponentDeclaration ownedDeclaration : declaration.getOwnedComponents()) {

      /*
       * If the current grant is still valid there is nothing to do
       */
      synchronized (granted) {
        GrantDeclaration previuos = granted.get(ownedDeclaration);
        if (previuos != null && previuos.getStates().contains(newState)) {
          continue;
        }
      }

      /*
       * Set new grant, according to new state
       */

      GrantDeclaration newGrant = null;
      for (GrantDeclaration grant : ownedDeclaration.getGrants()) {
        if (grant.getStates().contains(newState)) {
          newGrant = grant;
        }
      }

      setCurrentGrant(ownedDeclaration, newGrant);
    }
  }

  /**
   * Verify if a resolution request has access granted, and update the resolution constraints
   * accordingly
   */
  public void addGrantConstraints(RelToResolve relation) {

    PendingRequest request = PendingRequest.isRetry() ?
        PendingRequest.current() :
        new PendingRequest(CST.apamResolver,relation.getLinkSource(),relation.getRelationDefinition());

    for (OwnedComponentDeclaration ownedDeclaration : getOwned()) {

      GrantDeclaration grant = getCurrentGrant(ownedDeclaration);
      boolean granted = grant == null || match(grant, request);

      /*
       * Add a constraint to avoid that a request be resolved against an owned instance that
       * is not granted to the source of the request
       */
      for (Instance ownedInstance : getOwned(ownedDeclaration)) {
        if (!granted && request.isSatisfiedBy(ownedInstance)) {
          relation.getMngInstanceConstraints().add("(! ("+CST.INSTNAME+" = "+ownedInstance.getName()+"))");
        }
      }
    }

  }

}
TOP

Related Classes of fr.imag.adele.apam.manager.conflict.ContentManager$GrantScope

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.