Package fr.imag.adele.apam.declarations.encoding.capability

Source Code of fr.imag.adele.apam.declarations.encoding.capability.CapabilityParser

package fr.imag.adele.apam.declarations.encoding.capability;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.felix.bundlerepository.Capability;
import org.apache.felix.bundlerepository.Property;

import fr.imag.adele.apam.CST;
import fr.imag.adele.apam.declarations.AtomicImplementationDeclaration;
import fr.imag.adele.apam.declarations.ComponentDeclaration;
import fr.imag.adele.apam.declarations.ComponentKind;
import fr.imag.adele.apam.declarations.CompositeDeclaration;
import fr.imag.adele.apam.declarations.ImplementationDeclaration;
import fr.imag.adele.apam.declarations.InstanceDeclaration;
import fr.imag.adele.apam.declarations.PropertyDefinition;
import fr.imag.adele.apam.declarations.RelationDeclaration;
import fr.imag.adele.apam.declarations.Reporter;
import fr.imag.adele.apam.declarations.SpecificationDeclaration;
import fr.imag.adele.apam.declarations.Reporter.Severity;
import fr.imag.adele.apam.declarations.encoding.Decoder;
import fr.imag.adele.apam.declarations.encoding.ipojo.ComponentParser;
import fr.imag.adele.apam.declarations.instrumentation.InstrumentedClass;
import fr.imag.adele.apam.declarations.instrumentation.UnloadedClassMetadata;
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.declarations.references.components.VersionedReference;
import fr.imag.adele.apam.declarations.references.resources.InterfaceReference;
import fr.imag.adele.apam.declarations.references.resources.MessageReference;
import fr.imag.adele.apam.declarations.references.resources.PackageReference;
import fr.imag.adele.apam.declarations.references.resources.UnknownReference;
import fr.imag.adele.apam.util.Attribute;

/**
* Parses a component declaration encoded in a capability in an OSGi Bundle Repository.
*
* This is the format used by the Apam Component Repository at build time, and the OBR
* manager at runtime.
*
* @author vega
*
*/
public class CapabilityParser implements Decoder<Capability> {

  private Reporter         reporter;
 
  private ComponentDeclaration   component;
  private Map<String, Property>  properties;
 
 
 
  @Override
  public ComponentDeclaration decode(Capability capability, Reporter reporter) {

    this.reporter   = reporter;
    this.component  = null;
 
   
    if (capability != null && ! CST.CAPABILITY_COMPONENT.equals(capability.getName())) {
            info("Capability " + (capability == null ? null : capability.getName()) + " is not an apam component");
            return result();
    }
   
    if( capability.getProperties() == null || capability.getProperties().length == 0) {
            warning("No properties found for the capability : "+capability.getName());
            return result();
        }

    /*
     * Intialiaze the property map
     */
    this.properties = new HashMap<String, Property>();
    for(Property property : capability.getProperties() ) {
      properties.put(property.getName(), property);
    }
         

    /*
     * Create the appropriate component declaration, depending on the kind of component
     */
    String componentName   = property(CST.NAME);
    String componentkind  = property(CST.COMPONENT_TYPE);
           
    info("parsing ACR capability for component : " + componentName + " of type " + componentkind);

    switch(kind(componentkind)) {
      case SPECIFICATION:
              component = new SpecificationDeclaration(componentName);
        break;
      case IMPLEMENTATION:
            if (isDefined(CST.APAM_COMPOSITE) && flag(CST.APAM_COMPOSITE)) {
                 
              SpecificationReference specification             = reference(CST.PROVIDE_SPECIFICATION, ComponentKind.SPECIFICATION);
              String range                         = property(CST.REQUIRE_VERSION);
              VersionedReference<SpecificationDeclaration> specificationVersion  = specification != null ? VersionedReference.range(specification,range) : null;

              ComponentReference<?> main = reference(CST.APAM_MAIN_COMPONENT,ComponentKind.COMPONENT);

              component = new CompositeDeclaration(componentName,specificationVersion,main);
            }
            else {

              SpecificationReference specification            = reference(CST.PROVIDE_SPECIFICATION, ComponentKind.SPECIFICATION);
              String range                         = property(CST.REQUIRE_VERSION);
              VersionedReference<SpecificationDeclaration> specificationVersion  = specification != null ? VersionedReference.range(specification,range) : null;
             
              InstrumentedClass instrumentedClass =  new UnloadedClassMetadata(property(CST.PROVIDE_CLASSNAME));
                component = new AtomicImplementationDeclaration(componentName, specificationVersion, instrumentedClass);
            }
        break;
      case INSTANCE:
              ImplementationReference<ImplementationDeclaration> implementation   = reference(CST.IMPLNAME,ComponentKind.IMPLEMENTATION);
            String range                             = property(CST.REQUIRE_VERSION);
               VersionedReference<ImplementationDeclaration> implementationVersion      = VersionedReference.range(implementation,range);

            component = new InstanceDeclaration(implementationVersion, componentName);
        break;
      default:
    }
   
       
        /*
         * Verify we could create the declaration
         */
        if (component == null) {
          warning("Unknown apam component type : "+componentkind+" for "+componentName);
          return result();
    }

        /*
         * Add predefined properties
         */
        if(isDefined(CST.SINGLETON)) {
          component.setSingleton(flag(CST.SINGLETON));
        }
       
        if(isDefined(CST.SHARED)) {
          component.setShared(flag(CST.SHARED));
        }
       
        if(isDefined(CST.INSTANTIABLE)) {
          component.setInstantiable(flag(CST.INSTANTIABLE));
        }

        if(isDefined(CST.VERSION)) {
            component.getProperties().put(CST.VERSION, property(CST.VERSION));
        }

        // Check the provides interfaces and messages
        if(isDefined(CST.PROVIDE_INTERFACES)) {
            for(String ref : list(CST.PROVIDE_INTERFACES)) {
              component.getProvidedResources().add(new InterfaceReference(ref));
            }
        }
       
        if(isDefined(CST.PROVIDE_MESSAGES)) {
            for(String ref : list(CST.PROVIDE_MESSAGES)) {
              component.getProvidedResources().add(new MessageReference(ref));
            }
        }
       
        // Add encoded properties, definitions and relations

        for (String propertyName : properties.keySet()) {
           
          if (isPropertyDefinition(propertyName)) {
                component.getPropertyDefinitions().add(definition(propertyName));
          }

          if (isRelationDefinition(propertyName)) {
                component.getRelations().add(relation(propertyName));
          }
       
          if (! isPredefinedProperty(propertyName)) {
                component.getProperties().put(propertyName, property(propertyName));
          }
        }
               
        return (result());
  }

  private final boolean isPropertyDefinition(String propertyName) {
      return propertyName.startsWith(CST.DEFINITION_PREFIX);
  }

  private final PropertyDefinition definition(String propertyName) {
      String property = propertyName.substring(CST.DEFINITION_PREFIX.length());
      return new PropertyDefinition(component.getReference(),property,type(propertyName),property(propertyName));
  }


  private final boolean isPredefinedProperty(String propertyName) {
        return   Attribute.isFinalAttribute(propertyName) ||
            Attribute.isBuiltAttribute(propertyName) ||
            !Attribute.isInheritedAttribute(propertyName);
  }
 
  private final boolean isRelationDefinition(String propertyName) {
      return propertyName.startsWith(CST.RELATION_PREFIX);
  }
 
  private final RelationDeclaration relation(String propertyName) {
      String relation = propertyName.substring(CST.RELATION_PREFIX.length());
        return new RelationDeclaration(component.getReference(),relation,reference(propertyName),false);
   
  }
 
  private final ResolvableReference reference(String propertyName) {

    String encodedReference = property(propertyName);

      if (encodedReference.startsWith("{"+ComponentParser.INTERFACE+"}")) {
        encodedReference = encodedReference.substring(("{"+ComponentParser.INTERFACE+"}").length());
        return (!encodedReference.isEmpty()) ? new InterfaceReference(encodedReference) : new UnknownReference(new InterfaceReference("unknown"));
      }
      else if (encodedReference.startsWith("{"+ComponentParser.MESSAGE+"}")) {
        encodedReference = encodedReference.substring(("{"+ComponentParser.MESSAGE+"}").length());
        return (!encodedReference.isEmpty()) ? new MessageReference(encodedReference) : new UnknownReference(new MessageReference("unknown"));
      }
      else if (encodedReference.startsWith("{"+ComponentParser.PACKAGE+"}")) {
        encodedReference = encodedReference.substring(("{"+ComponentParser.PACKAGE+"}").length());
        return new PackageReference(encodedReference);
      }
      else {
        return new ComponentReference<ComponentDeclaration>(encodedReference);
      }
  }
 

    /**
     * Free references to all intermediate objects (to allow reuse of this parser) and
     * returns the final result
     */
  private ComponentDeclaration result() {
        this.properties   = null;
        this.reporter  = null;
       
        ComponentDeclaration result = component;
        this.component    = null;
       
        return result;
  }

  private final String property(String propertyName) {
    Property property = properties.get(propertyName);
    return property != null ? property.getValue() : null;
  }

  private final String type(String propertyName) {
    Property property = properties.get(propertyName);
    return property != null ? property.getType() : null;
  }

  private final boolean isDefined(String propertyName) {
    return properties.containsKey(propertyName);
  }
  
  private final boolean flag(String propertyName) {
    return Boolean.valueOf(property(propertyName));
  }

  /**
   * Get a list of strings
   */
  private static final Pattern SIMPLE_LIST_PATTERN   = Pattern.compile(",");
  private static final Pattern TRIMMED_LIST_PATTERN   = Pattern.compile("\\s*,\\s*");

  private List<String> list(String propertyName) {
    return list(propertyName,true);
  }
 
  private List<String> list(String propertyName, boolean trimmed) {
    Pattern pattern   = trimmed ? TRIMMED_LIST_PATTERN : SIMPLE_LIST_PATTERN;
    String encodedList  = property(propertyName);
    return encodedList != null ? Arrays.asList(pattern.split(delimited(encodedList))) : Collections.<String> emptyList();
  }

  /**
   * Skip all optional leading and ending delimiters for lists
   */
  private String delimited(String encodedList) {
   
    if (encodedList.startsWith("{")) {
      if (encodedList.endsWith("}")) {
        return encodedList.substring(1, encodedList.length() - 1).trim();
      }
      else {
        error("Invalid string. \"}\" missing: " + encodedList);
        return encodedList.substring(1).trim();
      }
    }
   
    return encodedList.trim();
  }
 
  @SuppressWarnings("unchecked")
  private final <T extends ComponentReference<?>> T reference(String propertyName, ComponentKind kind) {
    String component = property(propertyName);
      return component != null ? (T) kind.createReference(component) : null;
  }
 
  private final void error(String message) {
    reporter.report(Severity.ERROR, message);
  }
 
  private final void warning(String message) {
    reporter.report(Severity.WARNING, message);
  }

  private final void info(String message) {
    reporter.report(Severity.INFO, message);
  }

  /**
   * Whether this capability represents an Apam component
   */
  public static boolean isComponent(Capability capability) {
   
    return  capability != null &&
        CST.CAPABILITY_COMPONENT.equals(capability.getName()) &&
        capability.getProperties() != null &&
        capability.getProperties().length> 0 &&
        capability.getPropertiesAsMap().get(CST.NAME) != null &&
        capability.getPropertiesAsMap().get(CST.COMPONENT_TYPE) != null;
  }

  /**
   * The Apam component represented by this capability
   */
  public static ComponentReference<?> getComponent(Capability capability) {
   
    if (! isComponent(capability))
      return null;

    ComponentKind kind  = kind((String) capability.getPropertiesAsMap().get(CST.COMPONENT_TYPE));
      return kind != null ? kind.createReference((String) capability.getPropertiesAsMap().get(CST.NAME)) : null;
  }
 
  /**
   * Convert a component kind from its internal representation
   */
  private static ComponentKind kind(String componentkind) {
   
    if (CST.SPECIFICATION.equals(componentkind)) {
      return ComponentKind.SPECIFICATION;
      }
    else if (CST.IMPLEMENTATION.equals(componentkind)) {
      return ComponentKind.IMPLEMENTATION;
      }
      else if (CST.INSTANCE.equals(componentkind)) {
        return ComponentKind.INSTANCE;
      }
      else {
        return null;
      }
  }
}
TOP

Related Classes of fr.imag.adele.apam.declarations.encoding.capability.CapabilityParser

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.