mirror of
https://github.com/esiur/esiur-dart.git
synced 2025-05-06 12:02:57 +00:00
1.2.6
This commit is contained in:
parent
4c36f591da
commit
cb8e6d5430
@ -1,32 +1,29 @@
|
|||||||
|
|
||||||
import 'ExceptionCode.dart';
|
import 'ExceptionCode.dart';
|
||||||
import 'ErrorType.dart';
|
import 'ErrorType.dart';
|
||||||
|
|
||||||
class AsyncException implements Exception
|
class AsyncException implements Exception {
|
||||||
{
|
final ErrorType type;
|
||||||
final ErrorType type;
|
final int code;
|
||||||
final int code;
|
final String message;
|
||||||
final String message;
|
|
||||||
|
|
||||||
AsyncException(this.type, this.code, this.message)
|
AsyncException(this.type, this.code, this.message) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
static toAsyncException(Exception ex) {
|
||||||
|
return ex is AsyncException
|
||||||
|
? ex
|
||||||
|
: new AsyncException(ErrorType.Exception, 0, ex.toString());
|
||||||
|
}
|
||||||
|
|
||||||
static toAsyncException(Exception ex)
|
String errMsg() {
|
||||||
{
|
if (type == ErrorType.Management)
|
||||||
return ex is AsyncException ? ex
|
return ExceptionCode.values.elementAt(code).toString() +
|
||||||
: new AsyncException(ErrorType.Exception, 0, ex.toString());
|
": " +
|
||||||
}
|
(message ?? "");
|
||||||
|
else
|
||||||
|
return code.toString() + ": " + message;
|
||||||
|
}
|
||||||
|
|
||||||
String errMsg() {
|
@override
|
||||||
if (type == ErrorType.Management)
|
|
||||||
return ExceptionCode.values.elementAt(code).toString() + ": " + (message ?? "");
|
|
||||||
else
|
|
||||||
return code.toString() + ": " + message;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
String toString() {
|
||||||
return errMsg();
|
return errMsg();
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,10 @@ class AsyncReply<T> implements Future<T>
|
|||||||
{
|
{
|
||||||
_errorCallbacks.add((ex)=>onError());
|
_errorCallbacks.add((ex)=>onError());
|
||||||
}
|
}
|
||||||
|
else if (onError is Function(Object, StackTrace))
|
||||||
|
{
|
||||||
|
_errorCallbacks.add((ex)=>onError(ex, null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -169,10 +173,17 @@ class AsyncReply<T> implements Future<T>
|
|||||||
if (_resultReady)
|
if (_resultReady)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_exception = AsyncException.toAsyncException(exception);
|
if (exception is AsyncException)
|
||||||
|
_exception = exception;
|
||||||
|
else
|
||||||
|
_exception = AsyncException.toAsyncException(exception);
|
||||||
|
|
||||||
///lock (callbacksLock)
|
///lock (callbacksLock)
|
||||||
//{
|
//{
|
||||||
|
|
||||||
|
if (this._errorCallbacks.length == 0)
|
||||||
|
throw _exception;
|
||||||
|
else
|
||||||
_errorCallbacks.forEach((x) {
|
_errorCallbacks.forEach((x) {
|
||||||
x(_exception);
|
x(_exception);
|
||||||
});
|
});
|
||||||
|
@ -916,12 +916,12 @@ class DistributedConnection extends NetworkConnection with IStore
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resource">Resource.</param>
|
/// <param name="resource">Resource.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool put(IResource resource)
|
AsyncReply<bool> put(IResource resource)
|
||||||
{
|
{
|
||||||
if (Codec.isLocalResource(resource, this))
|
if (Codec.isLocalResource(resource, this))
|
||||||
_resources.add((resource as DistributedResource).id, resource);
|
_resources.add((resource as DistributedResource).id, resource);
|
||||||
// else .. put it in the server....
|
// else .. put it in the server....
|
||||||
return true;
|
return AsyncReply.ready(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,322 +33,271 @@ import '../../Data/Codec.dart';
|
|||||||
import './DistributedConnection.dart';
|
import './DistributedConnection.dart';
|
||||||
import '../Packets/IIPPacketAction.dart';
|
import '../Packets/IIPPacketAction.dart';
|
||||||
|
|
||||||
class DistributedResource extends IResource
|
class DistributedResource extends IResource {
|
||||||
{
|
int _instanceId;
|
||||||
|
DistributedConnection _connection;
|
||||||
|
|
||||||
int _instanceId;
|
bool _attached = false;
|
||||||
DistributedConnection _connection;
|
//bool _isReady = false;
|
||||||
|
|
||||||
bool _attached = false;
|
String _link;
|
||||||
//bool _isReady = false;
|
List _properties;
|
||||||
|
bool _destroyed = false;
|
||||||
|
|
||||||
String _link;
|
List<KeyValuePair<int, dynamic>> _queued_updates =
|
||||||
List _properties;
|
List<KeyValuePair<int, dynamic>>();
|
||||||
bool _destroyed = false;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Connection responsible for the distributed resource.
|
||||||
|
/// </summary>
|
||||||
|
DistributedConnection get connection => _connection;
|
||||||
|
|
||||||
List<KeyValuePair<int, dynamic>> _queued_updates =List<KeyValuePair<int, dynamic>>();
|
/// <summary>
|
||||||
|
/// Resource link
|
||||||
|
/// </summary>
|
||||||
|
String get link => _link;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connection responsible for the distributed resource.
|
/// Instance Id given by the other end.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DistributedConnection get connection => _connection;
|
int get id => _instanceId;
|
||||||
|
|
||||||
/// <summary>
|
//bool get destroyed => _destroyed;
|
||||||
/// Resource link
|
|
||||||
/// </summary>
|
|
||||||
String get link => _link;
|
|
||||||
|
|
||||||
/// <summary>
|
bool get suspended => _suspended;
|
||||||
/// Instance Id given by the other end.
|
bool _suspended = true;
|
||||||
/// </summary>
|
|
||||||
int get id => _instanceId;
|
|
||||||
|
|
||||||
//bool get destroyed => _destroyed;
|
AsyncReply<bool> trigger(ResourceTrigger trigger) => AsyncReply.ready(true);
|
||||||
|
|
||||||
bool get suspended => _suspended;
|
/// <summary>
|
||||||
bool _suspended = true;
|
/// IDestructible interface.
|
||||||
|
/// </summary>
|
||||||
|
void destroy() {
|
||||||
|
_destroyed = true;
|
||||||
|
_attached = false;
|
||||||
|
_connection.sendDetachRequest(_instanceId);
|
||||||
|
emitArgs("destroy", [this]);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
void suspend() {
|
||||||
/// IDestructible interface.
|
_suspended = true;
|
||||||
/// </summary>
|
_attached = false;
|
||||||
void destroy()
|
}
|
||||||
{
|
|
||||||
_destroyed = true;
|
/// <summary>
|
||||||
_attached = false;
|
/// Resource is ready when all its properties are attached.
|
||||||
_connection.sendDetachRequest(_instanceId);
|
/// </summary>
|
||||||
emitArgs("destroy", [this]);
|
// bool get isReady => _isReady;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resource is attached when all its properties are received.
|
||||||
|
/// </summary>
|
||||||
|
bool get attached => _attached;
|
||||||
|
|
||||||
|
// public DistributedResourceStack Stack
|
||||||
|
//{
|
||||||
|
// get { return stack; }
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new distributed resource.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="connection">Connection responsible for the distributed resource.</param>
|
||||||
|
/// <param name="template">Resource template.</param>
|
||||||
|
/// <param name="instanceId">Instance Id given by the other end.</param>
|
||||||
|
/// <param name="age">Resource age.</param>
|
||||||
|
DistributedResource(
|
||||||
|
DistributedConnection connection, int instanceId, int age, String link) {
|
||||||
|
this._link = link;
|
||||||
|
this._connection = connection;
|
||||||
|
this._instanceId = instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void _ready()
|
||||||
|
//{
|
||||||
|
// _isReady = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Export all properties with ResourceProperty attributed as bytes array.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<PropertyValue> serialize() {
|
||||||
|
var props = new List<PropertyValue>(_properties.length);
|
||||||
|
|
||||||
|
for (var i = 0; i < _properties.length; i++)
|
||||||
|
props[i] = new PropertyValue(
|
||||||
|
_properties[i], instance.getAge(i), instance.getModificationDate(i));
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool attach(List<PropertyValue> properties) {
|
||||||
|
if (_attached)
|
||||||
|
return false;
|
||||||
|
else {
|
||||||
|
_suspended = false;
|
||||||
|
|
||||||
|
_properties = new List(properties.length); // object[properties.Length];
|
||||||
|
|
||||||
|
//_events = new DistributedResourceEvent[Instance.Template.Events.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < properties.length; i++) {
|
||||||
|
instance.setAge(i, properties[i].age);
|
||||||
|
instance.setModificationDate(i, properties[i].date);
|
||||||
|
_properties[i] = properties[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger holded events/property updates.
|
||||||
|
//foreach (var r in afterAttachmentTriggers)
|
||||||
|
// r.Key.Trigger(r.Value);
|
||||||
|
|
||||||
|
//afterAttachmentTriggers.Clear();
|
||||||
|
|
||||||
|
_attached = true;
|
||||||
|
|
||||||
|
if (_queued_updates.length > 0) {
|
||||||
|
_queued_updates
|
||||||
|
.forEach((kv) => updatePropertyByIndex(kv.key, kv.value));
|
||||||
|
_queued_updates.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
void suspend()
|
}
|
||||||
{
|
|
||||||
_suspended = true;
|
|
||||||
_attached = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resource is ready when all its properties are attached.
|
|
||||||
/// </summary>
|
|
||||||
// bool get isReady => _isReady;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resource is attached when all its properties are received.
|
|
||||||
/// </summary>
|
|
||||||
bool get attached => _attached;
|
|
||||||
|
|
||||||
|
|
||||||
// public DistributedResourceStack Stack
|
void emitEventByIndex(int index, List<dynamic> args) {
|
||||||
//{
|
// neglect events when the object is not yet attached
|
||||||
// get { return stack; }
|
if (!_attached) return;
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
var et = instance.template.getEventTemplateByIndex(index);
|
||||||
/// Create a new distributed resource.
|
//events[index]?.Invoke(this, args);
|
||||||
/// </summary>
|
emitArgs(et.name, args);
|
||||||
/// <param name="connection">Connection responsible for the distributed resource.</param>
|
|
||||||
/// <param name="template">Resource template.</param>
|
|
||||||
/// <param name="instanceId">Instance Id given by the other end.</param>
|
|
||||||
/// <param name="age">Resource age.</param>
|
|
||||||
DistributedResource(DistributedConnection connection, int instanceId, int age, String link)
|
|
||||||
{
|
|
||||||
this._link = link;
|
|
||||||
this._connection = connection;
|
|
||||||
this._instanceId = instanceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
//void _ready()
|
instance.emitResourceEvent(null, null, et.name, args);
|
||||||
//{
|
}
|
||||||
// _isReady = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// <summary>
|
AsyncReply<dynamic> invokeByNamedArguments(int index, Structure namedArgs) {
|
||||||
/// Export all properties with ResourceProperty attributed as bytes array.
|
if (_destroyed) throw new Exception("Trying to access destroyed object");
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
List<PropertyValue> serialize()
|
|
||||||
{
|
|
||||||
|
|
||||||
var props = new List<PropertyValue>(_properties.length);
|
if (_suspended) throw new Exception("Trying to access suspended object");
|
||||||
|
|
||||||
|
if (index >= instance.template.functions.length)
|
||||||
|
throw new Exception("Function index is incorrect");
|
||||||
|
|
||||||
for (var i = 0; i < _properties.length; i++)
|
return connection.sendInvokeByNamedArguments(_instanceId, index, namedArgs);
|
||||||
props[i] = new PropertyValue(_properties[i], instance.getAge(i), instance.getModificationDate(i));
|
}
|
||||||
|
|
||||||
return props;
|
AsyncReply<dynamic> invokeByArrayArguments(int index, List<dynamic> args) {
|
||||||
}
|
if (_destroyed) throw new Exception("Trying to access destroyed object");
|
||||||
|
|
||||||
bool attach(List<PropertyValue> properties)
|
if (_suspended) throw new Exception("Trying to access suspended object");
|
||||||
{
|
|
||||||
if (_attached)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_suspended = false;
|
|
||||||
|
|
||||||
_properties = new List(properties.length);// object[properties.Length];
|
if (index >= instance.template.functions.length)
|
||||||
|
throw new Exception("Function index is incorrect");
|
||||||
|
|
||||||
//_events = new DistributedResourceEvent[Instance.Template.Events.Length];
|
return connection.sendInvokeByArrayArguments(_instanceId, index, args);
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < properties.length; i++)
|
operator [](String index) {
|
||||||
{
|
var pt = instance.template.getPropertyTemplateByName(index);
|
||||||
instance.setAge(i, properties[i].age);
|
if (pt != null) return get(pt.index);
|
||||||
instance.setModificationDate(i, properties[i].date);
|
}
|
||||||
_properties[i] = properties[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// trigger holded events/property updates.
|
operator []=(String index, value) {
|
||||||
//foreach (var r in afterAttachmentTriggers)
|
var pt = instance.template.getPropertyTemplateByName(index);
|
||||||
// r.Key.Trigger(r.Value);
|
if (pt != null) set(pt.index, value);
|
||||||
|
}
|
||||||
|
|
||||||
//afterAttachmentTriggers.Clear();
|
String _getMemberName(Symbol symbol) {
|
||||||
|
var memberName = symbol.toString();
|
||||||
|
if (memberName.endsWith("=\")"))
|
||||||
|
return memberName.substring(8, memberName.length - 3);
|
||||||
|
else
|
||||||
|
return memberName.substring(8, memberName.length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
_attached = true;
|
@override //overring noSuchMethod
|
||||||
|
noSuchMethod(Invocation invocation) {
|
||||||
|
var memberName = _getMemberName(invocation.memberName);
|
||||||
|
|
||||||
if (_queued_updates.length > 0)
|
if (invocation.isMethod) {
|
||||||
{
|
var ft = instance.template.getFunctionTemplateByName(memberName);
|
||||||
_queued_updates.forEach((kv)=>updatePropertyByIndex(kv.key, kv.value));
|
|
||||||
_queued_updates.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (_attached && ft != null) {
|
||||||
|
if (invocation.namedArguments.length > 0) {
|
||||||
|
var namedArgs = new Structure();
|
||||||
|
for (var p in invocation.namedArguments.keys)
|
||||||
|
namedArgs[_getMemberName(p)] = invocation.namedArguments[p];
|
||||||
|
|
||||||
|
return invokeByNamedArguments(ft.index, namedArgs);
|
||||||
|
} else {
|
||||||
|
return invokeByArrayArguments(
|
||||||
|
ft.index, invocation.positionalArguments);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else if (invocation.isSetter) {
|
||||||
|
var pt = instance.template.getPropertyTemplateByName(memberName);
|
||||||
|
|
||||||
|
if (pt != null) {
|
||||||
|
set(pt.index, invocation.positionalArguments[0]);
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
void emitEventByIndex(int index, List<dynamic> args)
|
|
||||||
{
|
|
||||||
// neglect events when the object is not yet attached
|
|
||||||
if (!_attached)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var et = instance.template.getEventTemplateByIndex(index);
|
|
||||||
//events[index]?.Invoke(this, args);
|
|
||||||
emitArgs(et.name, args);
|
|
||||||
|
|
||||||
instance.emitResourceEvent(null, null, et.name, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncReply<dynamic> invokeByNamedArguments(int index, Structure namedArgs)
|
|
||||||
{
|
|
||||||
if (_destroyed)
|
|
||||||
throw new Exception("Trying to access destroyed object");
|
|
||||||
|
|
||||||
if (_suspended)
|
|
||||||
throw new Exception("Trying to access suspended object");
|
|
||||||
|
|
||||||
if (index >= instance.template.functions.length)
|
|
||||||
throw new Exception("Function index is incorrect");
|
|
||||||
|
|
||||||
|
|
||||||
return connection.sendInvokeByNamedArguments(_instanceId, index, namedArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AsyncReply<dynamic> invokeByArrayArguments(int index, List<dynamic> args)
|
|
||||||
{
|
|
||||||
if (_destroyed)
|
|
||||||
throw new Exception("Trying to access destroyed object");
|
|
||||||
|
|
||||||
if (_suspended)
|
|
||||||
throw new Exception("Trying to access suspended object");
|
|
||||||
|
|
||||||
if (index >= instance.template.functions.length)
|
|
||||||
throw new Exception("Function index is incorrect");
|
|
||||||
|
|
||||||
|
|
||||||
return connection.sendInvokeByArrayArguments(_instanceId, index, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator [](String index)
|
|
||||||
{
|
|
||||||
var pt = instance.template.getPropertyTemplateByName(index);
|
|
||||||
if (pt != null)
|
|
||||||
return get(pt.index);
|
|
||||||
}
|
}
|
||||||
|
} else if (invocation.isGetter) {
|
||||||
|
var pt = instance.template.getPropertyTemplateByName(memberName);
|
||||||
|
|
||||||
operator []=(String index, value)
|
if (pt != null) {
|
||||||
{
|
return get(pt.index);
|
||||||
var pt = instance.template.getPropertyTemplateByName(index);
|
|
||||||
if (pt != null)
|
|
||||||
set(pt.index, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getMemberName(Symbol symbol)
|
|
||||||
{
|
|
||||||
var memberName = symbol.toString();
|
|
||||||
if (memberName.endsWith("=\")"))
|
|
||||||
return memberName.substring(8, memberName.length - 3);
|
|
||||||
else
|
|
||||||
return memberName.substring(8, memberName.length - 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override //overring noSuchMethod
|
return null;
|
||||||
noSuchMethod(Invocation invocation)
|
}
|
||||||
{
|
|
||||||
var memberName = _getMemberName(invocation.memberName);
|
|
||||||
|
|
||||||
if (invocation.isMethod)
|
|
||||||
{
|
|
||||||
var ft = instance.template.getFunctionTemplateByName(memberName);
|
|
||||||
|
|
||||||
if (_attached && ft!=null)
|
|
||||||
{
|
|
||||||
if (invocation.namedArguments.length > 0)
|
|
||||||
{
|
|
||||||
var namedArgs = new Structure();
|
|
||||||
for(var p in invocation.namedArguments.keys)
|
|
||||||
namedArgs[_getMemberName(p)] = invocation.namedArguments[p];
|
|
||||||
|
|
||||||
return invokeByNamedArguments(ft.index, namedArgs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return invokeByArrayArguments(ft.index, invocation.positionalArguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (invocation.isSetter)
|
|
||||||
{
|
|
||||||
var pt = instance.template.getPropertyTemplateByName(memberName);
|
|
||||||
|
|
||||||
if (pt != null)
|
/// <summary>
|
||||||
{
|
/// Get a property value.
|
||||||
set(pt.index, invocation.positionalArguments[0]);
|
/// </summary>
|
||||||
return true;
|
/// <param name="index">Zero-based property index.</param>
|
||||||
}
|
/// <returns>Value</returns>
|
||||||
}
|
get(int index) {
|
||||||
else if (invocation.isGetter)
|
if (index >= _properties.length) return null;
|
||||||
{
|
return _properties[index];
|
||||||
|
}
|
||||||
var pt = instance.template.getPropertyTemplateByName(memberName);
|
|
||||||
|
|
||||||
if (pt != null)
|
void updatePropertyByIndex(int index, dynamic value) {
|
||||||
{
|
if (!_attached) {
|
||||||
return get(pt.index);
|
_queued_updates.add(KeyValuePair(index, value));
|
||||||
}
|
} else {
|
||||||
}
|
var pt = instance.template.getPropertyTemplateByIndex(index);
|
||||||
|
_properties[index] = value;
|
||||||
return null;
|
instance.emitModification(pt, value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set property value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">Zero-based property index.</param>
|
||||||
|
/// <param name="value">Value</param>
|
||||||
|
/// <returns>Indicator when the property is set.</returns>
|
||||||
|
AsyncReply<dynamic> set(int index, dynamic value) {
|
||||||
|
if (index >= _properties.length) return null;
|
||||||
|
|
||||||
|
var reply = new AsyncReply<dynamic>();
|
||||||
|
|
||||||
/// <summary>
|
var parameters = Codec.compose(value, connection);
|
||||||
/// Get a property value.
|
connection
|
||||||
/// </summary>
|
.sendRequest(IIPPacketAction.SetProperty)
|
||||||
/// <param name="index">Zero-based property index.</param>
|
.addUint32(_instanceId)
|
||||||
/// <returns>Value</returns>
|
.addUint8(index)
|
||||||
get(int index)
|
.addDC(parameters)
|
||||||
{
|
.done()
|
||||||
if (index >= _properties.length)
|
.then((res) {
|
||||||
return null;
|
// not really needed, server will always send property modified,
|
||||||
return _properties[index];
|
// this only happens if the programmer forgot to emit in property setter
|
||||||
}
|
_properties[index] = value;
|
||||||
|
reply.trigger(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply;
|
||||||
void updatePropertyByIndex(int index, dynamic value)
|
}
|
||||||
{
|
}
|
||||||
if (!_attached)
|
|
||||||
{
|
|
||||||
_queued_updates.add(KeyValuePair(index, value));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var pt = instance.template.getPropertyTemplateByIndex(index);
|
|
||||||
_properties[index] = value;
|
|
||||||
instance.emitModification(pt, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set property value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="index">Zero-based property index.</param>
|
|
||||||
/// <param name="value">Value</param>
|
|
||||||
/// <returns>Indicator when the property is set.</returns>
|
|
||||||
AsyncReply<dynamic> set(int index, dynamic value)
|
|
||||||
{
|
|
||||||
if (index >= _properties.length)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var reply = new AsyncReply<dynamic>();
|
|
||||||
|
|
||||||
var parameters = Codec.compose(value, connection);
|
|
||||||
connection.sendRequest(IIPPacketAction.SetProperty)
|
|
||||||
.addUint32(_instanceId)
|
|
||||||
.addUint8(index)
|
|
||||||
.addDC(parameters)
|
|
||||||
.done()
|
|
||||||
.then((res)
|
|
||||||
{
|
|
||||||
// not really needed, server will always send property modified,
|
|
||||||
// this only happens if the programmer forgot to emit in property setter
|
|
||||||
_properties[index] = value;
|
|
||||||
reply.trigger(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -231,8 +231,8 @@ class IIPAuthPacket
|
|||||||
}
|
}
|
||||||
else if (command == IIPAuthPacketCommand.Acknowledge)
|
else if (command == IIPAuthPacketCommand.Acknowledge)
|
||||||
{
|
{
|
||||||
remoteMethod = ((data[offset] >> 4) & 0x3);
|
remoteMethod = AuthenticationMethod.values[ ((data[offset] >> 4) & 0x3)];
|
||||||
localMethod = ((data[offset] >> 2) & 0x3);
|
localMethod = AuthenticationMethod.values[ ((data[offset] >> 2) & 0x3)];
|
||||||
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
var encrypt = ((data[offset++] & 0x2) == 0x2);
|
||||||
|
|
||||||
if (_notEnough(offset, ends, 1))
|
if (_notEnough(offset, ends, 1))
|
||||||
|
@ -35,12 +35,11 @@ abstract class IStore implements IResource
|
|||||||
{
|
{
|
||||||
AsyncReply<IResource> get(String path);
|
AsyncReply<IResource> get(String path);
|
||||||
AsyncReply<IResource> retrieve(int iid);
|
AsyncReply<IResource> retrieve(int iid);
|
||||||
bool put(IResource resource);
|
AsyncReply<bool> put(IResource resource);
|
||||||
String link(IResource resource);
|
String link(IResource resource);
|
||||||
bool record(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
|
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 modify(IResource resource, String propertyName, dynamic value, int age, DateTime dateTime);
|
||||||
bool remove(IResource resource);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -38,258 +38,223 @@ import 'ResourceTrigger.dart';
|
|||||||
import '../Net/IIP/DistributedConnection.dart';
|
import '../Net/IIP/DistributedConnection.dart';
|
||||||
|
|
||||||
// Centeral Resource Issuer
|
// Centeral Resource Issuer
|
||||||
class Warehouse
|
class Warehouse {
|
||||||
{
|
static AutoList<IResource, Instance> _stores =
|
||||||
static AutoList<IResource, Instance> _stores = new AutoList<IResource, Instance>(null);
|
new AutoList<IResource, Instance>(null);
|
||||||
static Map<int, IResource> _resources = new Map<int, IResource>();
|
static Map<int, IResource> _resources = new Map<int, IResource>();
|
||||||
static int resourceCounter = 0;
|
static int resourceCounter = 0;
|
||||||
|
|
||||||
static KeyList<Guid, ResourceTemplate> _templates = new KeyList<Guid, ResourceTemplate>();
|
static KeyList<Guid, ResourceTemplate> _templates =
|
||||||
|
new KeyList<Guid, ResourceTemplate>();
|
||||||
|
|
||||||
|
//public delegate void StoreConnectedEvent(IStore store, string name);
|
||||||
|
//public delegate void StoreDisconnectedEvent(IStore store);
|
||||||
|
|
||||||
//public delegate void StoreConnectedEvent(IStore store, string name);
|
//public static event StoreConnectedEvent StoreConnected;
|
||||||
//public delegate void StoreDisconnectedEvent(IStore store);
|
///public static event StoreDisconnectedEvent StoreDisconnected;
|
||||||
|
|
||||||
//public static event StoreConnectedEvent StoreConnected;
|
|
||||||
///public static event StoreDisconnectedEvent StoreDisconnected;
|
|
||||||
|
|
||||||
static bool _warehouseIsOpen = false;
|
static bool _warehouseIsOpen = false;
|
||||||
|
|
||||||
static KeyList<String, IStore Function()> protocols = _getSupportedProtocols();
|
static KeyList<String, AsyncReply<IStore> Function(String, dynamic)>
|
||||||
|
protocols = _getSupportedProtocols();
|
||||||
|
|
||||||
static final _urlRegex = RegExp(r'^(?:([^\s|:]*):\/\/([^\/]*)\/?(.*))');
|
static final _urlRegex = RegExp(r'^(?:([^\s|:]*):\/\/([^\/]*)\/?(.*))');
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a store by its name.
|
/// Get a store by its name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">Store instance name</param>
|
/// <param name="name">Store instance name</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static IStore getStore(String name)
|
static IStore getStore(String name) {
|
||||||
{
|
for (var s in _stores) if (s.instance.name == name) return s;
|
||||||
for(var s in _stores)
|
return null;
|
||||||
if (s.instance.name == name)
|
}
|
||||||
return s;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a resource by instance Id.
|
/// Get a resource by instance Id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id">Instance Id</param>
|
/// <param name="id">Instance Id</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
static AsyncReply<IResource> getById(int id)
|
static AsyncReply<IResource> getById(int id) {
|
||||||
{
|
if (_resources.containsKey(id))
|
||||||
if (_resources.containsKey(id))
|
return new AsyncReply<IResource>.ready(_resources[id]);
|
||||||
return new AsyncReply<IResource>.ready(_resources[id]);
|
else
|
||||||
else
|
return new AsyncReply<IResource>.ready(null);
|
||||||
return new AsyncReply<IResource>.ready(null);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open the warehouse.
|
/// Open the warehouse.
|
||||||
/// This function issues the initialize trigger to all stores and resources.
|
/// This function issues the initialize trigger to all stores and resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True, if no problem occurred.</returns>
|
/// <returns>True, if no problem occurred.</returns>
|
||||||
static AsyncReply<bool> open()
|
static AsyncReply<bool> open() {
|
||||||
{
|
var bag = new AsyncBag<bool>();
|
||||||
var bag = new AsyncBag<bool>();
|
|
||||||
|
|
||||||
|
for (var s in _stores) bag.add(s.trigger(ResourceTrigger.Initialize));
|
||||||
|
|
||||||
for(var s in _stores)
|
bag.seal();
|
||||||
bag.add(s.trigger(ResourceTrigger.Initialize));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bag.seal();
|
|
||||||
|
|
||||||
var rt = new AsyncReply<bool>();
|
|
||||||
bag.then((x)
|
|
||||||
{
|
|
||||||
for (var b in x)
|
|
||||||
if (!b)
|
|
||||||
{
|
|
||||||
rt.trigger(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var rBag = new AsyncBag<bool>();
|
|
||||||
for (var rk in _resources.keys)
|
|
||||||
rBag.add(_resources[rk].trigger(ResourceTrigger.SystemInitialized));
|
|
||||||
|
|
||||||
rBag.seal();
|
|
||||||
|
|
||||||
rBag.then((y)
|
|
||||||
{
|
|
||||||
for (var b in y)
|
|
||||||
if (!b)
|
|
||||||
{
|
|
||||||
rt.trigger(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rt.trigger(true);
|
|
||||||
_warehouseIsOpen = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Close the warehouse.
|
|
||||||
/// This function issues terminate trigger to all resources and stores.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True, if no problem occurred.</returns>
|
|
||||||
static AsyncReply<bool> close()
|
|
||||||
{
|
|
||||||
|
|
||||||
var bag = new AsyncBag<bool>();
|
|
||||||
|
|
||||||
for (var resource in _resources.values)
|
|
||||||
if (!(resource is IStore))
|
|
||||||
bag.add(resource.trigger(ResourceTrigger.Terminate));
|
|
||||||
|
|
||||||
for (var s in _stores)
|
|
||||||
bag.add(s.trigger(ResourceTrigger.Terminate));
|
|
||||||
|
|
||||||
for (var resource in _resources.values)
|
|
||||||
if (!(resource is IStore))
|
|
||||||
bag.add(resource.trigger(ResourceTrigger.SystemTerminated));
|
|
||||||
|
|
||||||
for (var store in _stores)
|
|
||||||
bag.add(store.trigger(ResourceTrigger.SystemTerminated));
|
|
||||||
|
|
||||||
bag.seal();
|
|
||||||
|
|
||||||
var rt = new AsyncReply<bool>();
|
|
||||||
bag.then((x)
|
|
||||||
{
|
|
||||||
for (var b in x)
|
|
||||||
if (!b)
|
|
||||||
{
|
|
||||||
rt.trigger(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rt.trigger(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static List<IResource> qureyIn(List<String> path, int index, AutoList<IResource, Instance> resources)
|
|
||||||
{
|
|
||||||
var rt = new List<IResource>();
|
|
||||||
|
|
||||||
if (index == path.length - 1)
|
|
||||||
{
|
|
||||||
if (path[index] == "")
|
|
||||||
for (var child in resources)
|
|
||||||
rt.add(child);
|
|
||||||
else
|
|
||||||
for (var child in resources)
|
|
||||||
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));
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var rt = new AsyncReply<List<IResource>>();
|
|
||||||
get(path).then((x)
|
|
||||||
{
|
|
||||||
var p = path.split('/');
|
|
||||||
|
|
||||||
if (x == null)
|
|
||||||
{
|
|
||||||
rt.trigger(qureyIn(p, 0, _stores));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var ar = qureyIn(p, 0, _stores).where((r) => r != x).toList();
|
|
||||||
ar.insert(0, x);
|
|
||||||
rt.trigger(ar);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
|
|
||||||
|
var rt = new AsyncReply<bool>();
|
||||||
|
bag.then((x) {
|
||||||
|
for (var b in x)
|
||||||
|
if (!b) {
|
||||||
|
rt.trigger(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var rBag = new AsyncBag<bool>();
|
||||||
|
for (var rk in _resources.keys)
|
||||||
|
rBag.add(_resources[rk].trigger(ResourceTrigger.SystemInitialized));
|
||||||
|
|
||||||
|
rBag.seal();
|
||||||
|
|
||||||
|
rBag.then((y) {
|
||||||
|
for (var b in y)
|
||||||
|
if (!b) {
|
||||||
|
rt.trigger(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.trigger(true);
|
||||||
|
_warehouseIsOpen = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Close the warehouse.
|
||||||
|
/// This function issues terminate trigger to all resources and stores.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True, if no problem occurred.</returns>
|
||||||
|
static AsyncReply<bool> close() {
|
||||||
|
var bag = new AsyncBag<bool>();
|
||||||
|
|
||||||
|
for (var resource in _resources.values)
|
||||||
|
if (!(resource is IStore))
|
||||||
|
bag.add(resource.trigger(ResourceTrigger.Terminate));
|
||||||
|
|
||||||
|
for (var s in _stores) bag.add(s.trigger(ResourceTrigger.Terminate));
|
||||||
|
|
||||||
|
for (var resource in _resources.values)
|
||||||
|
if (!(resource is IStore))
|
||||||
|
bag.add(resource.trigger(ResourceTrigger.SystemTerminated));
|
||||||
|
|
||||||
|
for (var store in _stores)
|
||||||
|
bag.add(store.trigger(ResourceTrigger.SystemTerminated));
|
||||||
|
|
||||||
|
bag.seal();
|
||||||
|
|
||||||
|
var rt = new AsyncReply<bool>();
|
||||||
|
bag.then((x) {
|
||||||
|
for (var b in x)
|
||||||
|
if (!b) {
|
||||||
|
rt.trigger(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.trigger(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<IResource> qureyIn(
|
||||||
|
List<String> path, int index, AutoList<IResource, Instance> resources) {
|
||||||
|
var rt = new List<IResource>();
|
||||||
|
|
||||||
|
if (index == path.length - 1) {
|
||||||
|
if (path[index] == "")
|
||||||
|
for (var child in resources) rt.add(child);
|
||||||
|
else
|
||||||
|
for (var child in resources)
|
||||||
|
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));
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
var rt = new AsyncReply<List<IResource>>();
|
||||||
|
get(path).then((x) {
|
||||||
|
var p = path.split('/');
|
||||||
|
|
||||||
|
if (x == null) {
|
||||||
|
rt.trigger(qureyIn(p, 0, _stores));
|
||||||
|
} else {
|
||||||
|
var ar = qureyIn(p, 0, _stores).where((r) => r != x).toList();
|
||||||
|
ar.insert(0, x);
|
||||||
|
rt.trigger(ar);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a resource by its path.
|
||||||
|
/// Resource path is sperated by '/' character, e.g. "system/http".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns>Resource instance.</returns>
|
||||||
|
static AsyncReply<dynamic> get(String path,
|
||||||
|
[attributes = null,
|
||||||
|
IResource parent = null,
|
||||||
|
IPermissionsManager manager = null]) {
|
||||||
|
var rt = AsyncReply<IResource>();
|
||||||
|
|
||||||
|
// 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 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);
|
||||||
|
}).error((e) {
|
||||||
|
rt.triggerError(e);
|
||||||
|
//Warehouse.remove(store);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!_warehouseIsOpen)
|
||||||
|
open().then((v) {
|
||||||
|
if (v)
|
||||||
|
getFromStore();
|
||||||
|
else
|
||||||
|
rt.trigger(null);
|
||||||
|
});
|
||||||
|
else
|
||||||
|
getFromStore();
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
query(path).then((rs) {
|
||||||
/// Get a resource by its path.
|
if (rs != null && rs.length > 0)
|
||||||
/// Resource path is sperated by '/' character, e.g. "system/http".
|
rt.trigger(rs[0]);
|
||||||
/// </summary>
|
else
|
||||||
/// <param name="path"></param>
|
rt.trigger(null);
|
||||||
/// <returns>Resource instance.</returns>
|
});
|
||||||
static AsyncReply<dynamic> get(String path, [attributes = null, IResource parent = null, IPermissionsManager manager = null])
|
|
||||||
{
|
|
||||||
var rt = new AsyncReply<IResource>();
|
|
||||||
|
|
||||||
// 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 store = handler();
|
|
||||||
put(store, url[2], null, parent, null, 0, manager, attributes);
|
|
||||||
|
|
||||||
store.trigger(ResourceTrigger.Open).then<dynamic>((x)
|
|
||||||
{
|
|
||||||
|
|
||||||
_warehouseIsOpen = true;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}).error((e)
|
|
||||||
{
|
|
||||||
rt.triggerError(e);
|
|
||||||
Warehouse.remove(store);
|
|
||||||
});
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
query(path).then((rs)
|
|
||||||
{
|
|
||||||
if (rs != null && rs.length > 0)
|
|
||||||
rt.trigger(rs[0]);
|
|
||||||
else
|
|
||||||
rt.trigger(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var p = path.split('/');
|
var p = path.split('/');
|
||||||
@ -359,154 +324,187 @@ class Warehouse
|
|||||||
|
|
||||||
return new AsyncReply<IResource>.ready(null);
|
return new AsyncReply<IResource>.ready(null);
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Put a resource in the warehouse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="resource">Resource instance.</param>
|
||||||
|
/// <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<bool> put(IResource resource, String name,
|
||||||
|
[IStore store = null,
|
||||||
|
IResource parent = null,
|
||||||
|
ResourceTemplate customTemplate = null,
|
||||||
|
int age = 0,
|
||||||
|
IPermissionsManager manager = null,
|
||||||
|
attributes = null]) {
|
||||||
|
var rt = AsyncReply<bool>();
|
||||||
|
|
||||||
|
resource.instance = new Instance(
|
||||||
|
resourceCounter++, name, resource, store, customTemplate, age);
|
||||||
|
|
||||||
|
if (attributes != null)
|
||||||
|
resource.instance.setAttributes(Structure.fromMap(attributes));
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else
|
||||||
|
parent.instance.children.add(resource);
|
||||||
|
|
||||||
|
var initResource = () {
|
||||||
|
_resources[resource.instance.id] = resource;
|
||||||
|
|
||||||
|
if (_warehouseIsOpen) {
|
||||||
|
resource.trigger(ResourceTrigger.Initialize).then<dynamic>((value) {
|
||||||
|
if (resource is IStore)
|
||||||
|
resource.trigger(ResourceTrigger.Open).then<dynamic>((value) {
|
||||||
|
rt.trigger(value);
|
||||||
|
}).error((ex) => rt.triggerError(ex));
|
||||||
|
else
|
||||||
|
rt.trigger(value);
|
||||||
|
}).error((ex) => rt.triggerError(ex));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (resource is IStore) {
|
||||||
|
_stores.add(resource);
|
||||||
|
initResource();
|
||||||
|
} else {
|
||||||
|
store.put(resource).then<dynamic>((value) {
|
||||||
|
if (value)
|
||||||
|
initResource();
|
||||||
|
else
|
||||||
|
rt.trigger(false);
|
||||||
|
}).error((ex) => rt.triggerError(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
return rt;
|
||||||
/// Put a resource in the warehouse.
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="resource">Resource instance.</param>
|
|
||||||
/// <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 void put(IResource resource, String name, [IStore store = null, IResource parent = null, ResourceTemplate customTemplate = null, int age = 0, IPermissionsManager manager = null, attributes = null])
|
|
||||||
{
|
|
||||||
resource.instance = new Instance(resourceCounter++, name, resource, store, customTemplate, age);
|
|
||||||
|
|
||||||
if (attributes != null)
|
static AsyncReply<T> New<T extends IResource>(T resource, String name,
|
||||||
resource.instance.setAttributes(Structure.fromMap(attributes));
|
[IStore store = null,
|
||||||
|
IResource parent = null,
|
||||||
if (manager != null)
|
IPermissionsManager manager = null,
|
||||||
resource.instance.managers.add(manager);
|
attributes = null,
|
||||||
|
properties = null]) {
|
||||||
if (store == parent)
|
if (properties != null) {
|
||||||
parent = null;
|
dynamic d = resource;
|
||||||
|
|
||||||
if (parent == null)
|
|
||||||
{
|
|
||||||
if (!(resource is IStore))
|
|
||||||
store.instance.children.add(resource);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
parent.instance.children.add(resource);
|
|
||||||
|
|
||||||
|
|
||||||
if (resource is IStore)
|
|
||||||
{
|
|
||||||
_stores.add(resource);
|
|
||||||
//StoreConnected?.Invoke(resource as IStore, name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
store.put(resource);
|
|
||||||
|
|
||||||
_resources[resource.instance.id] = resource;
|
|
||||||
|
|
||||||
if (_warehouseIsOpen)
|
|
||||||
resource.trigger(ResourceTrigger.Initialize);
|
|
||||||
|
|
||||||
|
for (var i = 0; i < properties.length; i++)
|
||||||
|
d[properties.keys.elementAt(i)] = properties.at(i);
|
||||||
|
//setProperty(resource, properties.keys.elementAt(i), properties.at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static T New<T extends IResource>(String name, [IStore store = null, IResource parent = null, IPermissionsManager manager = null, Structure attributes = null])
|
var rt = AsyncReply<T>();
|
||||||
{
|
|
||||||
/*
|
put(resource, name, store, parent, null, 0, manager, attributes)
|
||||||
|
.then<bool>((value) {
|
||||||
|
if (value)
|
||||||
|
rt.trigger(resource);
|
||||||
|
else
|
||||||
|
rt.trigger(null);
|
||||||
|
}).error((ex) => rt.triggerError(ex));
|
||||||
|
|
||||||
|
return rt;
|
||||||
|
|
||||||
|
/*
|
||||||
var type = ResourceProxy.GetProxy<T>();
|
var type = ResourceProxy.GetProxy<T>();
|
||||||
var res = Activator.CreateInstance(type) as IResource;
|
var res = Activator.CreateInstance(type) as IResource;
|
||||||
put(res, name, store, parent, null, 0, manager, attributes);
|
put(res, name, store, parent, null, 0, manager, attributes);
|
||||||
return (T)res;
|
return (T)res;
|
||||||
*/
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Put a resource template in the templates warehouse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="template">Resource template.</param>
|
||||||
|
static void putTemplate(ResourceTemplate template) {
|
||||||
|
if (!_templates.containsKey(template.classId))
|
||||||
|
_templates.add(template.classId, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a template by type from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">.Net type.</param>
|
||||||
|
/// <returns>Resource template.</returns>
|
||||||
|
static ResourceTemplate getTemplateByType(Type type) {
|
||||||
|
// loaded ?
|
||||||
|
for (var t in _templates.values)
|
||||||
|
if (t.className == type.toString()) return t;
|
||||||
|
|
||||||
|
var template = new ResourceTemplate.fromType(type);
|
||||||
|
_templates.add(template.classId, template);
|
||||||
|
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a template by class Id from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="classId">Class Id.</param>
|
||||||
|
/// <returns>Resource template.</returns>
|
||||||
|
static AsyncReply<ResourceTemplate> getTemplateByClassId(Guid classId) {
|
||||||
|
if (_templates.containsKey(classId))
|
||||||
|
return new AsyncReply<ResourceTemplate>.ready(_templates[classId]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a template by class name from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="className">Class name.</param>
|
||||||
|
/// <returns>Resource template.</returns>
|
||||||
|
static AsyncReply<ResourceTemplate> getTemplateByClassName(String className) {
|
||||||
|
for (var t in _templates.values)
|
||||||
|
if (t.className == className)
|
||||||
|
return new AsyncReply<ResourceTemplate>.ready(t);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool remove(IResource resource) {
|
||||||
|
if (resource.instance == null) return false;
|
||||||
|
|
||||||
|
if (_resources.containsKey(resource.instance.id))
|
||||||
|
_resources.remove(resource.instance.id);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (resource is IStore) {
|
||||||
|
_stores.remove(resource);
|
||||||
|
|
||||||
|
// remove all objects associated with the store
|
||||||
|
var toBeRemoved =
|
||||||
|
_resources.values.where((x) => x.instance.store == resource);
|
||||||
|
for (var o in toBeRemoved) remove(o);
|
||||||
|
|
||||||
|
// StoreDisconnected?.Invoke(resource as IStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
if (resource.instance.store != null)
|
||||||
/// Put a resource template in the templates warehouse.
|
resource.instance.store.remove(resource);
|
||||||
/// </summary>
|
|
||||||
/// <param name="template">Resource template.</param>
|
|
||||||
static void putTemplate(ResourceTemplate template)
|
|
||||||
{
|
|
||||||
if (!_templates.containsKey(template.classId))
|
|
||||||
_templates.add(template.classId, template);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
resource.destroy();
|
||||||
|
|
||||||
/// <summary>
|
return true;
|
||||||
/// Get a template by type from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="type">.Net type.</param>
|
|
||||||
/// <returns>Resource template.</returns>
|
|
||||||
static ResourceTemplate getTemplateByType(Type type)
|
|
||||||
{
|
|
||||||
// loaded ?
|
|
||||||
for (var t in _templates.values)
|
|
||||||
if (t.className == type.toString())
|
|
||||||
return t;
|
|
||||||
|
|
||||||
var template = new ResourceTemplate.fromType(type);
|
static KeyList<String, AsyncReply<IStore> Function(String, dynamic)>
|
||||||
_templates.add(template.classId, template);
|
_getSupportedProtocols() {
|
||||||
|
var rt =
|
||||||
return template;
|
new KeyList<String, AsyncReply<IStore> Function(String, dynamic)>();
|
||||||
}
|
rt.add(
|
||||||
|
"iip",
|
||||||
/// <summary>
|
(String name, attributes) => Warehouse.New<DistributedConnection>(
|
||||||
/// Get a template by class Id from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
DistributedConnection(), name, null, null, null, attributes));
|
||||||
/// </summary>
|
return rt;
|
||||||
/// <param name="classId">Class Id.</param>
|
}
|
||||||
/// <returns>Resource template.</returns>
|
|
||||||
static AsyncReply<ResourceTemplate> getTemplateByClassId(Guid classId)
|
|
||||||
{
|
|
||||||
if (_templates.containsKey(classId))
|
|
||||||
return new AsyncReply<ResourceTemplate>.ready(_templates[classId]);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get a template by class name from the templates warehouse. If not in the warehouse, a new ResourceTemplate is created and added to the warehouse.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="className">Class name.</param>
|
|
||||||
/// <returns>Resource template.</returns>
|
|
||||||
static AsyncReply<ResourceTemplate> getTemplateByClassName(String className)
|
|
||||||
{
|
|
||||||
for (var t in _templates.values)
|
|
||||||
if (t.className == className)
|
|
||||||
return new AsyncReply<ResourceTemplate>.ready(t);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool remove(IResource resource)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (resource.instance == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_resources.containsKey(resource.instance.id))
|
|
||||||
_resources.remove(resource.instance.id);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (resource is IStore)
|
|
||||||
{
|
|
||||||
_stores.remove(resource);
|
|
||||||
|
|
||||||
// remove all objects associated with the store
|
|
||||||
var toBeRemoved = _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);
|
|
||||||
|
|
||||||
resource.destroy();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static KeyList<String, IStore Function()> _getSupportedProtocols()
|
|
||||||
{
|
|
||||||
var rt = new KeyList<String, IStore Function()>();
|
|
||||||
rt.add("iip", () => new DistributedConnection());
|
|
||||||
return rt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
name: esiur
|
name: esiur
|
||||||
description: Distributed Object Framework.
|
description: Distributed Object Framework.
|
||||||
version: 1.2.4
|
version: 1.2.6
|
||||||
# author: Ahmed Zamil <ahmed@dijlh.com>
|
# author: Ahmed Zamil <ahmed@dijlh.com>
|
||||||
homepage: https://github.com/esiur/esiur-dart
|
homepage: https://github.com/esiur/esiur-dart
|
||||||
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.1.0 <3.0.0"
|
sdk: ">=2.1.0 <3.0.0"
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
test: ^1.14.2
|
test: ^1.14.2
|
||||||
|
|
||||||
|
@ -3,13 +3,14 @@ import 'package:esiur/esiur.dart';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
main() async {
|
main() async {
|
||||||
test("Connect to server", () async {
|
try {
|
||||||
// // // connect to the server
|
var x = await Warehouse.get("iip://localhost:5070/sys/cp",
|
||||||
var x = await Warehouse.get("iip://localhost:5000/sys/su",
|
|
||||||
{"username": "admin", "password": "1234", "domain": "example.com"});
|
{"username": "admin", "password": "1234", "domain": "example.com"});
|
||||||
|
|
||||||
print(x);
|
print(x);
|
||||||
});
|
} catch (ex) {
|
||||||
|
print("Error occured");
|
||||||
|
print(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// describe object
|
// describe object
|
||||||
|
Loading…
x
Reference in New Issue
Block a user