Source/NFX.Erlang/DataAccess/ErlSchemaUtils.cs
/// <summary>
/// Convert an Erlang hierarchical term representing a schema to a Row.
/// </summary>
/// <param name="row">Row to update</param>
/// <param name="data">
///   Data to update row with.
///   The data must be in the form {SchemaName::atom, [{FieldName::atom(), Value}]}.
/// </param>
/// <param name="schema">Alternative schema to use in place of row.Schema</param>
/// <param name="targetName">Name of the target for looking up field attributes</param>
/// <param name="schemaName">Alternative name of the top-most 'SchemaName' atom used in the "data".</param>
/// <param name="knownSchemas">List of known schemas to use when initializing a field a DynamicRow type.</param>
Convert an Erlang hierarchical term representing a schema to a Row.
Convert an Erlang hierarchical term representing a schema to a Row .
public static void Update(this Row row, IErlObject data, Schema schema = null, string targetName = null,
                             string schemaName = null, Registry<Schema> knownSchemas = null)
    {
      if (schema == null)
        schema = row.Schema;
      if (schemaName == null)
        schemaName = schema.Name;
      if (data == null)
        data = new ErlTuple(new ErlAtom(schemaName), new ErlList());
      if (!checkKeyValueTuple(data) || ((ErlTuple)data)[1].TypeOrder != ErlTypeOrder.ErlList)
        throw new ErlDataAccessException(
          StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));
      var dataList = ((ErlTuple)data)[1] as ErlList;
      if (!((ErlTuple)data)[0].ValueAsString.Equals(schemaName))
        throw new ErlDataAccessException(
          StringConsts.ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR.Args(data.ToString(), schema.Name));
      var presentFieldNames = new HashSet<string>();
      foreach (var item in dataList.Where(checkKeyValueTuple).Cast<ErlTuple>())
        presentFieldNames.Add(item[0].ValueAsString);
      ErlList newList = null;
      foreach (var fld in schema.Where(fd => typeof(Row).IsAssignableFrom(fd.Type)))
        if (!presentFieldNames.Contains(fld.Name))
        {
          if (newList == null)
            newList = (ErlList)dataList.Clone();
          newList.Add(new ErlTuple(new ErlAtom(fld.Name), new ErlList()));
        }
      if (newList == null) newList = dataList;
      foreach (var item in newList.Where(checkKeyValueTuple).Cast<ErlTuple>())
      {
        var name  = item[0].ValueAsString;
        var value = item[1];
        var fdef  = schema[name];
        var attr  = fdef[targetName];
        if (!attr.Visible || (attr.Metadata != null && attr.Metadata.Navigate("$readonly|$read-only|$read_only").ValueAsBool()))
          continue;
        if (typeof(Row).IsAssignableFrom(fdef.Type))
        {
          Schema chldSch;
          var chldRow = row[fdef.Order] as Row;
          if (chldRow != null)
            chldSch = chldRow.Schema;
          else
          {
            if (!knownSchemas.TryGetValue(name, out chldSch))
              throw new ErlDataAccessException(
                StringConsts.ERL_DS_SCHEMA_NOT_KNOWN_ERROR.Args(name, data.ToString()));
            chldRow = new DynamicRow(chldSch);
            chldRow.ApplyDefaultFieldValues();
            row[fdef.Order] = chldRow;
          }
          if (value.TypeOrder != ErlTypeOrder.ErlList)
            throw new ErlDataAccessException(
              StringConsts.ERL_DS_SCHEMA_INVALID_VALUE_ERROR.Args(chldSch.Name, value));
          chldRow.Update(item, chldSch, targetName, knownSchemas: knownSchemas);
        }
        else
        {
          var clr = SchemaMap.ErlToClrValue(value, schema, fdef, null, data);
          row.SetFieldValue(fdef, clr);
        }
      }
    }
public static void Update ( this Row row , IErlObject data , Schema schema = null , string targetName = null , string schemaName = null , Registry < Schema > knownSchemas = null ) { if ( schema == null ) schema = row . Schema ; if ( schemaName == null ) schemaName = schema . Name ; if ( data == null ) data = new ErlTuple ( new ErlAtom ( schemaName ) , new ErlList ( ) ) ; if ( ! checkKeyValueTuple ( data ) || ( ( ErlTuple ) data ) [ 1 ] . TypeOrder != ErlTypeOrder . ErlList ) throw new ErlDataAccessException ( StringConsts . ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR . Args ( data . ToString ( ) , schema . Name ) ) ; var dataList = ( ( ErlTuple ) data ) [ 1 ] as ErlList ; if ( ! ( ( ErlTuple ) data ) [ 0 ] . ValueAsString . Equals ( schemaName ) ) throw new ErlDataAccessException ( StringConsts . ERL_DS_CRUD_RESP_SCH_MISMATCH_ERROR . Args ( data . ToString ( ) , schema . Name ) ) ; var presentFieldNames = new HashSet < string > ( ) ; foreach ( var item in dataList . Where ( checkKeyValueTuple ) . Cast < ErlTuple > ( ) ) presentFieldNames . Add ( item [ 0 ] . ValueAsString ) ; ErlList newList = null ; foreach ( var fld in schema . Where ( fd => typeof ( Row ) . IsAssignableFrom ( fd . Type ) ) ) if ( ! presentFieldNames . Contains ( fld . Name ) ) { if ( newList == null ) newList = ( ErlList ) dataList . Clone ( ) ; newList . Add ( new ErlTuple ( new ErlAtom ( fld . Name ) , new ErlList ( ) ) ) ; } if ( newList == null ) newList = dataList ; foreach ( var item in newList . Where ( checkKeyValueTuple ) . Cast < ErlTuple > ( ) ) { var name = item [ 0 ] . ValueAsString ; var value = item [ 1 ] ; var fdef = schema [ name ] ; var attr = fdef [ targetName ] ; if ( ! attr . Visible || ( attr . Metadata != null && attr . Metadata . Navigate ( " " ) . ValueAsBool ( ) ) ) continue ; if ( typeof ( Row ) . IsAssignableFrom ( fdef . Type ) ) { Schema chldSch ; var chldRow = row [ fdef . Order ] as Row ; if ( chldRow != null ) chldSch = chldRow . Schema ; else { if ( ! knownSchemas . TryGetValue ( name , out chldSch ) ) throw new ErlDataAccessException ( StringConsts . ERL_DS_SCHEMA_NOT_KNOWN_ERROR . Args ( name , data . ToString ( ) ) ) ; chldRow = new DynamicRow ( chldSch ) ; chldRow . ApplyDefaultFieldValues ( ) ; row [ fdef . Order ] = chldRow ; } if ( value . TypeOrder != ErlTypeOrder . ErlList ) throw new ErlDataAccessException ( StringConsts . ERL_DS_SCHEMA_INVALID_VALUE_ERROR . Args ( chldSch . Name , value ) ) ; chldRow . Update ( item , chldSch , targetName , knownSchemas : knownSchemas ) ; } else { var clr = SchemaMap . ErlToClrValue ( value , schema , fdef , null , data ) ; row . SetFieldValue ( fdef , clr ) ; } } }
Convert an Erlang hierarchical term representing a schema to a Row.
Convert an Erlang hierarchical term representing a schema to a Row .
// Input data must be in the form: {SchemaName::atom(), [{FieldName::atom(), Value}]} // where Value can be any primitive value or a hierarchical value with another Row type. // Make sure that the first element of the tuple matches the schema name // Contains a set of field names that are present in configuration // Add: {FieldName::atom(), []} // If no new items were added to the list use current list: // If this field is defined in the schema as a Row type, then we need to descend into the // value's hierarchical structure and treat it as a nested row // Get the row associated // If the row has a field of Row type initialized, use its Schema value. // Otherwise lookup the schema from the given registry // Construct the field's value as dynmiac row of the looked up schema type // Recursively update the field's value from given data by using the field's schema: // This is a primitive value type
Row
this
data
IErlObject
Data to update row with.
The data must be in the form {SchemaName::atom, [{FieldName::atom(), Value}]}.
Data to update row with . The data must be in the form { SchemaName :: atom [ { FieldName :: atom () Value } ] } .
schema
Schema
Alternative schema to use in place of row.Schema
Alternative schema to use in place of row . Schema
targetName
string
Name of the target for looking up field attributes
Name of the target for looking up field attributes
schemaName
string
Alternative name of the top-most 'SchemaName' atom used in the "data".
Alternative name of the top - most ' SchemaName ' atom used in the " data " .
knownSchemas
Registry<Schema>
List of known schemas to use when initializing a field a DynamicRow type.
List of known schemas to use when initializing a field a DynamicRow type .
row
Row to update
Row to update