Editing a system
Now that we have our object tracker defined we need a way to edit objects within the system.
Options@ChemicalSystemApply={Overwrite->True};
ChemicalSystemApply[ChemicalSystem[system_],function_,ID_Integer,OptionsPattern[]]:=
With[{o=system[ID]},
If[OptionValue@Overwrite,
Replace[function[o],
r_?(MatchQ[Head@#,Head@o]&):>(system[ID]=r)
],
function@o
]
];
Note that the way this is defined, the function must return an object of with the same head for the change to be kept.
We can make one further simplification: recalling that when an object is added to the system the system ID is tracked we can add the following definition:
ChemicalSystemApply[function_,h_[ID_Integer,systemID_Integer],ops:OptionsPattern[]]:=ChemicalSystemApply[ChemicalSystem[systemID],function,ID,ops];
ChemicalSystemApply[function_,h_[a_Association],ops:OptionsPattern[]]:=
With[{ID=a["ID"],system=a["System"]},
ChemicalSystemApply[
ChemicalSystem@system,
function,
h[ID,system],
ops
]
];
And then knowing that objects will just be heads on associations the following two functions will be useful
ChemicalSystemGet[h_[a_Association],prop_]:=a[prop];
ChemicalSystemGet[h_[objectID_Integer,systemID_Integer],prop_]:=ChemicalSystemGet[ChemicalSystem[systemID][objectID],prop]
ChemicalSystemSet[h_[a_Association],prop_,val_,function_:Set]:=h@Append[a,Switch[function,Set,(prop->val),SetDelayed,prop:>val]];
ChemicalSystemSet[h_[objectID_Integer,systemID_Integer],prop_,val_,function_:Set]:=ChemicalSystemSet[ChemicalSystem[systemID][objectID],prop,val,function];
ChemicalSystemSet~SetAttributes~HoldAll;
Finally, for working with objects the following interface to set and get attributes will be helpful:
SetChemicalSystemUpValues[sym_Symbol]:=With[{symPattern=sym[_Association|PatternSequence[_Integer,_Integer]]},sym/:HoldPattern[PropertyValue[o:symPattern,property_]]:=ChemicalSystemGet[o,property];
sym/:HoldPattern[(o:symPattern)[property_]]:=PropertyValue[o,property];
sym/:HoldPattern[Set[(o:symPattern)[property_],val_]]:=ChemicalSystemApply[ChemicalSystemSet[#,property,val,Set]&,o];
sym/:HoldPattern[SetDelayed[(o:symPattern)[property_,val_]]]:=ChemicalSystemApply[ChemicalSystemSet[#,property,val,SetDelayed]&,o];
];
ChemicalSystemUpValues~SetAttributes~HoldFirst;