2
0
mirror of https://github.com/esiur/esiur-dart.git synced 2025-06-27 14:53:11 +00:00

null-safety

This commit is contained in:
2021-07-24 13:12:43 +03:00
parent 6be04c39ed
commit 614c6853e3
48 changed files with 3022 additions and 3320 deletions

View File

@ -1,7 +1,7 @@
class FactoryEntry {
final Type type;
final Function() instanceCreator;
final Function() arrayCreator;
final Function instanceCreator;
final Function arrayCreator;
FactoryEntry(this.type, this.instanceCreator, this.arrayCreator);
}

View File

@ -33,7 +33,7 @@ import 'Instance.dart';
abstract class IResource extends IDestructible {
AsyncReply<bool> trigger(ResourceTrigger trigger);
Instance instance;
Instance? instance;
invoke(String name, List arguments);
setProperty(String name, value);

View File

@ -28,18 +28,20 @@ import '../Data/KeyList.dart';
import './Template/PropertyTemplate.dart';
import '../Data/PropertyValue.dart';
// old
// old
// abstract class IStore extends IResource
// new
abstract class IStore implements IResource
{
AsyncReply<IResource> get(String path);
AsyncReply<IResource> retrieve(int iid);
AsyncReply<bool> put(IResource resource);
String link(IResource resource);
bool record(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
bool modify(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
bool remove(IResource resource);
abstract class IStore implements IResource {
AsyncReply<IResource?> get(String path);
AsyncReply<IResource?> retrieve(int iid);
AsyncReply<bool> put(IResource resource);
String? link(IResource resource);
bool record(IResource resource, String propertyName, dynamic value, int age,
DateTime dateTime);
bool modify(IResource resource, String propertyName, dynamic value, int age,
DateTime dateTime);
bool remove(IResource resource);
AsyncReply<KeyList<PropertyTemplate, List<PropertyValue>>> getRecord(IResource resource, DateTime fromDate, DateTime toDate);
AsyncReply<KeyList<PropertyTemplate, List<PropertyValue>>?> getRecord(
IResource resource, DateTime fromDate, DateTime toDate);
}

View File

@ -21,123 +21,97 @@ import './Template/MemberTemplate.dart';
import '../Data/PropertyValue.dart';
import 'Warehouse.dart';
class Instance extends IEventHandler
{
String _name;
class Instance extends IEventHandler {
String _name;
AutoList<IResource, Instance> _children;
IResource _resource;
IStore _store;
AutoList<IResource, Instance> _parents;
//bool inherit;
TypeTemplate _template;
late AutoList<IResource, Instance> _children;
IResource _resource;
IStore? _store;
late AutoList<IResource, Instance> _parents;
//bool inherit;
late TypeTemplate _template;
AutoList<IPermissionsManager, Instance> _managers;
late AutoList<IPermissionsManager, Instance> _managers;
late KeyList<String, dynamic> _attributes;
KeyList<String, dynamic> _attributes;
List<int> _ages = <int>[];
List<DateTime> _modificationDates = <DateTime>[];
int _instanceAge;
DateTime? _instanceModificationDate;
List<int> _ages = new List<int>();
List<DateTime> _modificationDates = new List<DateTime>();
int _instanceAge;
DateTime _instanceModificationDate;
int _id;
int _id;
/// <summary>
/// Instance attributes are custom properties associated with the instance, a place to store information by IStore.
/// </summary>
KeyList<String, dynamic> get attributes => _attributes;
@override
String toString() => _name + " (" + (link ?? '') + ")";
/// <summary>
/// Instance attributes are custom properties associated with the instance, a place to store information by IStore.
/// </summary>
KeyList<String, dynamic> get attributes => _attributes;
@override
String toString() => _name + " (" + link + ")";
bool removeAttributes([List<String> attributes = null])
{
if (attributes == null)
this._attributes.clear();
else
{
for (var attr in attributes)
this.attributes.remove(attr);
}
return true;
bool removeAttributes([List<String>? attributes = null]) {
if (attributes == null)
this._attributes.clear();
else {
for (var attr in attributes) this.attributes.remove(attr);
}
Structure getAttributes([List<String> attributes = null])
{
var st = new Structure();
return true;
}
if (attributes == null)
{
var clone = this.attributes.keys.toList();
clone.add("managers");
attributes = clone.toList();
}
Structure getAttributes([List<String>? attributes = null]) {
var st = new Structure();
for(var attr in attributes)
{
if (attr == "name")
st["name"] = _name;
else if (attr == "managers")
{
var mngrs = new List<Structure>();
for (var i = 0; i < _managers.length; i++)
{
var mst = new Structure();
mst["type"] = _managers[i].runtimeType;
mst["settings"] = _managers[i].settings;
mngrs.add(mst);
}
st["managers"] = mngrs;
}
else if (attr == "parents")
{
st["parents"] = _parents.toList();
}
else if (attr == "children")
{
st["children"] = _children.toList();
}
else if (attr == "childrenCount")
{
st["childrenCount"] = _children.count;
}
else if (attr == "type")
{
st["type"] = resource.runtimeType;
}
else
st[attr] = _attributes[attr];
}
return st;
if (attributes == null) {
var clone = this.attributes.keys.toList();
clone.add("managers");
attributes = clone.toList();
}
bool setAttributes(Structure attributes, [bool clearAttributes = false])
{
try
{
for (var attr in attributes) {
if (attr == "name")
st["name"] = _name;
else if (attr == "managers") {
var mngrs = <Structure>[];
if (clearAttributes)
_attributes.clear();
for (var i = 0; i < _managers.length; i++) {
var mst = new Structure();
mst["type"] = _managers[i].runtimeType;
mst["settings"] = _managers[i].settings;
for (var attrKey in attributes.keys)
if (attrKey == "name")
_name = attributes[attrKey];
else if (attrKey == "managers")
{
_managers.clear();
mngrs.add(mst);
}
var mngrs = attributes[attrKey] as List;
// this is not implemented now, Flutter doesn't support mirrors, needs a workaround @ Warehouse.registerManager
/*
st["managers"] = mngrs;
} else if (attr == "parents") {
st["parents"] = _parents.toList();
} else if (attr == "children") {
st["children"] = _children.toList();
} else if (attr == "childrenCount") {
st["childrenCount"] = _children.count;
} else if (attr == "type") {
st["type"] = resource.runtimeType;
} else
st[attr] = _attributes[attr];
}
return st;
}
bool setAttributes(Structure attributes, [bool clearAttributes = false]) {
try {
if (clearAttributes) _attributes.clear();
for (var attrKey in attributes.keys)
if (attrKey == "name")
_name = attributes[attrKey] as String;
else if (attrKey == "managers") {
_managers.clear();
var mngrs = attributes[attrKey] as List;
// this is not implemented now, Flutter doesn't support mirrors, needs a workaround @ Warehouse.registerManager
/*
for (var mngr in mngrs)
{
var m = mngr as Structure;
@ -153,22 +127,17 @@ class Instance extends IEventHandler
return false;
}
*/
}
else
{
_attributes[attrKey] = attributes[attrKey];
}
} else {
_attributes[attrKey] = attributes[attrKey];
}
catch(ex)
{
return false;
}
return true;
} catch (ex) {
return false;
}
/*
return true;
}
/*
public Structure GetAttributes()
{
var st = new Structure();
@ -192,73 +161,67 @@ class Instance extends IEventHandler
return st;
}*/
/// <summary>
/// Get the age of a given property index.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Age.</returns>
int getAge(int index)
{
if (index < _ages.length)
return _ages[index];
else
return 0;
}
/// <summary>
/// Get the age of a given property index.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <returns>Age.</returns>
int getAge(int index) {
if (index < _ages.length)
return _ages[index];
else
return 0;
}
/// <summary>
/// Set the age of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Age.</param>
void setAge(int index, int value)
{
if (index < _ages.length)
{
_ages[index] = value;
if (value > _instanceAge)
_instanceAge = value;
}
/// <summary>
/// Set the age of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Age.</param>
void setAge(int index, int value) {
if (index < _ages.length) {
_ages[index] = value;
if (value > _instanceAge) _instanceAge = value;
}
}
/// <summary>
/// Set the modification date of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Modification date.</param>
void setModificationDate(int index, DateTime value)
{
if (index < _modificationDates.length)
{
_modificationDates[index] = value;
if (_instanceModificationDate == null || value.millisecondsSinceEpoch > _instanceModificationDate.millisecondsSinceEpoch)
_instanceModificationDate = value;
}
/// <summary>
/// Set the modification date of a property.
/// </summary>
/// <param name="index">Zero-based property index.</param>
/// <param name="value">Modification date.</param>
void setModificationDate(int index, DateTime value) {
if (index < _modificationDates.length) {
_modificationDates[index] = value;
if (_instanceModificationDate == null ||
value.millisecondsSinceEpoch >
(_instanceModificationDate as DateTime).millisecondsSinceEpoch)
_instanceModificationDate = value;
}
}
/// <summary>
/// Get modification date of a specific property.
/// </summary>
/// <param name="index">Zero-based property index</param>
/// <returns>Modification date.</returns>
DateTime getModificationDate(int index)
{
if (index < _modificationDates.length)
return _modificationDates[index];
else
return new DateTime(0);
}
/// <summary>
/// Get modification date of a specific property.
/// </summary>
/// <param name="index">Zero-based property index</param>
/// <returns>Modification date.</returns>
DateTime getModificationDate(int index) {
if (index < _modificationDates.length)
return _modificationDates[index];
else
return new DateTime(0);
}
/// <summary>
/// Load property value (used by stores)
/// </summary>
/// <param name="name">Property name</param>
/// <param name="age">Property age</param>
/// <param name="value">Property value</param>
/// <returns></returns>
bool loadProperty(String name, int age, DateTime modificationDate, dynamic value)
{
/*
/// <summary>
/// Load property value (used by stores)
/// </summary>
/// <param name="name">Property name</param>
/// <param name="age">Property age</param>
/// <param name="value">Property value</param>
/// <returns></returns>
bool loadProperty(
String name, int age, DateTime modificationDate, dynamic value) {
/*
var pt = _template.getPropertyTemplate(name);
if (pt == null)
@ -281,64 +244,58 @@ class Instance extends IEventHandler
setModificationDate(pt.index, modificationDate);
*/
return true;
return true;
}
/// <summary>
/// Age of the instance, incremented by 1 in every modification.
/// </summary>
int get age => _instanceAge;
// this must be internal
set age(value) => _instanceAge = value;
/// <summary>
/// Last modification date.
/// </summary>
DateTime? get modificationDate => _instanceModificationDate;
/// <summary>
/// Instance Id.
/// </summary>
int get id => _id;
/// <summary>
/// Import properties from bytes array.
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
bool deserialize(List<PropertyValue> properties) {
for (var i = 0; i < properties.length; i++) {
var pt = _template.getPropertyTemplateByIndex(i);
if (pt != null) {
var pv = properties[i];
loadProperty(pt.name, pv.age, pv.date, pv.value);
}
}
/// <summary>
/// Age of the instance, incremented by 1 in every modification.
/// </summary>
int get age => _instanceAge;
// this must be internal
set age (value) => _instanceAge = value;
return true;
}
/// <summary>
/// Last modification date.
/// </summary>
DateTime get modificationDate => _instanceModificationDate;
/// <summary>
/// Instance Id.
/// </summary>
int get id => _id;
/// <summary>
/// Import properties from bytes array.
/// </summary>
/// <param name="properties"></param>
/// <returns></returns>
bool deserialize(List<PropertyValue> properties)
{
for (var i = 0; i < properties.length; i++)
{
var pt = _template.getPropertyTemplateByIndex(i);
if (pt != null)
{
var pv = properties[i];
loadProperty(pt.name, pv.age, pv.date, pv.value);
}
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
List<PropertyValue> serialize() {
List<PropertyValue> props = <PropertyValue>[];
return true;
for (var pt in _template.properties) {
// var rt = pt.info.getValue(resource, null);
// props.add(new PropertyValue(rt, _ages[pt.index], _modificationDates[pt.index]));
}
/// <summary>
/// Export all properties with ResourceProperty attributed as bytes array.
/// </summary>
/// <returns></returns>
List<PropertyValue> serialize()
{
List<PropertyValue> props = new List<PropertyValue>();
for (var pt in _template.properties)
{
// var rt = pt.info.getValue(resource, null);
// props.add(new PropertyValue(rt, _ages[pt.index], _modificationDates[pt.index]));
}
return props;
}
/*
return props;
}
/*
public bool Deserialize(byte[] data, uint offset, uint length)
{
@ -347,7 +304,7 @@ class Instance extends IEventHandler
return true;
}
*/
/*
/*
public byte[] Serialize(bool includeLength = false, DistributedConnection sender = null)
{
@ -405,70 +362,62 @@ class Instance extends IEventHandler
}
*/
/// <summary>
/// If True, the instance can be stored to disk.
/// </summary>
/// <returns></returns>
bool isStorable()
{
return false;
/// <summary>
/// If True, the instance can be stored to disk.
/// </summary>
/// <returns></returns>
bool isStorable() {
return false;
}
void emitModification(PropertyTemplate pt, dynamic value) {
_instanceAge++;
var now = DateTime.now().toUtc();
_ages[pt.index] = _instanceAge;
_modificationDates[pt.index] = now;
if (pt.storage == StorageMode.NonVolatile) {
_store?.modify(_resource, pt.name, value, _ages[pt.index], now);
} else if (pt.storage == StorageMode.Recordable) {
_store?.record(_resource, pt.name, value, _ages[pt.index], now);
}
emitArgs("resourceModified", [_resource, pt.name, value]);
//_resource.emitArgs("modified", [pt.name, value]);
_resource.emitArgs(":${pt.name}", [value]);
}
void emitModification(PropertyTemplate pt, dynamic value)
{
_instanceAge++;
var now = DateTime.now().toUtc();
_ages[pt.index] = _instanceAge;
_modificationDates[pt.index] = now;
if (pt.storage == StorageMode.NonVolatile)
{
_store.modify(_resource, pt.name, value, _ages[pt.index], now);
}
else if (pt.storage == StorageMode.Recordable)
{
_store.record(_resource, pt.name, value, _ages[pt.index], now);
}
emitArgs("resourceModified", [_resource, pt.name, value]);
//_resource.emitArgs("modified", [pt.name, value]);
_resource.emitArgs(":${pt.name}", [value]);
/// <summary>
/// Notify listeners that a property was modified.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
modified(String propertyName) {
var valueObject = new ValueObject();
if (getPropertyValue(propertyName, valueObject)) {
var pt = _template.getPropertyTemplateByName(propertyName);
if (pt != null) emitModification(pt, valueObject.value);
}
}
/// <summary>
/// Notify listeners that a property was modified.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="newValue"></param>
/// <param name="oldValue"></param>
modified(String propertyName)
{
var valueObject = new ValueObject();
if (getPropertyValue(propertyName, valueObject))
{
var pt = _template.getPropertyTemplateByName(propertyName);
emitModification(pt, valueObject.value);
}
}
emitResourceEvent(
issuer, List<Session>? receivers, String name, dynamic args) {
emitArgs(
"resourceEventOccurred", [_resource, issuer, receivers, name, args]);
}
emitResourceEvent(issuer, List<Session> receivers, String name, dynamic args)
{
emitArgs("resourceEventOccurred", [_resource, issuer, receivers, name, args]);
}
/// <summary>
/// Get the value of a given property by name.
/// </summary>
/// <param name="name">Property name</param>
/// <param name="value">Output value</param>
/// <returns>True, if the resource has the property.</returns>
bool getPropertyValue(String name, ValueObject valueObject) {
var pt = _template.getPropertyTemplateByName(name);
/// <summary>
/// Get the value of a given property by name.
/// </summary>
/// <param name="name">Property name</param>
/// <param name="value">Output value</param>
/// <returns>True, if the resource has the property.</returns>
bool getPropertyValue(String name, ValueObject valueObject)
{
var pt = _template.getPropertyTemplateByName(name);
/*
/*
if (pt != null && pt.info != null)
{
valueObject.value = pt.info.getValue(_resource, null);
@ -476,146 +425,130 @@ class Instance extends IEventHandler
}*/
valueObject.value = null;
return false;
}
valueObject.value = null;
return false;
}
/*
/*
public bool Inherit
{
get { return inherit; }
}*/
/// <summary>
/// List of parents.
/// </summary>
AutoList<IResource, Instance> get parents => _parents;
/// <summary>
/// List of parents.
/// </summary>
AutoList<IResource, Instance> get parents => _parents;
/// <summary>
/// Store responsible for creating and keeping the resource.
/// </summary>
IStore get store => _store;
/// <summary>
/// Store responsible for creating and keeping the resource.
/// </summary>
IStore? get store => _store;
/// <summary>
/// List of children.
/// </summary>
AutoList<IResource, Instance> get children => _children;
/// <summary>
/// The unique and permanent link to the resource.
/// </summary>
String get link
{
if (_store != null)
return _store.link(_resource);
else
{
var l = new List<String>();
/// <summary>
/// List of children.
/// </summary>
AutoList<IResource, Instance> get children => _children;
var p = _resource;
/// <summary>
/// The unique and permanent link to the resource.
/// </summary>
String? get link {
if (_store != null)
return _store?.link(_resource);
else {
var l = <String>[];
while (true)
{
l.insert(0, p.instance.name);
var p = _resource;
if (p.instance.parents.count == 0)
break;
while (true) {
if (p.instance != null) break;
var pi = p.instance as Instance;
p = p.instance.parents.first();
}
l.insert(0, pi.name);
return l.join("/");
}
if (pi.parents.count == 0) break;
p = pi.parents.first;
}
return l.join("/");
}
}
/// <summary>
/// Instance name.
/// </summary>
String get name => _name;
set name(value) => name = value;
/// <summary>
/// Resource managed by this instance.
/// </summary>
IResource get resource => _resource;
/// <summary>
/// Resource template describes the properties, functions and events of the resource.
/// </summary>
TypeTemplate get template => _template;
/// <summary>
/// Check for permission.
/// </summary>
/// <param name="session">Caller sessions.</param>
/// <param name="action">Action type</param>
/// <param name="member">Function, property or event to check for permission.</param>
/// <param name="inquirer">Permission inquirer.</param>
/// <returns>Ruling.</returns>
Ruling applicable(Session session, ActionType action, MemberTemplate? member,
[dynamic inquirer = null]) {
for (var i = 0; i < _managers.length; i++) {
var r = _managers[i]
.applicable(this.resource, session, action, member, inquirer);
if (r != Ruling.DontCare) return r;
}
/// <summary>
/// Instance name.
/// </summary>
String get name => _name;
set name(value) => name = value;
return Ruling.DontCare;
}
/// <summary>
/// Resource managed by this instance.
/// </summary>
IResource get resource => _resource;
/// <summary>
/// Resource template describes the properties, functions and events of the resource.
/// </summary>
TypeTemplate get template => _template;
/// <summary>
/// Execution managers.
/// </summary>
AutoList<IPermissionsManager, Instance> get managers => _managers;
/// <summary>
/// Check for permission.
/// </summary>
/// <param name="session">Caller sessions.</param>
/// <param name="action">Action type</param>
/// <param name="member">Function, property or event to check for permission.</param>
/// <param name="inquirer">Permission inquirer.</param>
/// <returns>Ruling.</returns>
Ruling applicable(Session session, ActionType action, MemberTemplate member, [dynamic inquirer = null])
{
for(var i = 0; i < _managers.length; i++)
{
var r = _managers[i].applicable(this.resource, session, action, member, inquirer);
if (r != Ruling.DontCare)
return r;
}
/// <summary>
/// Create new instance.
/// </summary>
/// <param name="id">Instance Id.</param>
/// <param name="name">Name of the instance.</param>
/// <param name="resource">Resource to manage.</param>
/// <param name="store">Store responsible for the resource.</param>
Instance(this._id, this._name, this._resource, this._store,
[TypeTemplate? customTemplate = null, this._instanceAge = 0]) {
_attributes = new KeyList<String, dynamic>(this);
_children = new AutoList<IResource, Instance>(this);
_parents = new AutoList<IResource, Instance>(this);
_managers = new AutoList<IPermissionsManager, Instance>(this);
return Ruling.DontCare;
_children.on("add", children_OnAdd);
_children.on("remove", children_OnRemoved);
_parents.on("add", parents_OnAdd);
_parents.on("remove", parents_OnRemoved);
resource.on("destroy", resource_OnDestroy);
if (customTemplate != null)
_template = customTemplate;
else
_template = Warehouse.getTemplateByType(resource.runtimeType);
// set ages
for (int i = 0; i < _template.properties.length; i++) {
_ages.add(0);
_modificationDates.add(new DateTime(0)); //DateTime.MinValue);
}
/// <summary>
/// Execution managers.
/// </summary>
AutoList<IPermissionsManager, Instance> get managers => _managers;
/// <summary>
/// Create new instance.
/// </summary>
/// <param name="id">Instance Id.</param>
/// <param name="name">Name of the instance.</param>
/// <param name="resource">Resource to manage.</param>
/// <param name="store">Store responsible for the resource.</param>
Instance(int id, String name, IResource resource, IStore store, [TypeTemplate customTemplate = null, int age = 0])
{
_store = store;
_resource = resource;
_id = id;
_name = name;
_instanceAge = age;
_attributes = new KeyList<String, dynamic>(this);
_children = new AutoList<IResource, Instance>(this);
_parents = new AutoList<IResource, Instance>(this);
_managers = new AutoList<IPermissionsManager, Instance>(this);
_children.on("add", children_OnAdd);
_children.on("remove", children_OnRemoved);
_parents.on("add", parents_OnAdd);
_parents.on("remove", parents_OnRemoved);
resource.on("destroy", resource_OnDestroy);
if (customTemplate != null)
_template = customTemplate;
else
_template = Warehouse.getTemplateByType(resource.runtimeType);
// set ages
for (int i = 0; i < _template.properties.length; i++)
{
_ages.add(0);
_modificationDates.add(new DateTime(0));//DateTime.MinValue);
}
/*
/*
// connect events
Type t = resource.runtimeType;
@ -650,33 +583,33 @@ class Instance extends IEventHandler
}
*/
}
}
void children_OnRemoved(Instance parent, IResource value)
{
value.instance.parents.remove(_resource);
}
void children_OnRemoved(Instance parent, IResource value) {
value.instance?.parents.remove(_resource);
}
void children_OnAdd(Instance parent, IResource value)
{
if (!value.instance.parents.contains(_resource))
value.instance.parents.add(_resource);
void children_OnAdd(Instance parent, IResource value) {
if (value.instance != null) {
var ins = value.instance as Instance;
if (ins.parents.contains(_resource))
value.instance?.parents.add(_resource);
}
}
void parents_OnRemoved(Instance parent, IResource value)
{
value.instance.children.remove(_resource);
void parents_OnRemoved(Instance parent, IResource value) {
value.instance?.children.remove(_resource);
}
void parents_OnAdd(Instance parent, IResource value) {
if (value.instance != null) {
var ins = value.instance as Instance;
if (!ins.children.contains(_resource))
value.instance?.children.add(_resource);
}
}
void parents_OnAdd(Instance parent, IResource value)
{
if (!value.instance.children.contains(_resource))
value.instance.children.add(_resource);
}
void resource_OnDestroy(sender)
{
emitArgs("resourceDestroyed", [sender]);
}
void resource_OnDestroy(sender) {
emitArgs("resourceDestroyed", [sender]);
}
}

View File

@ -3,32 +3,30 @@ import '../../Data/BinaryList.dart';
import "../../Data/ParseResult.dart";
import './TemplateDataType.dart';
class ArgumentTemplate
{
String name;
class ArgumentTemplate {
String name;
TemplateDataType type;
TemplateDataType type;
static ParseResult<ArgumentTemplate> parse(DC data, int offset)
{
var cs = data[offset++];
var name = data.getString(offset, cs);
offset += cs;
var tdr = TemplateDataType.parse(data, offset);
static ParseResult<ArgumentTemplate> parse(DC data, int offset) {
var cs = data[offset++];
var name = data.getString(offset, cs);
offset += cs;
var tdr = TemplateDataType.parse(data, offset);
return ParseResult<ArgumentTemplate>(cs + 1 + tdr.size, ArgumentTemplate(name, tdr.value));
}
ArgumentTemplate(this.name, this.type);
DC compose()
{
var name = DC.stringToBytes(this.name);
return new BinaryList()
.addUint8(name.length)
.addDC(name)
.addDC(type.compose())
.toDC();
}
return ParseResult<ArgumentTemplate>(
cs + 1 + tdr.size, ArgumentTemplate(name, tdr.value));
}
ArgumentTemplate(this.name, this.type);
DC compose() {
var name = DC.stringToBytes(this.name);
return (BinaryList()
..addUint8(name.length)
..addDC(name)
..addDC(type.compose()))
.toDC();
}
}

View File

@ -6,7 +6,7 @@ import 'MemberType.dart';
import 'TemplateDataType.dart';
class EventTemplate extends MemberTemplate {
String expansion;
String? expansion;
bool listenable;
TemplateDataType argumentType;
@ -14,21 +14,21 @@ class EventTemplate extends MemberTemplate {
var name = super.compose();
if (expansion != null) {
var exp = DC.stringToBytes(expansion);
return new BinaryList()
.addUint8(listenable ? 0x58 : 0x50)
.addUint8(name.length)
.addDC(name)
.addDC(argumentType.compose())
.addInt32(exp.length)
.addDC(exp)
var exp = DC.stringToBytes(expansion as String);
return (BinaryList()
..addUint8(listenable ? 0x58 : 0x50)
..addUint8(name.length)
..addDC(name)
..addDC(argumentType.compose())
..addInt32(exp.length)
..addDC(exp))
.toDC();
} else {
return new BinaryList()
.addUint8(listenable ? 0x48 : 0x40)
.addUint8(name.length)
.addDC(name)
.addDC(argumentType.compose())
return (BinaryList()
..addUint8(listenable ? 0x48 : 0x40)
..addUint8(name.length)
..addDC(name)
..addDC(argumentType.compose()))
.toDC();
}
}

View File

@ -7,8 +7,8 @@ import 'ArgumentTemplate.dart';
import 'TemplateDataType.dart';
class FunctionTemplate extends MemberTemplate {
String expansion;
bool isVoid;
String? expansion;
// bool isVoid;
TemplateDataType returnType;
List<ArgumentTemplate> arguments;
@ -18,10 +18,10 @@ class FunctionTemplate extends MemberTemplate {
var name = super.compose();
var bl = new BinaryList()
.addUint8(name.length)
.addDC(name)
.addDC(returnType.compose())
.addUint8(arguments.length);
..addUint8(name.length)
..addDC(name)
..addDC(returnType.compose())
..addUint8(arguments.length);
for (var i = 0; i < arguments.length; i++)
bl.addDC(arguments[i].compose());
@ -29,9 +29,9 @@ class FunctionTemplate extends MemberTemplate {
if (expansion != null)
{
var exp = DC.stringToBytes(expansion);
bl.addInt32(exp.length)
.addDC(exp);
var exp = DC.stringToBytes(expansion as String);
bl..addInt32(exp.length)
..addDC(exp);
bl.insertUint8(0, 0x10);
}
else
@ -41,9 +41,9 @@ class FunctionTemplate extends MemberTemplate {
}
FunctionTemplate(TypeTemplate template, int index, String name,
this.arguments, this.returnType, String expansion)
this.arguments, this.returnType, this.expansion)
: super(template, MemberType.Property, index, name) {
this.isVoid = isVoid;
this.expansion = expansion;
}
}

View File

@ -17,12 +17,8 @@ class MemberTemplate
TypeTemplate get template => _template;
MemberTemplate(TypeTemplate template, MemberType type, int index, String name)
MemberTemplate(this._template, this._type, this._index, this._name)
{
this._template = template;
this._type = type;
this._index = index;
this._name = name;
}
String get fullname => _template.className + "." + _name;

View File

@ -14,63 +14,59 @@ class PropertyTemplate extends MemberTemplate {
int storage;
String readExpansion;
String? readExpansion;
String writeExpansion;
String? writeExpansion;
DC compose() {
var name = super.compose();
var pv = ((permission) << 1) | (storage == StorageMode.Recordable ? 1 : 0);
if (writeExpansion != null && readExpansion != null) {
var rexp = DC.stringToBytes(readExpansion);
var wexp = DC.stringToBytes(writeExpansion);
return new BinaryList()
.addUint8(0x38 | pv)
.addUint8(name.length)
.addDC(name)
.addDC(valueType.compose())
.addInt32(wexp.length)
.addDC(wexp)
.addInt32(rexp.length)
.addDC(rexp)
var rexp = DC.stringToBytes(readExpansion as String);
var wexp = DC.stringToBytes(writeExpansion as String);
return (BinaryList()
..addUint8(0x38 | pv)
..addUint8(name.length)
..addDC(name)
..addDC(valueType.compose())
..addInt32(wexp.length)
..addDC(wexp)
..addInt32(rexp.length)
..addDC(rexp))
.toDC();
} else if (writeExpansion != null) {
var wexp = DC.stringToBytes(writeExpansion);
return new BinaryList()
.addUint8(0x30 | pv)
.addUint8(name.length)
.addDC(name)
.addDC(valueType.compose())
.addInt32(wexp.length)
.addDC(wexp)
var wexp = DC.stringToBytes(writeExpansion as String);
return (BinaryList()
..addUint8(0x30 | pv)
..addUint8(name.length)
..addDC(name)
..addDC(valueType.compose())
..addInt32(wexp.length)
..addDC(wexp))
.toDC();
} else if (readExpansion != null) {
var rexp = DC.stringToBytes(readExpansion);
return new BinaryList()
.addUint8(0x28 | pv)
.addUint8(name.length)
.addDC(name)
.addDC(valueType.compose())
.addInt32(rexp.length)
.addDC(rexp)
var rexp = DC.stringToBytes(readExpansion as String);
return (BinaryList()
..addUint8(0x28 | pv)
..addUint8(name.length)
..addDC(name)
..addDC(valueType.compose())
..addInt32(rexp.length)
..addDC(rexp))
.toDC();
} else
return new BinaryList()
.addUint8(0x20 | pv)
.addUint8(name.length)
.addDC(name)
.addDC(valueType.compose())
return (BinaryList()
..addUint8(0x20 | pv)
..addUint8(name.length)
..addDC(name)
..addDC(valueType.compose()))
.toDC();
}
PropertyTemplate(TypeTemplate template, int index, String name,
TemplateDataType valueType, String read, String write, int storage)
this.valueType, this.readExpansion, this.writeExpansion, this.storage)
: super(template, MemberType.Property, index, name) {
//this.Recordable = recordable;
this.storage = storage;
this.readExpansion = read;
this.writeExpansion = write;
this.valueType = valueType;
}
}

View File

@ -16,11 +16,12 @@ import '../../Resource/Warehouse.dart';
import 'TemplateType.dart';
class TemplateDataType {
int type;
TypeTemplate get typeTemplate =>
typeGuid == null ? null : Warehouse.getTemplateByClassId(typeGuid);
late int type;
TypeTemplate? get typeTemplate => typeGuid == null
? null
: Warehouse.getTemplateByClassId(typeGuid as Guid);
Guid typeGuid;
Guid? typeGuid;
// @TODO: implement fromType
TemplateDataType.fromType(type, bool isArray) {
@ -98,7 +99,10 @@ class TemplateDataType {
type == DataType.ResourceArray ||
type == DataType.Record ||
type == DataType.RecordArray) {
return BinaryList().addUint8(type).addDC(typeGuid.value).toDC();
return (BinaryList()
..addUint8(type)
..addDC((typeGuid as Guid).value))
.toDC();
} else
return DC.fromList([type]);
}

View File

@ -1,9 +1,9 @@
import '../../Data/DataType.dart';
class TemplateDescriber {
final List<Prop> properties;
final List<Evt> events;
final List<Func> functions;
final List<Prop>? properties;
final List<Evt>? events;
final List<Func>? functions;
final String nameSpace;
final int version;
@ -47,8 +47,8 @@ class Prop {
final String name;
final Type type;
final bool isArray;
final String readAnnotation;
final String writeAnnotation;
final String? readAnnotation;
final String? writeAnnotation;
Prop(this.name, this.type, this.isArray,
[this.readAnnotation = null, this.writeAnnotation = null]);
}
@ -58,7 +58,7 @@ class Evt {
final bool listenable;
final Type type;
final bool isArray;
final String annotation;
final String? annotation;
Evt(this.name, this.type, this.isArray,
[this.listenable = false, this.annotation]);
@ -69,7 +69,7 @@ class Func {
final Type returnType;
final List<Arg> argsType;
final bool isArray;
final String annotation;
final String? annotation;
Func(this.name, this.returnType, this.isArray, this.argsType,
[this.annotation = null]);

View File

@ -22,26 +22,26 @@ import 'TemplateDataType.dart';
import 'TemplateType.dart';
class TypeTemplate {
Guid _classId;
String _className;
late Guid _classId;
late String _className;
List<MemberTemplate> _members = [];
List<FunctionTemplate> _functions = [];
List<EventTemplate> _events = [];
List<PropertyTemplate> _properties = [];
int _version;
late int _version;
//bool isReady;
TemplateType _templateType;
late TemplateType _templateType;
DC _content;
late DC _content;
DC get content => _content;
TemplateType get type => _templateType;
Type _definedType;
Type? _definedType;
Type get definedType => _definedType;
Type? get definedType => _definedType;
/*
MemberTemplate getMemberTemplate(MemberInfo member)
{
@ -59,32 +59,32 @@ class TypeTemplate {
//@TODO: implement
static List<TypeTemplate> getDependencies(TypeTemplate template) => [];
EventTemplate getEventTemplateByName(String eventName) {
EventTemplate? getEventTemplateByName(String eventName) {
for (var i in _events) if (i.name == eventName) return i;
return null;
}
EventTemplate getEventTemplateByIndex(int index) {
EventTemplate? getEventTemplateByIndex(int index) {
for (var i in _events) if (i.index == index) return i;
return null;
}
FunctionTemplate getFunctionTemplateByName(String functionName) {
FunctionTemplate? getFunctionTemplateByName(String functionName) {
for (var i in _functions) if (i.name == functionName) return i;
return null;
}
FunctionTemplate getFunctionTemplateByIndex(int index) {
FunctionTemplate? getFunctionTemplateByIndex(int index) {
for (var i in _functions) if (i.index == index) return i;
return null;
}
PropertyTemplate getPropertyTemplateByIndex(int index) {
PropertyTemplate? getPropertyTemplateByIndex(int index) {
for (var i in _properties) if (i.index == index) return i;
return null;
}
PropertyTemplate getPropertyTemplateByName(String propertyName) {
PropertyTemplate? getPropertyTemplateByName(String propertyName) {
for (var i in _properties) if (i.name == propertyName) return i;
return null;
}
@ -143,9 +143,11 @@ class TypeTemplate {
if (addToWarehouse) Warehouse.putTemplate(this);
// _templates.add(template.classId, template);
if (describer.properties != null)
for (var i = 0; i < describer.properties.length; i++) {
var pi = describer.properties[i];
if (describer.properties != null) {
var props = describer.properties as List<Prop>;
for (var i = 0; i < props.length; i++) {
var pi = props[i];
var pt = PropertyTemplate(
this,
i,
@ -156,10 +158,13 @@ class TypeTemplate {
0);
properties.add(pt);
}
}
if (describer.functions != null)
for (var i = 0; i < describer.functions.length; i++) {
var fi = describer.functions[i];
if (describer.functions != null) {
var funcs = describer.functions as List<Func>;
for (var i = 0; i < funcs.length; i++) {
var fi = funcs[i];
List<ArgumentTemplate> args = fi.argsType
.map((arg) => ArgumentTemplate(
@ -176,10 +181,12 @@ class TypeTemplate {
functions.add(ft);
}
}
if (describer.events != null)
for (var i = 0; i < describer.events.length; i++) {
var ei = describer.events[i];
if (describer.events != null) {
var evts = describer.events as List<Evt>;
for (var i = 0; i < evts.length; i++) {
var ei = evts[i];
var et = new EventTemplate(
this,
@ -191,6 +198,7 @@ class TypeTemplate {
events.add(et);
}
}
// append signals
events.forEach(_members.add);
@ -200,14 +208,13 @@ class TypeTemplate {
properties.forEach(_members.add);
// bake it binarily
var b = new BinaryList();
b
.addUint8(_templateType.index)
.addGuid(classId)
.addUint8(className.length)
.addString(className)
.addInt32(_version)
.addUint16(_members.length);
var b = BinaryList()
..addUint8(_templateType.index)
..addGuid(classId)
..addUint8(className.length)
..addString(className)
..addInt32(_version)
..addUint16(_members.length);
functions.forEach((ft) => b.addDC(ft.compose()));
properties.forEach((pt) => b.addDC(pt.compose()));
@ -429,7 +436,7 @@ class TypeTemplate {
*/
TypeTemplate.parse(DC data, [int offset = 0, int contentLength]) {
TypeTemplate.parse(DC data, [int offset = 0, int? contentLength]) {
// cool Dart feature
contentLength ??= data.length;
@ -464,7 +471,7 @@ class TypeTemplate {
if (type == 0) // function
{
String expansion = null;
String? expansion = null;
var hasExpansion = ((data[offset++] & 0x10) == 0x10);
var name = data.getString(offset + 1, data[offset]);
@ -497,7 +504,7 @@ class TypeTemplate {
_functions.add(ft);
} else if (type == 1) // property
{
String readExpansion = null, writeExpansion = null;
String? readExpansion = null, writeExpansion = null;
var hasReadExpansion = ((data[offset] & 0x8) == 0x8);
var hasWriteExpansion = ((data[offset] & 0x10) == 0x10);
@ -539,7 +546,7 @@ class TypeTemplate {
_properties.add(pt);
} else if (type == 2) // Event
{
String expansion = null;
String? expansion = null;
var hasExpansion = ((data[offset] & 0x10) == 0x10);
var listenable = ((data[offset++] & 0x8) == 0x8);

View File

@ -22,6 +22,10 @@ SOFTWARE.
*/
import '../Core/AsyncException.dart';
import '../Core/ErrorType.dart';
import '../Core/ExceptionCode.dart';
import '../Data/AutoList.dart';
import 'FactoryEntry.dart';
import 'Template/TemplateType.dart';
@ -41,8 +45,7 @@ import '../Net/IIP/DistributedConnection.dart';
// Centeral Resource Issuer
class Warehouse {
static AutoList<IResource, Instance> _stores =
new AutoList<IResource, Instance>(null);
static AutoList<IStore, Instance> _stores = AutoList<IStore, Instance>();
static Map<int, IResource> _resources = new Map<int, IResource>();
static int resourceCounter = 0;
@ -74,8 +77,8 @@ class Warehouse {
/// </summary>
/// <param name="name">Store instance name</param>
/// <returns></returns>
static IStore getStore(String name) {
for (var s in _stores) if (s.instance.name == name) return s;
static IStore? getStore(String name) {
for (var s in _stores) if (s.instance?.name == name) return s;
return null;
}
@ -84,11 +87,11 @@ class Warehouse {
/// </summary>
/// <param name="id">Instance Id</param>
/// <returns></returns>
static AsyncReply<IResource> getById(int id) {
static AsyncReply<IResource?> getById(int id) {
if (_resources.containsKey(id))
return new AsyncReply<IResource>.ready(_resources[id]);
return new AsyncReply<IResource?>.ready(_resources[id]);
else
return new AsyncReply<IResource>.ready(null);
return new AsyncReply<IResource?>.ready(null);
}
/// <summary>
@ -106,20 +109,21 @@ class Warehouse {
var rt = new AsyncReply<bool>();
bag.then((x) {
for (var b in x)
if (!b) {
if (b == null || b == false) {
rt.trigger(false);
return;
}
var rBag = new AsyncBag<bool>();
for (var rk in _resources.keys)
rBag.add(_resources[rk].trigger(ResourceTrigger.SystemInitialized));
rBag.add((_resources[rk] as IResource)
.trigger(ResourceTrigger.SystemInitialized));
rBag.seal();
rBag.then((y) {
for (var b in y)
if (!b) {
if (b == null || b == false) {
rt.trigger(false);
return;
}
@ -158,7 +162,7 @@ class Warehouse {
var rt = new AsyncReply<bool>();
bag.then((x) {
for (var b in x)
if (!b) {
if (b == null || b == false) {
rt.trigger(false);
return;
}
@ -178,19 +182,21 @@ class Warehouse {
for (var child in resources) rt.add(child);
else
for (var child in resources)
if (child.instance.name == path[index]) rt.add(child);
if (child.instance?.name == path[index]) rt.add(child);
} else
for (var child in resources)
if (child.instance.name == path[index])
rt.addAll(qureyIn(path, index + 1, child.instance.children));
if (child.instance?.name == path[index])
rt.addAll(qureyIn(path, index + 1,
child.instance?.children as AutoList<IResource, Instance>));
return rt;
}
static AsyncReply<List<IResource>> query(String path) {
static AsyncReply<List<IResource>?> query(String? path) {
if (path == null || path == "") {
var roots = _stores.where((s) => s.instance.parents.length == 0).toList();
return new AsyncReply<List<IResource>>.ready(roots);
var roots =
_stores.where((s) => s.instance?.parents.length == 0).toList();
return new AsyncReply<List<IResource>?>.ready(roots);
} else {
var rt = new AsyncReply<List<IResource>>();
get(path).then((x) {
@ -215,40 +221,46 @@ class Warehouse {
/// </summary>
/// <param name="path"></param>
/// <returns>Resource instance.</returns>
static AsyncReply<T> get<T extends IResource>(String path,
static AsyncReply<T?> get<T extends IResource>(String path,
[attributes = null,
IResource parent = null,
IPermissionsManager manager = null]) {
var rt = AsyncReply<T>();
IResource? parent = null,
IPermissionsManager? manager = null]) {
var rt = AsyncReply<T?>();
// Should we create a new store ?
if (_urlRegex.hasMatch(path)) {
var url = _urlRegex.allMatches(path).first;
if (protocols.containsKey(url[1])) {
var handler = protocols[url[1]];
var handler =
protocols[url[1]] as AsyncReply<IStore> Function(String, dynamic);
var getFromStore = () {
handler(url[2], attributes).then<IStore>((store) {
if (url[3].length > 0 && url[3] != "")
store.get(url[3]).then<dynamic>((r) {
rt.trigger(r);
}).error((e) => rt.triggerError(e));
else
rt.trigger(store as T);
}).error((e) {
rt.triggerError(e);
//Warehouse.remove(store);
});
handler(url[2] as String, attributes)
..then((store) {
if ((url[3] as String).length > 0 && url[3] != "")
store.get(url[3] as String)
..then((r) {
rt.trigger(r as T);
})
..error((e) => rt.triggerError(e));
else
rt.trigger(store as T);
})
..error((e) {
rt.triggerError(e);
//Warehouse.remove(store);
});
};
if (!_warehouseIsOpen)
open().then((v) {
if (v)
getFromStore();
else
rt.trigger(null);
});
open()
..then((v) {
if (v)
getFromStore();
else
rt.trigger(null);
});
else
getFromStore();
@ -258,7 +270,7 @@ class Warehouse {
query(path).then((rs) {
if (rs != null && rs.length > 0)
rt.trigger(rs[0]);
rt.trigger(rs[0] as T);
else
rt.trigger(null);
});
@ -342,14 +354,14 @@ class Warehouse {
/// <param name="name">Resource name.</param>
/// <param name="store">IStore that manages the resource. Can be null if the resource is a store.</param>
/// <param name="parent">Parent resource. if not presented the store becomes the parent for the resource.</param>
static AsyncReply<T> put<T extends IResource>(String name, T resource,
[IStore store = null,
IResource parent = null,
TypeTemplate customTemplate = null,
static AsyncReply<T?> put<T extends IResource>(String name, T resource,
[IStore? store = null,
IResource? parent = null,
TypeTemplate? customTemplate = null,
int age = 0,
IPermissionsManager manager = null,
IPermissionsManager? manager = null,
attributes = null]) {
var rt = AsyncReply<T>();
var rt = AsyncReply<T?>();
if (resource.instance != null) {
rt.triggerError(Exception("Resource has a store."));
@ -415,19 +427,21 @@ class Warehouse {
resourceCounter++, name, resource, store, customTemplate, age);
if (attributes != null)
resource.instance.setAttributes(Structure.fromMap(attributes));
resource.instance?.setAttributes(Structure.fromMap(attributes));
if (manager != null) resource.instance.managers.add(manager);
if (manager != null) resource.instance?.managers.add(manager);
if (store == parent) parent = null;
if (parent == null) {
if (!(resource is IStore)) store.instance.children.add(resource);
if (!(resource is IStore)) store?.instance?.children.add(resource);
} else
parent.instance.children.add(resource);
parent.instance?.children.add(resource);
var initResource = () {
_resources[resource.instance.id] = resource;
if (resource.instance == null) return;
_resources[(resource.instance as Instance).id] = resource;
if (_warehouseIsOpen) {
resource.trigger(ResourceTrigger.Initialize).then<dynamic>((value) {
@ -451,7 +465,7 @@ class Warehouse {
_stores.add(resource);
initResource();
} else {
store.put(resource).then<dynamic>((value) {
store?.put(resource).then<dynamic>((value) {
if (value)
initResource();
else
@ -468,20 +482,23 @@ class Warehouse {
}
static T createInstance<T>(Type T) {
return _factory[T].instanceCreator.call();
return _factory[T]?.instanceCreator.call();
}
static List<T> createArray<T>(Type T) {
return _factory[T].arrayCreator.call();
return _factory[T]?.arrayCreator.call();
}
static AsyncReply<T> newResource<T extends IResource>(String name,
[IStore store = null,
IResource parent = null,
IPermissionsManager manager = null,
[IStore? store = null,
IResource? parent = null,
IPermissionsManager? manager = null,
attributes = null,
properties = null]) {
var resource = _factory[T].instanceCreator.call();
if (_factory[T] == null)
throw Exception("No Instance Creator was found for type ${T}");
var resource = _factory[T]?.instanceCreator.call();
if (properties != null) {
dynamic d = resource;
@ -494,12 +511,16 @@ class Warehouse {
var rt = AsyncReply<T>();
put<T>(name, resource, store, parent, null, 0, manager, attributes)
.then<IResource>((value) {
if (value != null)
rt.trigger(resource);
else
rt.trigger(null);
}).error((ex) => rt.triggerError(ex));
..then((value) {
if (value != null)
rt.trigger(resource);
else
rt.triggerError(AsyncException(
ErrorType.Management,
ExceptionCode.GeneralFailure.index,
"Can't put the resource")); // .trigger(null);
})
..error((ex) => rt.triggerError(ex));
return rt;
@ -516,7 +537,7 @@ class Warehouse {
/// </summary>
/// <param name="template">Resource template.</param>
static void putTemplate(TypeTemplate template) {
_templates[template.type][template.classId] = template;
_templates[template.type]?[template.classId] = template;
}
/// <summary>
@ -541,22 +562,22 @@ class Warehouse {
/// </summary>
/// <param name="classId">Class Id.</param>
/// <returns>Resource template.</returns>
static TypeTemplate getTemplateByClassId(Guid classId,
static TypeTemplate? getTemplateByClassId(Guid classId,
[TemplateType templateType = TemplateType.Unspecified]) {
if (templateType == TemplateType.Unspecified) {
// look in resources
var template = _templates[TemplateType.Resource][classId];
var template = _templates[TemplateType.Resource]?[classId];
if (template != null) return template;
// look in records
template = _templates[TemplateType.Record][classId];
template = _templates[TemplateType.Record]?[classId];
if (template != null) return template;
// look in wrappers
template = _templates[TemplateType.Wrapper][classId];
template = _templates[TemplateType.Wrapper]?[classId];
return template;
} else {
return _templates[templateType][classId];
return _templates[templateType]?[classId];
}
}
@ -565,29 +586,29 @@ class Warehouse {
/// </summary>
/// <param name="className">Class name.</param>
/// <returns>Resource template.</returns>
static TypeTemplate getTemplateByClassName(String className,
static TypeTemplate? getTemplateByClassName(String className,
[TemplateType templateType = TemplateType.Unspecified]) {
if (templateType == TemplateType.Unspecified) {
// look in resources
var template = _templates[TemplateType.Resource]
.values
?.values
.firstWhere((x) => x.className == className);
if (template != null) return template;
// look in records
template = _templates[TemplateType.Record]
.values
?.values
.firstWhere((x) => x.className == className);
if (template != null) return template;
// look in wrappers
template = _templates[TemplateType.Wrapper]
.values
?.values
.firstWhere((x) => x.className == className);
return template;
} else {
return _templates[templateType]
.values
?.values
.firstWhere((x) => x.className == className);
}
}
@ -595,8 +616,8 @@ class Warehouse {
static bool remove(IResource resource) {
if (resource.instance == null) return false;
if (_resources.containsKey(resource.instance.id))
_resources.remove(resource.instance.id);
if (_resources.containsKey(resource.instance?.id))
_resources.remove(resource.instance?.id);
else
return false;
@ -605,14 +626,14 @@ class Warehouse {
// remove all objects associated with the store
var toBeRemoved =
_resources.values.where((x) => x.instance.store == resource);
_resources.values.where((x) => x.instance?.store == resource);
for (var o in toBeRemoved) remove(o);
// StoreDisconnected?.Invoke(resource as IStore);
}
if (resource.instance.store != null)
resource.instance.store.remove(resource);
if (resource.instance?.store != null)
resource.instance?.store?.remove(resource);
resource.destroy();