Esempio n. 1
0
def add_child_typeattr(parent_id, child_template_id, **kwargs):
    """
        Add template and a type and typeattrs.
    """

    #does this child already exist in this template?
    existing_child_typeattr = db.DBSession.query(TypeAttr).join(
        TemplateType).filter(TypeAttr.parent_id == parent_id).filter(
            TemplateType.template_id == child_template_id).first()

    if existing_child_typeattr is not None:
        return existing_child_typeattr

    parent_typeattr = db.DBSession.query(TypeAttr)\
            .filter(TypeAttr.id == parent_id).one()

    child_type = add_child_templatetype(parent_typeattr.type_id,
                                        child_template_id)

    child_typeattr_i = TypeAttr()
    child_typeattr_i.attr_id = parent_typeattr.attr_id
    child_typeattr_i.type_id = child_type.id
    child_typeattr_i.parent_id = parent_id

    db.DBSession.add(child_typeattr_i)

    db.DBSession.flush()

    return child_typeattr_i
Esempio n. 2
0
def _set_typeattr(typeattr, existing_ta=None, check_dimensions=True):
    """
        Add or update a type attribute.
        If an existing type attribute is provided, then update.

        Checks are performed to ensure that the dimension provided on the
        type attr (not updateable) is the same as that on the referring attribute.
        The unit provided (stored on tattr) must conform to the dimension stored
        on the referring attribute (stored on tattr).

        This is done so that multiple templates can all use the same attribute,
        but specify different units.

        If no attr_id is provided, but an attr_name and dimension are provided,
        then a new attribute can be created (or retrieved) and used. I.e., no
        attribute ID must be specified if attr_name and dimension are specified.

        ***WARNING***
        Setting ID to null means a new type attribute (and even a new attr)
        may be added, None are removed or replaced. To remove other type attrs, do it
        manually using delete_typeattr
    """
    if existing_ta is None:

        #check for an existing TA
        check_existing_ta = None
        if typeattr.attr_id and typeattr.type_id:
            check_existing_ta = db.DBSession.query(TypeAttr)\
                .filter(TypeAttr.attr_id == typeattr.attr_id, TypeAttr.type_id == typeattr.type_id).first()

        #There's already a TA with this attr_id in this type
        if check_existing_ta is not None:
            ta = check_existing_ta
        else:
            ta = TypeAttr(attr_id=typeattr.attr_id)
            ## default new type attrs to 'active'.
            ##This has replaced the database default because for child typeattrs,
            ##we need the status to be NULL so it can inherit from its parent
            ta.status = 'A'
    else:
        if typeattr.id is not None:
            ta = db.DBSession.query(TypeAttr).filter(
                TypeAttr.id == typeattr.id).one()
        else:
            ta = existing_ta

    ta.attr_id = typeattr.attr_id
    ta.unit_id = typeattr.unit_id
    ta.type_id = typeattr.type_id
    ta.data_type = typeattr.data_type
    ta.status = typeattr.status if typeattr.status is not None else 'A'

    if hasattr(
            typeattr,
            'default_dataset_id') and typeattr.default_dataset_id is not None:
        ta.default_dataset_id = typeattr.default_dataset_id

    ta.description = typeattr.description

    ta.properties = typeattr.get_properties()

    #support legacy use of 'is_var' instead of 'attr_is_var'
    if hasattr(typeattr, 'is_var') and typeattr.is_var is not None:
        typeattr.attr_is_var = typeattr.is_var

    ta.attr_is_var = typeattr.attr_is_var if typeattr.attr_is_var is not None else 'N'

    ta.data_restriction = _parse_data_restriction(typeattr.data_restriction)

    if typeattr.unit_id is None or typeattr.unit_id == '':
        # All right. Check passed
        ta.unit_id = None
        pass
    else:
        unit = units.get_unit(typeattr.unit_id)
        dimension = units.get_dimension(unit.dimension_id)
        if typeattr.attr_id is not None and typeattr.attr_id > 0 and check_dimensions:
            # Getting the passed attribute, so we need to check consistency
            # between attr dimension id and typeattr dimension id
            attr = db.DBSession.query(Attr).filter(
                Attr.id == ta.attr_id).first()
            if attr is not None and attr.dimension_id is not None and\
               attr.dimension_id != dimension.id or \
               attr is not None and attr.dimension_id is None:

                attr_dimension = units.get_dimension(attr.dimension_id)
                # In this case there is an inconsistency between
                # attr.dimension_id and typeattr.unit_id
                raise HydraError(
                    "Unit mismatch between type and attirbute." +
                    f"Type attribute for {attr.name} specifies " +
                    f"unit {unit.name}, dimension {dimension.name}." +
                    f"The attribute specifies a dimension of {attr_dimension.name}"
                    + "Cannot set a unit on a type attribute which " +
                    "does not match its attribute.")
        elif typeattr.attr_id is None and typeattr.name is not None:
            # Getting/creating the attribute by typeattr dimension id and typeattr name
            # In this case the dimension_id "null"/"not null" status is ininfluent
            attr = get_attr_by_name_and_dimension(typeattr.name, dimension.id)

            ta.attr_id = attr.id
            ta.attr = attr

    if check_dimensions:
        check_dimension(ta)

    if existing_ta is None:
        log.debug("Adding ta to DB")
        db.DBSession.add(ta)

    if not hasattr(ta, 'attr'):
        attr = db.DBSession.query(Attr).filter(Attr.id == ta.attr_id).one()
        ta.attr = attr

    return ta
Esempio n. 3
0
def parse_json_typeattr(type_i,
                        typeattr_j,
                        attribute_j,
                        default_dataset_j,
                        user_id=None):
    dimension_i = None
    if attribute_j.dimension_id is not None:
        # The dimension_id of the attribute is not None
        dimension_i = units.get_dimension(attribute_j.dimension_id)
    elif attribute_j.dimension is not None:
        # The dimension name of the attribute is not None
        dimension_name = attribute_j.dimension.strip()
        if dimension_name.lower() in ('dimensionless', ''):
            dimension_name = 'dimensionless'
        dimension_i = units.get_dimension_by_name(dimension_name.strip())
    elif attribute_j.unit_id is not None:
        # The unit_id of the attribute is not None
        dimension_i = units.get_dimension_by_unit_id(attribute_j.unit_id)
    elif attribute_j.unit not in ('', None):
        # The unit of the attribute is not None
        attribute_unit_id = units.get_unit_by_abbreviation(attribute_j.unit).id
        attribute_j.unit_id = attribute_unit_id
        dimension_i = units.get_dimension_by_unit_id(attribute_j.unit_id)

    attribute_name = attribute_j.name.strip()

    if dimension_i is None:
        # In this case we must get the attr with dimension id not set
        attr_i = get_attr_by_name_and_dimension(attribute_name, None)
    else:
        attr_i = get_attr_by_name_and_dimension(attribute_name, dimension_i.id)

    #Get an ID for the attribute
    db.DBSession.flush()

    for ta in type_i.typeattrs:
        if ta.attr_id == attr_i.id:
            typeattr_i = ta
            break
    else:
        typeattr_i = TypeAttr()
        log.debug("Creating type attr: type_id=%s, attr_id=%s", type_i.id,
                  attr_i.id)
        typeattr_i.type_id = type_i.id
        typeattr_i.attr_id = attr_i.id
        typeattr_i.attr_is_var = typeattr_j.attr_is_var
        typeattr_i.attr = attr_i
        typeattr_i.status = 'A'
        type_i.typeattrs.append(typeattr_i)
        db.DBSession.add(typeattr_i)

    unit_id = None
    if attribute_j.unit_id is not None:
        typeattr_i.unit_id = typeattr_j.unit_id

    check_dimension(typeattr_i)

    if typeattr_j.description is not None:
        typeattr_i.description = typeattr_j.description

    if typeattr_j.properties is not None:
        if isinstance(typeattr_j.properties, dict):
            typeattr_i.properties = json.dumps(typeattr_j.properties)
        else:
            typeattr_i.properties = typeattr_j.properties

    if typeattr_j.is_var is not None:
        typeattr_i.attr_is_var = typeattr_j.is_var

    if typeattr_j.data_type is not None:
        typeattr_i.data_type = typeattr_j.data_type

    if default_dataset_j is not None:
        default = default_dataset_j

        unit = default.unit
        unit_id = None
        if unit not in (None, ''):
            unit_id = units.get_unit_by_abbreviation(unit).id

        if unit_id is None and typeattr_i.unit_id is not None:
            unit_id = typeattr_i.unit_id

        if unit_id is not None:
            check_dimension(typeattr_i, unit_id)

        if unit_id is not None and typeattr_i.unit_id is not None:
            if unit_id != typeattr_i.unit_id:
                raise HydraError(
                    "Default value has a unit of %s but the attribute"
                    " says the unit should be: %s" %
                    (typeattr_i.unit_id, unit_id))

        val = default.value

        data_type = default.type
        name = default.name if default.name not in (
            None, '') else "%s Default" % attr_i.name

        dataset_i = add_dataset(data_type,
                                val,
                                unit_id,
                                name=name,
                                user_id=user_id)
        typeattr_i.default_dataset_id = dataset_i.id

    if typeattr_j.restriction is not None or typeattr_j.data_restriction is not None:
        restriction = typeattr_j.restriction if typeattr_j.restriction is not None else typeattr_j.data_restriction
        if isinstance(restriction, dict):
            typeattr_i.data_restriction = json.dumps(restriction)
        else:
            typeattr_i.data_restriction = restriction
    else:
        typeattr_i.data_restriction = None

    return typeattr_i
Esempio n. 4
0
def _parse_xml_typeattr(type_i, attribute, user_id=None):
    """
        convert a typeattr etree element and turn it into a hydra type attr
    """

    attr = _parse_xml_attribute(attribute)

    for ta in type_i.typeattrs:
        if ta.attr_id == attr.id:
            # Find the TypeAttr
            typeattr_i = ta
            break
    else:
        # Creating a new TypeAttr
        typeattr_i = TypeAttr()
        log.debug("Creating type attr: type_id=%s, attr_id=%s", type_i.id,
                  attr.id)
        typeattr_i.type_id = type_i.id
        typeattr_i.attr_id = attr.id
        type_i.typeattrs.append(typeattr_i)
        db.DBSession.add(typeattr_i)

    typeattr_unit_id = None
    if attribute.find('unit') is not None:
        # Found the unit as child at first level
        unit = attribute.find('unit').text
        if unit not in ('', None):
            typeattr_unit_id = units.get_unit_by_abbreviation(unit).id

    if typeattr_unit_id is not None:
        typeattr_i.unit_id = typeattr_unit_id

    check_dimension(typeattr_i)

    if attribute.find('description') is not None:
        typeattr_i.description = attribute.find('description').text

    if attribute.find('properties') is not None:
        properties_string = get_etree_layout_as_dict(
            attribute.find('properties'))
        typeattr_i.properties = str(properties_string)

    if attribute.find('is_var') is not None:
        typeattr_i.attr_is_var = attribute.find('is_var').text
    if attribute.find('data_type') is not None:
        typeattr_i.data_type = attribute.find('data_type').text

    # Analyzing the "default" node
    if attribute.find('default') is not None:
        default = attribute.find('default')

        dataset_unit_id = None
        if default.find('unit') is not None:
            dataset_unit = default.find('unit').text
            if dataset_unit not in ('', None):
                dataset_unit_id = units.get_unit_by_abbreviation(
                    dataset_unit).id

        if dataset_unit_id is None and typeattr_i.unit_id is not None:
            dataset_unit = typeattr_i.unit_id

        if dataset_unit_id is not None and typeattr_i.unit_id is not None:
            if dataset_unit_id != typeattr_i.unit_id:
                raise HydraError(
                    f"Default value has a unit of {typeattr_i.unit_id}" +
                    "but the attribute" +
                    f" says the unit should be: {dataset_unit_id}")

        val = default.find('value').text
        try:
            Decimal(val)
            data_type = 'scalar'
        except:
            data_type = 'descriptor'

        dataset = add_dataset(data_type,
                              val,
                              dataset_unit_id,
                              name="%s Default" % attr.name,
                              user_id=user_id)

        typeattr_i.default_dataset_id = dataset.id

    if attribute.find('restrictions') is not None:
        restriction = str(
            dataset_util.get_restriction_as_dict(
                attribute.find('restrictions')))
        typeattr_i.data_restriction = restriction
    else:
        typeattr_i.data_restriction = None

    return typeattr_i