Package fr.imag.adele.apam.util

Source Code of fr.imag.adele.apam.util.Attribute

package fr.imag.adele.apam.util;

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

import org.osgi.framework.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.imag.adele.apam.AttrType;
import fr.imag.adele.apam.CST;

public class Attribute {

  /*
   * ================== Attributes ===================//
   */
  private static Logger logger = LoggerFactory.getLogger(Attribute.class);

  /**
   * Check if the attribute value is valid; if so return the value to put into
   * the object property Map. In the Map, values are String, Integer or
   * Set<String> for all sets. Type can be a singleton "int", "boolean", "float", "version" or
   * "string" or enumeration "v1, v2, v3 ..." or a set of these : "{int}", or
   * "{string}" or enumeration "{v1, v2, v3 ...}"
   *
   * Parameter "value" can be String, Integer, Boolean, Set<Integer> or
   * Set<String>. If the value is String, it is checked and transformed into
   * the Map type. If it is an Object, it is checked and transformed into the
   * Set.
   *
   * Type ca be a substitution, in which case type is prefixed bt "$" : $int,
   * $boolean, .. ${int} ... Value for a substitution must be a string with at
   * least a "$"
   *
   * If the attribute in not declared or the value invalid,return null. If
   * valid, return the Map value (String or int).
   */
  @SuppressWarnings("unchecked")
  public static Object checkAttrType(String attribute, Object value, String typeString) {
    if ((typeString == null) || (value == null) || typeString.isEmpty() || attribute == null || attribute.isEmpty()) {
      logger.error("Invalid property " + attribute + " = " + value + " type=" + typeString);
      return null;
    }

    AttrType aType = splitType(typeString);
    if (aType == null) {
      return null;
    }

    if (value instanceof String) {
      if (Substitute.isSubstitution(value)) {
        return (value);
      }
      // It is not a substitution, with a string as value
      return checkAttrTypeString(attribute, (String) value, aType);
    }

    /*
     * integers. They are stored as Integer if singleton, as Set<String> for
     * sets<String> or Set<Integer>
     */
    if (aType.type == AttrType.INTEGER) { // aType.singletonType.equals
      // ("integer")) {
      if (aType.isSet) {
        // Value MUST be a Set of Integer
        if (!(value instanceof Set<?>)) {
          logger.error("Attribute value " + value + " not an a Set<Integer> for attribute " + attribute);
          return false;
        }
        Set<String> valSetInt = new HashSet<String>();
        try {
          for (Object i : (Set<?>) value) {
            if (i instanceof Integer) {
              valSetInt.add(Integer.toString((Integer) i));
            } else {
              if (i instanceof String) {
                // to be sure it is an integer
                Integer.valueOf((String) i);
                valSetInt.add((String) i);
              }
            }
          }
        } catch (Exception e) {
          logger.error("In attribute value " + value + " is not an Integer Set, for attribute " + attribute);
          return false;
        }
        //TODO
        //return Collections.unmodifiableSet(valSetInt);
        return valSetInt ;
      }
      // A singleton
      if (value instanceof Integer) {
        return value;
      }
      logger.error("Invalid integer value " + value + " for attribute " + attribute);
      return false;
    }
   
    /*
     * doubles. They are stored as Float if singleton, as Set<String> for
     * sets<String> or Set<Float>
     */
    if (aType.type == AttrType.FLOAT) {
      if (aType.isSet) {
        // Value MUST be a Set of Float
        if (!(value instanceof Set<?>)) {
          logger.error("Attribute value " + value + " not an a Set<Float> for attribute " + attribute);
          return false;
        }
        Set<String> valSetFloat = new HashSet<String>();
        try {
          for (Object i : (Set<?>) value) {
            if (i instanceof Float) {
              valSetFloat.add(Float.toString((Float) i));
            } else {
              if (i instanceof String) {
                // to be sure it is an integer
                Float.valueOf((String) i);
                valSetFloat.add((String) i);
              }
            }
          }
        } catch (Exception e) {
          logger.error("In attribute value " + value + " is not an Float Set, for attribute " + attribute);
          return false;
        }
        return valSetFloat ;
      }
      // A singleton
      if (value instanceof Float) {
        return value;
      }
      logger.error("Invalid Float value " + value + " for attribute " + attribute);
      return false;
    }   
   
    if (aType.type == AttrType.VERSION) {
      if (aType.isSet) {
        // Value MUST be a Set of Version
        if (!(value instanceof Set<?>)) {
          logger.error("Attribute value " + value + " not an a Set<Version> for attribute " + attribute);
          return false;
        }
        Set<String> valSetVersion = new HashSet<String>();
        try {
          for (Object i : (Set<?>) value) {
            if (i instanceof Version) {
              valSetVersion.add(i.toString());
            } else {
              if (i instanceof String) {
                // to be sure it is an integer
                Version.parseVersion((String) i);
                valSetVersion.add((String) i);
              }
            }
          }
        } catch (Exception e) {
          logger.error("In attribute value " + value + " is not an Version Set, for attribute " + attribute);
          return false;
        }
        return valSetVersion ;
      }
      // A singleton
      if (value instanceof Version) {
        return value;
      }
      logger.error("Invalid Version value " + value + " for attribute " + attribute);
      return false;
    }     

    /*
     * Booleans
     */
    if (aType.type == AttrType.BOOLEAN) {
      if (aType.isSet) {
        logger.error("Set of booleans are not alowed");
        return null;
      }
      if (value instanceof Boolean) {
        return value;
      }
      logger.error("Invalid value: not a Boolean " + value + " for attribute " + attribute);
      return null;
    }

    /*
     * array of String or array of enumerated. Array of string in all cases
     */
    if (!aType.isSet) {
      logger.error("Invalid value: not a single String " + value + " for attribute " + attribute);
      return null;
    }
    if (!(value instanceof Set)) {
      logger.error("Invalid value: not a Set of String " + value + " for attribute " + attribute);
      return null;
    }

    for (Object i : (Set<?>) value) {
      if (!(i instanceof String)) {
        logger.error("In attribute value " + value + ", " + i.toString() + " is not a String, for attribute " + attribute);
        return false;
      }
    }

    /*
     * String array
     */
    if (aType.type == AttrType.STRING) {
      //TODO
      //return Collections.unmodifiableSet((Set<String>) value);
      return (Set<String>) value ;
    }

    /*
     * It is a set of enumeration Compute all values in type. Check if all
     * values are in type.
     */
    // Set<String> enumType = Util.splitSet(type) ;
    if (aType.enumValues.containsAll((Set<String>) value)) {
      //TODO
      //return Collections.unmodifiableSet((Set<String>) value);
      return (Set<String>) value ;
    } else {
      logger.error("Invalid value " + value + " for attribut " + attribute + ". Expected subset of " + aType.typeString);
      return false;
    }
  };

  /**
   * only string, int, boolean, double and enumerations attributes are accepted.
   * Return the value if it is correct. For "int" returns an Integer object,
   * otherwise it is the string "value" does not work for set of integer,
   * treated as string set. Matching may fail.
   *
   * @param value
   *            : a singleton, or a set "a, b, c, ...."
   * @param type
   *            : a singleton "int", "boolean", "double" or "string" or enumeration
   *            "v1, v2, v3 ..." or a set of these : "{int}", "{boolean}" or
   *            "{string}" or enumeration "{v1, v2, v3 ...}"
   */
  private static Object checkAttrTypeString(String attr, String value, AttrType at) {

    Set<String> values = Collections.unmodifiableSet(Util.splitSet(value));
    if (values.size() > 1 && !at.isSet) {
      logger.error("Values are a set \"" + values + "\" for attribute \"" + attr + "\". while type is singleton: \"" + at.typeString + "\"");
      return null;
    }

    switch (at.type) {
    case AttrType.ENUM:
      if (at.isSet) {
        if (at.enumValues.containsAll(values)) {
          return values;
        }
        logger.error("Invalid attribute value(s) \"" + value + "\" for attribute \"" + attr + "\".  Expected subset of: " + Util.stringSet2String(at.enumValues));
        return null;
      }
      if (at.enumValues.contains(value)) {
        return value;
      }
      logger.error("Invalid attribute value \"" + value + "\" for attribute \"" + attr + "\".  Expected a member of: " + Util.stringSet2String(at.enumValues));
      return null;

    case AttrType.BOOLEAN:
      // if (type.equals("boolean")) {
      try {
        if (!at.isSet) {
          return Boolean.valueOf(value);
        }
        logger.error("Boolean set are not allowed. Attribute \"" + attr);
        return null;
      } catch (Exception e) {
        logger.error("Invalid attribute value \"" + value + "\" for attribute \"" + attr + "\".  Boolean value(s) expected");
        return null;
      }
    case AttrType.INTEGER:
      // if (type.equals("integer")) {
      try {
        if (!at.isSet) {
          return Integer.valueOf(value);
        }
        // unfortunately, match does not recognizes a set of integer.
        // return the list as a string ;
        Set<String> normalizedValues = new HashSet<String>();
        for (String val : values) {
          normalizedValues.add(Integer.toString(Integer.parseInt(val)));
        }
        return normalizedValues;
      } catch (Exception e) {
        logger.error("Invalid attribute value \"" + value + "\" for attribute \"" + attr + "\".  Integer value(s) expected");
        return null;
      }
    case AttrType.FLOAT:
      try {
        if (!at.isSet) {
          return Float.valueOf(value);
        }
        // unfortunately, match does not recognizes a set of float.
        // return the list as a string ;
        Set<String> normalizedValues = new HashSet<String>();
        for (String val : values) {
          normalizedValues.add(Float.toString(Float.parseFloat(val)));
        }
        return normalizedValues;
      } catch (Exception e) {
        logger.error("Invalid attribute value \"" + value + "\" for attribute \"" + attr + "\".  Float value(s) expected");
        return null;
      }     
    case AttrType.VERSION:
      try {
        if (!at.isSet) {
          return Version.parseVersion(value);
        }
        // unfortunately, match does not recognizes a set of version.
        // return the list as a string ;
        Set<String> normalizedValues = new HashSet<String>();
        for (String val : values) {
          normalizedValues.add(val);
        }
        return normalizedValues;
      } catch (Exception e) {
        logger.error("Invalid attribute value \"" + value + "\" for attribute \"" + attr + "\".  Version value(s) expected");
        return null;
      }     
     
    case AttrType.STRING:
      // if (type.equals("string")) {
      // All values are Ok for string.
      return at.isSet ? values : value;
    }

    return null;
  }

  public static boolean isFinalAttribute(String attr) {
    for (String pred : CST.finalAttributes) {
      if (pred.equals(attr)) {
        return true;
      }
    }
    return false;
  }
 
  public static boolean isBuiltAttribute(String attr) {
    // Attributes sets during build are considered final
    for (String pred : CST.buildAttributes) {
      if (pred.equals(attr)) {
        return true;
      }
    }   
    if(attr != null && attr.startsWith(CST.buildAttributePrefix)) {
      return true;
    }
    return false;
  }

  public static boolean isInheritedAttribute(String attr) {
    if (isReservedAttributePrefix(attr) || isBuiltAttribute(attr)) {
      return false;
    }
    for (String pred : CST.notInheritedAttribute) {
      if (pred.equals(attr)) {
        return false;
      }
    }
    return true;
  }

  public static boolean isReservedAttributePrefix(String attr) {
    for (String prefix : CST.reservedPrefix) {
      if (attr.startsWith(prefix)) {
        return true;
      }
    }
    return false;
  }

  public static AttrType splitType(String type) {
    return new AttrType(type);
  }

  /**
   * Check if attribute "attr" is valid when set on object "inst". inst can be
   * an instance, an implementation or a specification. Check if the value is
   * consistent with the type. All predefined attributes are Ok (scope ...)
   * Cannot be a reserved attribute
   */
  public static boolean validAttr(String component, String attr) {

    if (isFinalAttribute(attr)) {
      logger.error("ERROR: in " + component + ", attribute\"" + attr + "\" is final");
      return false;
    }

    if (isReservedAttributePrefix(attr)) {
      logger.error("ERROR: in " + component + ", attribute\"" + attr + "\" is reserved");
      return false;
    }

    return true;
  }

  /**
   *
   * @param type
   * @return
   */
  public static boolean validAttrType(String type) {
    type = type.trim();
    if ((type == null) || (type.isEmpty())) {
      logger.error("Invalid empty property type ");
      return false;
    }

    if (type.charAt(0) == '{') {
      type = type.substring(1, type.length() - 1);
    }

    Set<String> enumVals = Util.splitSet(type);
    if (enumVals == null || enumVals.size() == 0) {
      logger.error("Invalid empty property type ");
      return false;
    }

    if (enumVals.size() > 1) {
      return true;
    }
    type = enumVals.iterator().next();

    if (type == null || !(type.equals("string") || type.equals("int") || type.equals("boolean") || type.equals("float") || type.equals("version") || type.charAt(0) == '{')) {
      logger.error("Invalid type " + type + ". Supported: string, int, boolean, float, version, enumeration; and sets");
      return false;
    }
    return true;
  }

  // cannot be instantiated
  private Attribute() {
  }

}
TOP

Related Classes of fr.imag.adele.apam.util.Attribute

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.