evomimic / map-descriptors2

0 stars 0 forks source link

Create a New HolonDescriptor via Builder #19

Open evomimic opened 1 year ago

evomimic commented 1 year ago

The HolonDescriptor Builder allows fine-grained update operations to be staged prior to committing them to the HolonDescriptor in the backing store. See UC: Create Holon Type and the Metaspace Design Spec for more details.

Eventually, the Builder will offer three creation options (new, clone, derive). This story is only intended to deliver the 'new' option.

Design Sketch

Holon Descriptor Builder Data Structure Definitions

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
pub struct HolonDescriptorBuilder {
    pub header: Option<TypeHeader>,
    pub properties: Option<PropertyDescriptorMap>,
    pub builder_state: tbd
}

Property Descriptor Builder Data Structure Definitions

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
pub struct PropertyDescriptorBuilder {
    pub header: Option<TypeHeaderBuilder>,
    pub details: Option<PropertyDescriptorDetailsBuilder>,
}

pub struct PropertyDescriptorUsageBuilder {
    pub description: Option<String>,
    pub descriptor: Option<PropertyDescriptor>,
}

pub struct PropertyDescriptorMap {
    pub properties: Option<BTreeMap<String, PropertyDescriptorUsage>>,
}

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum PropertyDescriptorDetailsBuilder {
    Boolean(BooleanDescriptorBuilder),
    Composite(CompositeDescriptorBuilder),
    //Enum(EnumDescriptorBuilder),
    Integer(IntegerDescriptorBuilder),
    String(StringDescriptorBuilder),
    ValueCollection(ValueCollectionDescriptorBuilder), // can only contain collections of PropertyTypes (not Holons)
}

#[hdk_entry_helper]
#[derive(new, Default, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct BooleanDescriptorBuilder {
    pub is_fuzzy: Option<bool>,  // if true, this property has FuzzyBoolean value, otherwise just true or false
}

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct CompositeDescriptorBuilder {
    pub properties: Option<PropertyDescriptorMapBuilder>,
}

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct IntegerDescriptorBuilder {
    pub format: Option<IntegerFormat>,
    pub min_value: Option<i64>,
    pub max_value: Option<i64>,
}
#[hdk_entry_helper]
#[derive(Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum IntegerFormat {
    I8(),
    I16(),
    I32(),
    I64(),
    // I128(),
    U8(),
    U16(),
    U32(),
    U64(),
    // U128(),
}

#[hdk_entry_helper]
#[derive(new, Default, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct StringDescriptorBuilder {
    pub min_length: Option<u32>,
    pub max_length: Option<u32>,
    //pattern: Option<String>,
}

// This is just a first cut at ValueCollectionDescriptor
// It identifies the kinds of items the collection contains via a string

#[hdk_entry_helper]
#[derive(new, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ValueCollectionDescriptorBuilder {
    pub contains_items_of_type: Option<HolonReference>, 
    pub min_items: Option<u32>,
    pub max_items: Option<u32>,
    pub unique_items: Option<bool>, // true means duplicate items are not allowed
    pub is_ordered: Option<bool>,   // if items have an intrinsic order
}

Holon Descriptor Builder Creational Operations:

This function creates a new HolonDescriptorBuilder as an object to incrementally stage updates. It is up to the caller to decide how much information to supply to this function -- the function itself accepts completely empty to fully populated parameters to be provided. Invoking commit on the builder will request creation of a new HolonDescriptor (with no prior versions) from the Builder and persisting it in the backing store.

new_holon_descriptor_builder(
     type_name: Option<String>,
     description: Option<String>,
    properties: Option<PropertyDescriptorMap>,
) -> ExternResult<HolonDescriptorBuilder> 

add_string_property_descriptor_builder( map: PropertyDescriptorMap // the property map that will contain the new descriptor type_name: String, description: String, is_dependent: bool, min_length: u32, max_length: u32, ) -> ExternResult<PropertyDescriptorMap>

This function creates a new (empty) PropertyDescriptorBuilder as an object to incrementally stage updates. At this stage, the BaseType of the PropertyDescriptor must be specified before updating its details. Once the Builder is fully populated (i.e., the human agent has specified values for all the meta-properties of the PropertyDescriptor, the PropertyDescriptorBuilder can then be:

  1. committed to persist this propertyType as an independent (a.k.a., shared propertyType)
  2. AND/OR added to a PropertyMap within a HolonDescriptorBuilder.

getStringPropertyDescriptorBuilder(PropertyDescriptorBuilder)-> ExternResult

newProperty(
     within_builder : HolonDescriptorBuilder, 
     at_path : PropertyPath,
) ->  ExternResult<HolonDescriptorBuilder>

Creates a new (empty) PropertyDescriptorBuilder. At this point, the next step should be to select the BaseType for the property descriptor, so that the appropriate details can be captured.

addPropertyDescriptor(within_builder: HolonDescriptorBuilder, at_path: PropertyPath, ) -> ExternResult<HolonDescriptorBuilder>

Adds a new (empty) String property to the PropertyMap found via the specified at_path. The PropertyDescrib

pub fn new_composite_descriptor( type_name: String, description: String, is_dependent: bool, properties: PropertyDescriptorMap, ) -> Result<PropertyDescriptor, DescriptorsError> { let details = PropertyDescriptorDetails::Composite(CompositeDescriptor::new(properties));

let desc = new_property_descriptor(
    type_name,
    description,
    BaseType::Composite,
    is_dependent,
    details,
)?;
Ok(desc)

}

pub fn new_string_descriptor( type_name: String, description: String, is_dependent: bool, min_length: u32, max_length: u32, ) -> Result<PropertyDescriptor, DescriptorsError> { let details = PropertyDescriptorDetails::String(StringDescriptor::new(min_length, max_length)); let desc = new_property_descriptor( type_name, description, BaseType::String, is_dependent, details, )?; Ok(desc) }

pub fn new_integer_descriptor( type_name: String, description: String, is_dependent: bool, format: IntegerFormat, min_value: i64, max_value: i64, ) -> Result<PropertyDescriptor, DescriptorsError> { let details = PropertyDescriptorDetails::Integer(IntegerDescriptor::new(format, min_value, max_value)); let desc = new_property_descriptor( type_name, description, BaseType::Integer, is_dependent, details, )?; Ok(desc) } pub fn new_boolean_descriptor( type_name: String, description: String, is_dependent: bool, is_fuzzy: bool, ) -> Result<PropertyDescriptor, DescriptorsError> { let details = PropertyDescriptorDetails::Boolean(BooleanDescriptor::new(is_fuzzy)); let desc = new_property_descriptor( type_name, description, BaseType::Boolean, is_dependent, details, )?; Ok(desc) }

removeProperties(
     property_map: PropertyDescriptorMap,
     properties_to_remove: Vec<String>, // the list of property_names to remove from PropertyMap
)-> ExternResult<PropertyMap>

Marks an existing property as removed from a PropertyMap and returns the updated PropertyMap

FUTURE:

makeIdentifying -- adds an existing property to the list of identfying_properties -- returns Some/Error enum.

makeNotIdentifying -- removes a property from the list of identifying properties -- returns Some/Error enum.

evomimic commented 1 year ago

This issue is on hold pending completion of Issue #27