diff --git a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/Node.java b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/Node.java index 45c3a015..4dd6f47f 100644 --- a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/Node.java +++ b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/Node.java @@ -49,14 +49,14 @@ public class Node implements Externalizable { private boolean propertiesPopulated; private Object rawNodeData; - + /** * TODO */ public Node() { super(); } - + public Node(String nodeUri, String type) { setNodeUri(nodeUri); setType(type); diff --git a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/ResourceServiceRemote.java b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/ResourceServiceRemote.java index 7a2c1e6d..faa0ffec 100644 --- a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/ResourceServiceRemote.java +++ b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/ResourceServiceRemote.java @@ -15,6 +15,10 @@ */ package org.flowerplatform.core.node.remote; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; + import org.flowerplatform.core.CorePlugin; import org.flowerplatform.core.RemoteMethodInvocationListener; import org.flowerplatform.core.node.resource.ResourceService; @@ -27,7 +31,7 @@ */ public class ResourceServiceRemote { - public SubscriptionInfo subscribeToParentResource(String nodeUri) { + public SubscriptionInfo subscribeToParentResource(String nodeUri) { String sessionId = CorePlugin.getInstance().getRequestThreadLocal().get().getSession().getId(); return CorePlugin.getInstance().getResourceService() .subscribeToParentResource(sessionId, nodeUri, new ServiceContext(CorePlugin.getInstance().getResourceService())); diff --git a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/StylePropertyWrapper.java b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/StylePropertyWrapper.java index 285654ae..269de1e0 100644 --- a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/StylePropertyWrapper.java +++ b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/StylePropertyWrapper.java @@ -34,5 +34,9 @@ public StylePropertyWrapper setIsDefaultAs(boolean isDefault) { setIsDefault(isDefault); return this; } + + public StylePropertyWrapper() { + super(); + } } \ No newline at end of file diff --git a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/SubscriptionInfo.java b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/SubscriptionInfo.java index c6a2952a..2e3065e6 100644 --- a/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/SubscriptionInfo.java +++ b/org.flowerplatform.core/src/org/flowerplatform/core/node/remote/SubscriptionInfo.java @@ -26,6 +26,9 @@ public class SubscriptionInfo { private String resourceSet; + public SubscriptionInfo() { + } + public SubscriptionInfo(Node rootNode) { this(rootNode, null, null); } diff --git a/org.flowerplatform.flex_client.core/.flexLibProperties b/org.flowerplatform.flex_client.core/.flexLibProperties index 664a4bd8..ad14e181 100644 --- a/org.flowerplatform.flex_client.core/.flexLibProperties +++ b/org.flowerplatform.flex_client.core/.flexLibProperties @@ -7,7 +7,6 @@ - diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/CorePlugin.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/CorePlugin.as index c79285d0..bfb08ac1 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/CorePlugin.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/CorePlugin.as @@ -47,13 +47,13 @@ package org.flowerplatform.flex_client.core { import org.flowerplatform.flex_client.core.editor.remote.update.ChildrenUpdate; import org.flowerplatform.flex_client.core.editor.remote.update.PropertyUpdate; import org.flowerplatform.flex_client.core.editor.remote.update.Update; - import org.flowerplatform.flex_client.core.editor.resource.ResourceOperationsManager; + import org.flowerplatform.flex_client.core.editor.resource.ResourceOperationsHandler; import org.flowerplatform.flex_client.core.editor.ui.AboutView; import org.flowerplatform.flex_client.core.editor.ui.OpenNodeView; import org.flowerplatform.flex_client.core.link.ILinkHandler; import org.flowerplatform.flex_client.core.link.LinkView; import org.flowerplatform.flex_client.core.node.IServiceInvocator; - import org.flowerplatform.flex_client.core.node.NodeRegistryManager; + import org.flowerplatform.flex_client.core.node.NodeExternalInvocator; import org.flowerplatform.flex_client.core.node.controller.GenericValueProviderFromDescriptor; import org.flowerplatform.flex_client.core.node.controller.ResourceDebugControllers; import org.flowerplatform.flex_client.core.node.controller.TypeDescriptorRegistryDebugControllers; @@ -118,8 +118,6 @@ package org.flowerplatform.flex_client.core { public var globalMenuActionProvider:VectorActionProvider = new VectorActionProvider(); - public var nodeRegistryManager:NodeRegistryManager; - public var lastUpdateTimestampOfServer:Number = -1; public var lastUpdateTimestampOfClient:Number = -1; @@ -140,8 +138,12 @@ package org.flowerplatform.flex_client.core { return editorClassFactoryActionProvider; } - public function get resourceNodesManager():ResourceOperationsManager { - return ResourceOperationsManager(nodeRegistryManager.resourceOperationsManager.resourceOperationsHandler); + public function get nodeRegistryManager():* { + return _nodeRegistryManager; + } + + public function get resourceNodesManager():ResourceOperationsHandler { + return ResourceOperationsHandler(nodeRegistryManager.resourceOperationsManager.resourceOperationsHandler); } override public function preStart():void { @@ -164,9 +166,9 @@ package org.flowerplatform.flex_client.core { serviceLocator.addService("uploadService"); serviceLocator.addService("preferenceService"); - var resourceOperationsHandler:ResourceOperationsManager = new ResourceOperationsManager(); - nodeRegistryManager = new NodeRegistryManager(resourceOperationsHandler, IServiceInvocator(serviceLocator), resourceOperationsHandler); - + var resourceOperationsHandler:ResourceOperationsHandler = new ResourceOperationsHandler(); + _nodeRegistryManager = new NodeRegistryManager(resourceOperationsHandler, IServiceInvocator(serviceLocator), new NodeExternalInvocator()); + updateTimer = new UpdateTimer(5000); FlexUtilGlobals.getInstance().registerAction(RemoveNodeAction); @@ -549,3 +551,7 @@ package org.flowerplatform.flex_client.core { } } + +include "../../../../../../org.flowerplatform.js_client.core/WebContent/js/node_registry/ResourceOperationsManager.js"; +include "../../../../../../org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistryManager.js"; +include "../../../../../../org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistry.js"; diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/EditorFrontend.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/EditorFrontend.as index 1a339bc5..d8f834d8 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/EditorFrontend.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/EditorFrontend.as @@ -23,10 +23,8 @@ package org.flowerplatform.flex_client.core.editor { import spark.components.VGroup; import org.flowerplatform.flex_client.core.CorePlugin; - import org.flowerplatform.flex_client.core.editor.action.NodeTypeActionProvider; import org.flowerplatform.flex_client.core.editor.remote.Node; import org.flowerplatform.flex_client.core.node.INodeRegistryManagerListener; - import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flexutil.FlexUtilGlobals; import org.flowerplatform.flexutil.action.ComposedActionProvider; import org.flowerplatform.flexutil.action.IAction; @@ -49,7 +47,7 @@ package org.flowerplatform.flex_client.core.editor { protected var _viewHost:IViewHost; - public var nodeRegistry:NodeRegistry; + public var nodeRegistry:*; public function EditorFrontend() { super(); @@ -120,14 +118,14 @@ package org.flowerplatform.flex_client.core.editor { // nothing to do } - public function nodeRegistryRemoved(nodeRegistry:NodeRegistry):void { + public function nodeRegistryRemoved(nodeRegistry:*):void { if (this.nodeRegistry == nodeRegistry) { var workbench:IWorkbench = FlexUtilGlobals.getInstance().workbench; workbench.closeView(workbench.getViewComponentForEditor(this), true, false); } } - public function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:NodeRegistry):void { + public function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:*):void { // do nothing } diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/remote/update/Update.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/remote/update/Update.as index df785b0e..00be0568 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/remote/update/Update.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/remote/update/Update.as @@ -15,7 +15,6 @@ */ package org.flowerplatform.flex_client.core.editor.remote.update { import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.node.NodeRegistry; /** * @author Cristina Constantinescu @@ -29,7 +28,7 @@ package org.flowerplatform.flex_client.core.editor.remote.update { public var timestamp:Number; - public function apply(nodeRegistry:NodeRegistry, node:Node):void { + public function apply(nodeRegistry:*, node:Node):void { // do nothing } diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceNodesListView.mxml b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceNodesListView.mxml index 870e02df..c961ce60 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceNodesListView.mxml +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceNodesListView.mxml @@ -70,7 +70,7 @@ protected function setAllSelected(value:Boolean):void { for (var i:int = 0; i < resourceNodes.length; i++) { - var resourceNodeData:ResourceNode = ResourceNode(resourceNodes.getItemAt(i)); + var resourceNodeData:Object = resourceNodes.getItemAt(i); resourceNodeData.selected = value; } } @@ -78,7 +78,7 @@ protected function yesButton_clickHandler(event:MouseEvent):void { var invokedServerMethod:Boolean = false; for (var i:int = 0; i < resourceNodes.length; i++) { - var resourceNodeData:ResourceNode = ResourceNode(resourceNodes.getItemAt(i)); + var resourceNodeData:Object = resourceNodes.getItemAt(i); if (resourceNodeData.selected) { // invoke service method and wait for result to close the view CorePlugin.getInstance().serviceLocator.invoke(serverMethodToInvokeForSelection, [resourceNodeData.resourceNodeId], function(data:Object):void { diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsManager.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsHandler.as similarity index 81% rename from org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsManager.as rename to org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsHandler.as index b5a823f0..971b93d5 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsManager.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/resource/ResourceOperationsHandler.as @@ -1,18 +1,18 @@ /* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ +* +* Copyright (C) 2008 - 2013 Crispico Software, . +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation version 3. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details, at . +* +* license-end +*/ package org.flowerplatform.flex_client.core.editor.resource { import mx.collections.ArrayList; import mx.collections.IList; @@ -23,35 +23,33 @@ package org.flowerplatform.flex_client.core.editor.resource { import org.flowerplatform.flex_client.core.editor.action.ReloadAction; import org.flowerplatform.flex_client.core.editor.action.SaveAction; import org.flowerplatform.flex_client.core.editor.action.SaveAllAction; - import org.flowerplatform.flex_client.core.node.IExternalInvocator; import org.flowerplatform.flex_client.core.node.IResourceOperationsHandler; import org.flowerplatform.flex_client.resources.Resources; import org.flowerplatform.flexutil.FlexUtilGlobals; import org.flowerplatform.flexutil.layout.IWorkbench; import org.flowerplatform.flexutil.layout.event.ActiveViewChangedEvent; import org.flowerplatform.flexutil.layout.event.ViewsRemovedEvent; - import org.flowerplatform.flex_client.core.node.NodeRegistryManager; /** * @author Cristina Constantinescu * @author Mariana Gheorghe */ - public class ResourceOperationsManager implements IResourceOperationsHandler, IExternalInvocator { - + public class ResourceOperationsHandler implements IResourceOperationsHandler { + public var saveAction:SaveAction = new SaveAction(); public var saveAllAction:SaveAllAction = new SaveAllAction(); public var reloadAction:ReloadAction = new ReloadAction(); - - private var _nodeRegistryManager:NodeRegistryManager; - - public function get nodeRegistryManager():NodeRegistryManager { + + private var _nodeRegistryManager:*; + + public function get nodeRegistryManager():* { return _nodeRegistryManager; } - - public function set nodeRegistryManager(value:NodeRegistryManager):void { + + public function set nodeRegistryManager(value:*):void { _nodeRegistryManager = value; } - + public function activeViewChangedHandler(evt:ActiveViewChangedEvent):void { updateEditorFrontendActionsEnablement(); } @@ -106,7 +104,7 @@ package org.flowerplatform.flex_client.core.editor.resource { public function getResourceNodeLabel(resourceNodeId:String):String { return resourceNodeId; } - + /** * Don't remove editors immediately. If there are dirty editors, show save dialog. */ @@ -124,7 +122,7 @@ package org.flowerplatform.flex_client.core.editor.resource { } _nodeRegistryManager.resourceOperationsManager.showSaveDialog(nodeRegistries); } - + /** * If at least one dirty resourceNode found, shows the save dialog, else closes the editors OR @@ -156,7 +154,7 @@ package org.flowerplatform.flex_client.core.editor.resource { public function showReloadDialog(nodeRegistries:Array = null, resourceSets:Array = null):void { var resourceNodes:ArrayList = new ArrayList(); for each (var resourceSet:String in resourceSets) { - resourceNodes.addItem(new ResourceNode(resourceSet, true)); + resourceNodes.addItem({resourceNodeId: resourceSet, selected:true}); } var reloadView:ResourceNodesListView = new ResourceNodesListView(); @@ -178,7 +176,7 @@ package org.flowerplatform.flex_client.core.editor.resource { .setHeight(small ? 150 : 300) .show(); } - + /** * @return global dirty state for all open editors = saveAll action enablement. */ @@ -186,14 +184,5 @@ package org.flowerplatform.flex_client.core.editor.resource { return saveAllAction != null ? saveAllAction.enabled : false; } - public function showMessageBox(text:String, title:String):void { - FlexUtilGlobals.getInstance().messageBoxFactory.createMessageBox() - .setText(text) - .setTitle(title) - .setWidth(300) - .setHeight(200) - .showMessageBox(); - } - } } \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/ui/UploadView.mxml b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/ui/UploadView.mxml index e9c5e563..7c1e9c76 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/ui/UploadView.mxml +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/editor/ui/UploadView.mxml @@ -25,21 +25,17 @@ . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ package org.flowerplatform.flex_client.core.node { + import mx.collections.ArrayCollection; + + import org.flowerplatform.flex_client.core.editor.remote.FullNodeIdWithChildren; + import org.flowerplatform.flex_client.core.node.remote.ServiceContext; /** * @author Cristina Constantinescu */ public interface IExternalInvocator { - - function showMessageBox(text:String, title:String):void; - + + function getNewListInstance():ArrayCollection; + + function getNewFullNodeIdWithChildrenInstance():FullNodeIdWithChildren; + + function getServiceContextInstance():ServiceContext; + + function showMessageBox(titleKeyMessage:String, textKeyMessage:String, textParams:Array):void; + + function createUpdateEvent(source:Object, property:String, oldValue:Object, newValue:Object):Object; + + function addEventListener(source:Object, eventType:String, handler:Function):void; + + function removeEventListener(source:Object, eventType:String, handler:Function):void; + } } \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/INodeRegistryManagerListener.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/INodeRegistryManagerListener.as index be6989a6..386ae9af 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/INodeRegistryManagerListener.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/INodeRegistryManagerListener.as @@ -20,9 +20,9 @@ package org.flowerplatform.flex_client.core.node { */ public interface INodeRegistryManagerListener { - function nodeRegistryRemoved(nodeRegistry:NodeRegistry):void; + function nodeRegistryRemoved(nodeRegistry:*):void; - function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:NodeRegistry):void; + function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:*):void; } } \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/IResourceOperationsHandler.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/IResourceOperationsHandler.as index 1b4accf0..b539f8d7 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/IResourceOperationsHandler.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/IResourceOperationsHandler.as @@ -21,8 +21,8 @@ package org.flowerplatform.flex_client.core.node { */ public interface IResourceOperationsHandler { - function get nodeRegistryManager():NodeRegistryManager; - function set nodeRegistryManager(value:NodeRegistryManager):void; + function get nodeRegistryManager():*; + function set nodeRegistryManager(value:*):void; function updateGlobalDirtyState(someResourceNodeHasBecomeDirty:Boolean):void; diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeExternalInvocator.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeExternalInvocator.as new file mode 100644 index 00000000..8605649f --- /dev/null +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeExternalInvocator.as @@ -0,0 +1,51 @@ +package org.flowerplatform.flex_client.core.node { + import flash.events.IEventDispatcher; + + import mx.collections.ArrayCollection; + import mx.events.PropertyChangeEvent; + + import org.flowerplatform.flex_client.core.editor.remote.FullNodeIdWithChildren; + import org.flowerplatform.flex_client.core.node.remote.ServiceContext; + import org.flowerplatform.flex_client.resources.Resources; + import org.flowerplatform.flexutil.FlexUtilGlobals; + + /** + * @author Cristina Constantinescu + */ + public class NodeExternalInvocator implements IExternalInvocator { + + public function showMessageBox(titleKeyMessage:String, textKeyMessage:String, textParams:Array):void { + FlexUtilGlobals.getInstance().messageBoxFactory.createMessageBox() + .setText(Resources.getMessage(textKeyMessage, textParams)) + .setTitle(Resources.getMessage(titleKeyMessage)) + .setWidth(300) + .setHeight(200) + .showMessageBox(); + } + + public function addEventListener(source:Object, eventType:String, handler:Function):void { + IEventDispatcher(source).addEventListener(eventType, handler); + } + + public function createUpdateEvent(source:Object, property:String, oldValue:Object, newValue:Object):Object { + return PropertyChangeEvent.createUpdateEvent(source, property, oldValue, newValue); + } + + public function getNewFullNodeIdWithChildrenInstance():FullNodeIdWithChildren { + return new FullNodeIdWithChildren(); + } + + public function getNewListInstance():ArrayCollection { + return new ArrayCollection(); + } + + public function getServiceContextInstance():ServiceContext { + return new ServiceContext(); + } + + public function removeEventListener(source:Object, eventType:String, handler:Function):void { + IEventDispatcher(source).removeEventListener(eventType, handler); + } + + } +} \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistry.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistry.as deleted file mode 100644 index a06092c0..00000000 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistry.as +++ /dev/null @@ -1,396 +0,0 @@ -/* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ -package org.flowerplatform.flex_client.core.node { - import flash.events.EventDispatcher; - import flash.utils.Dictionary; - - import mx.collections.ArrayCollection; - import mx.collections.IList; - import mx.core.mx_internal; - import mx.utils.ObjectUtil; - - import org.flowerplatform.flex_client.core.CoreConstants; - import org.flowerplatform.flex_client.core.editor.remote.FullNodeIdWithChildren; - import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.editor.remote.NodeWithChildren; - import org.flowerplatform.flex_client.core.editor.remote.update.ChildrenUpdate; - import org.flowerplatform.flex_client.core.editor.remote.update.PropertyUpdate; - import org.flowerplatform.flex_client.core.editor.remote.update.Update; - import org.flowerplatform.flex_client.core.node.remote.ServiceContext; - - use namespace mx_internal; - - /** - * Holds a node registry (id -> Node) and handles the communication with the server. - * - *

- * This class is responsible for maintaing a consistent node tree.
- * E.g. when new nodes arrive from server, they are added in the registry and "linked" with their parent. When nodes are - * removed (e.g. node collapsed), they are removed from the registry and unlinked from their parents. - * - * @author Cristina Constantinescu - * @author Mariana Gheorghe - */ - public class NodeRegistry extends EventDispatcher { - - protected var registry:Dictionary = new Dictionary(); - - protected var rootNodeUri:String; - - protected var nodeChangeListeners:IList = new ArrayCollection(); - - protected var nodeRegistryManager:NodeRegistryManager; - - public function NodeRegistry(nodeRegistryManager:NodeRegistryManager) { - this.nodeRegistryManager = nodeRegistryManager; - } - - public function getRootNodeUri():String { - return rootNodeUri; - } - - public function getNodeById(id:String):Node { - return Node(registry[id]); - } - - public function addNodeChangeListener(listener:INodeChangeListener):void { - nodeChangeListeners.addItem(listener); - } - - public function collapse(node:Node, refreshChildren:Boolean = true):void { - if (!registry.hasOwnProperty(node.nodeUri)) { - return; - } - if (node.children == null) { - return; - } - while (node.children != null) { - unregisterNode(Node(node.children.getItemAt(0)), node); - } - } - - public function expand(node:Node, context:Object):void { - if (!registry.hasOwnProperty(node.nodeUri)) { - return; - } - - var serviceContext:ServiceContext = new ServiceContext(); - if (context != null) { - for (var key:Object in context) { - serviceContext.context[key] = context[key]; - } - } - serviceContext.add(CoreConstants.POPULATE_WITH_PROPERTIES, true); - - nodeRegistryManager.serviceInvocator.invoke( - "nodeService.getChildren", - [node.nodeUri, serviceContext], - function (result:Object):void { - expandCallbackHandler(node, ArrayCollection(result)); - - // additional handler to be executed - if (context != null && context.hasOwnProperty(CoreConstants.HANDLER)) { - context[CoreConstants.HANDLER](); - } - }); - } - - /** - * Handles updates received from server. - * - * There are 2 cases: - *

    - *
  • updates == null (server cannot provide any updates because no updates were registered before timestampOfLastRequest), a full refresh is needed
  • - *
  • otherwise - *
      - *
    • property update (PropertyUpdate) -> set/unset property from Node.properties
      - * A NodeUpdatedEvent is dispatched at the end; it contains all updated & removed properties keys. - *
    • child added (ChildrenUpdate.ADDED) -> adds new node in parent as last child OR, if targetNodeAddedBefore set, before given child's index. - *
    • child removed (ChildrenUpdate.REMOVED) -> removes node from parent - *
    - *
- * - * Note: If a given fullNodeId doesn't exist in nodeRegistry, it means it isn't visible for current client, so ignore it. - */ - public function processUpdates(updates:ArrayCollection):void { - if (updates == null) { - // refresh all from root node (node.parent == null) - for (var fullNodeId:Object in registry) { - var node:Node = Node(registry[fullNodeId]); - if (node.parent == null) { - refresh(node); - } - } - return; - } - - for (var i:int = updates.length - 1; i >= 0; i--) { - var update:Update = Update(updates.getItemAt(i)); - var nodeFromRegistry:Node = getNodeById(update.fullNodeId); - if (nodeFromRegistry == null) { // node not registered, probably it isn't visible for this client - continue; - } - - switch (update.type) { - case CoreConstants.UPDATE_PROPERTY: - var propertyUpdate:PropertyUpdate = PropertyUpdate(update); - - if (propertyUpdate.isUnset) { - delete nodeFromRegistry.properties[propertyUpdate.key]; - } else { - setPropertyValue(nodeFromRegistry, propertyUpdate.key, propertyUpdate.value); - } - break; - case CoreConstants.UPDATE_CHILD_ADDED: - if (nodeFromRegistry.children != null && !nodeFromRegistry.children.contains(getNodeById(ChildrenUpdate(update).targetNode.nodeUri))) { - var index:Number = -1; // -> add it last - if (ChildrenUpdate(update).fullTargetNodeAddedBeforeId != null) { - // get targetNodeAddedBefore from registry - var targetNodeAddedBeforeInRegistry:Node = getNodeById(ChildrenUpdate(update).fullTargetNodeAddedBeforeId); - if (targetNodeAddedBeforeInRegistry != null) { // exists, get its index in children list - index = nodeFromRegistry.children.getItemIndex(targetNodeAddedBeforeInRegistry); - } - } - registerNode(ChildrenUpdate(update).targetNode, nodeFromRegistry, index); - } else { - // child already added, probably after refresh - // e.g. I add a children, I expand => I get the list with the new children; when the - // client polls for data, this children will be received as well, and thus duplicated. - // NOTE: since the instant notifications for the client that executed => this doesn't apply - // for him; but for other clients yes - - // Nothing to do - } - break; - case CoreConstants.UPDATE_CHILD_REMOVED: - // children update - var targetNodeInRegistry:Node = getNodeById(ChildrenUpdate(update).targetNode.nodeUri); - - if (targetNodeInRegistry != null) { - unregisterNode(targetNodeInRegistry, nodeFromRegistry); - } else { - // node not registered, probably it isn't visible for this client - // Nothing to do - } - break; - case CoreConstants.UPDATE_REQUEST_REFRESH: - refresh(nodeFromRegistry); - break; - default: - update.apply(this, nodeFromRegistry); - } - } - } - - public function refresh(node:Node):void { - if (!registry.hasOwnProperty(node.nodeUri)) { - return; - } - nodeRegistryManager.serviceInvocator.invoke( - "nodeService.refresh", - [getFullNodeIdWithChildren(node)], - function (result:Object):void { - refreshHandler(node, NodeWithChildren(result)); - }); - } - - /** - * @return an hierarchical structure of fullNodeIds starting from node. - */ - protected function getFullNodeIdWithChildren(node:Node):FullNodeIdWithChildren { - var fullNodeIdWithChildren:FullNodeIdWithChildren = new FullNodeIdWithChildren(); - fullNodeIdWithChildren.fullNodeId = node.nodeUri; - - if (node.children != null) { - for each (var child:Node in node.children) { - if (fullNodeIdWithChildren.visibleChildren == null) { - fullNodeIdWithChildren.visibleChildren = new ArrayCollection(); - } - fullNodeIdWithChildren.visibleChildren.addItem(getFullNodeIdWithChildren(child)); - } - } - return fullNodeIdWithChildren; - } - - /** - * Handles refresh response from server. - * - * For each node: - *
    - *
  • re-set its properties and dispatch a NodeUpdateEvent without specifying the updated & removed properties keys - *
  • if no new children, remove all current node's children - *
  • else, iterate on current list - *
      - *
    • if current child id exists in new list -> get its new structure - *
    • else -> remove current child - *
    - *
  • at this point, the current list will contain only the children that haven't been removed - *
  • next, iterate on new list, there are 2 cases: - *
      - *
    • child added -> add new child in current list at the same index - *
    • child moved to a different index -> remove child from current index, add it to new index - *
    - *
- */ - protected function refreshHandler(node:Node, nodeWithVisibleChildren:NodeWithChildren):void { - // set new node properties and dispatch event - var nodeFromRegistry:Node = getNodeById(node.nodeUri); - setNodeProperties(nodeFromRegistry, nodeWithVisibleChildren.node.properties); - - var newNodeToCurrentNodeIndex:Dictionary = new Dictionary(); - var i:int; - var currentChildNode:Node; - - // no children -> remove the old ones - if (nodeWithVisibleChildren.children == null) { - collapse(node, false); - return; - } - - if (node.children != null) { // node has children -> merge current list with new list - // serch for children that doesn't exist in new list - var currentChildren:ArrayCollection = node.children != null ? new ArrayCollection(node.children.toArray()) : new ArrayCollection(); - for (i = 0; i < currentChildren.length; i++) { - var exists:Boolean = false; - currentChildNode = Node(currentChildren.getItemAt(i)); - for each (var newChildWithVisibleChildren:NodeWithChildren in nodeWithVisibleChildren.children) { - if (currentChildNode.nodeUri == newChildWithVisibleChildren.node.nodeUri) { - exists = true; - break; - } - } - if (exists) { - // child exists -> refresh its structure - refreshHandler(currentChildNode, newChildWithVisibleChildren); - // store, for the new child, its index in current list - newNodeToCurrentNodeIndex[newChildWithVisibleChildren.node.nodeUri] = i; - } else { - // child doesn't exist in new list -> remove it from parent - unregisterNode(currentChildNode, node); - } - } - } - - for (i = 0; i < nodeWithVisibleChildren.children.length; i++) { - var newChildNode:Node = NodeWithChildren(nodeWithVisibleChildren.children.getItemAt(i)).node; - if (!newNodeToCurrentNodeIndex.hasOwnProperty(newChildNode.nodeUri)) { // new child doesn't exist in current list -> add it - registerNode(newChildNode, node, i); - } else if (newNodeToCurrentNodeIndex[newChildNode.nodeUri] != i) { // new child exists in current list, but different indexes -> get current child and move it to new index - currentChildNode = getNodeById(newChildNode.nodeUri); - unregisterNode(currentChildNode, node); - registerNode(currentChildNode, node, i); - } - } - } - - mx_internal function mergeOrRegisterNode(node:Node):Node { - var existingNode:Node = getNodeById(node.nodeUri); - if (existingNode == null) { - registerNode(node, null); - return node; - } - setNodeProperties(existingNode, node.properties); - - return existingNode; - } - - /** - * Adds node to parent at given index and registers it in registry.
- * - * If parent is null, the node will only be registered - * If index is -1, the node will be added last. - */ - mx_internal function registerNode(node:Node, parent:Node, index:int = -1):void { - if (rootNodeUri == null) { - rootNodeUri = node.nodeUri; - } - - registry[node.nodeUri] = node; - - if (parent != null) { - node.parent = parent; - if (parent.children == null) { - parent.children = new ArrayCollection(); - } - if (index != -1) { - parent.children.addItemAt(node, index); - } else { - parent.children.addItem(node); - } - } - - for each (var listener:INodeChangeListener in nodeChangeListeners) { - listener.nodeAdded(node); - } - } - - /** - * Removes node from parent and un-registers it from registry. - */ - mx_internal function unregisterNode(node:Node, parent:Node = null):void { - if (parent != null && (parent.children == null || !parent.children.contains(node))) { - // not expanded or child already removed - return; - } - // remove children recursive - collapse(node, false); - - var nodeFromRegistry:Node = registry[node.nodeUri]; - if (nodeFromRegistry != null) { - delete registry[node.nodeUri]; - } - - if (parent != null) { - // remove from parent list of children - parent.children.removeItemAt(parent.children.getItemIndex(node)); - if (parent.children.length == 0) { // parent has no children left -> parent is leaf - parent.children = null; - } - } - for each (var listener:INodeChangeListener in nodeChangeListeners) { - listener.nodeRemoved(node); - } - } - - mx_internal function expandCallbackHandler(node:Node, children:ArrayCollection):void { - if (children == null) { - return; - } - - // register each child - for each (var child:Node in children) { - registerNode(child, node); - } - } - - public function setPropertyValue(node:Node, property:String, newValue:Object):void { - var oldValue:Object = node.properties.hasOwnProperty(property) ? node.properties[property] : null; - node.properties[property] = newValue; - - for each (var listener:INodeChangeListener in nodeChangeListeners) { - listener.nodeUpdated(node, property, oldValue, newValue); - } - } - - protected function setNodeProperties(node:Node, newProperties:Object):void { - var classInfoProperties:Array = ObjectUtil.getClassInfo(newProperties).properties as Array; - for each (var property:String in classInfoProperties) { - setPropertyValue(node, property, newProperties[property]); - } - } - - } -} diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistryManager.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistryManager.as deleted file mode 100644 index a38fcbdd..00000000 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/NodeRegistryManager.as +++ /dev/null @@ -1,421 +0,0 @@ -/* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ -package org.flowerplatform.flex_client.core.node { - import flash.utils.Dictionary; - - import mx.collections.ArrayCollection; - import mx.collections.IList; - import mx.core.mx_internal; - import mx.events.PropertyChangeEvent; - import mx.rpc.events.FaultEvent; - - import org.flowerplatform.flex_client.core.CoreConstants; - import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.editor.remote.SubscriptionInfo; - import org.flowerplatform.flex_client.resources.Resources; - import org.flowerplatform.flexutil.Pair; - - /** - * @author Cristina Constantinescu - */ - public class NodeRegistryManager { - - /** - * Keep maps between node registries and their resource node ids and vice versa. - */ - private var resourceSetToNodeRegistries:Dictionary = new Dictionary(); - private var nodeRegistryToResourceUris:Dictionary = new Dictionary(); - - private var resourceSetToResourceUris:Dictionary = new Dictionary(); - private var resourceUriToResourceSet:Dictionary = new Dictionary(); - - public var resourceOperationsManager:ResourceOperationsManagerJs; - public var serviceInvocator:IServiceInvocator; - public var externalInvocator:IExternalInvocator; - - public var listeners:IList = new ArrayCollection(); - - public function NodeRegistryManager(resourceOperationsHandler:IResourceOperationsHandler, serviceInvocator:IServiceInvocator, externalInvocator:IExternalInvocator) { - this.resourceOperationsManager = new ResourceOperationsManagerJs(this, resourceOperationsHandler); - this.serviceInvocator = serviceInvocator; - this.externalInvocator = externalInvocator; - } - - public function createNodeRegistry():NodeRegistry { - return new NodeRegistry(this); - } - - public function addListener(listener:INodeRegistryManagerListener):void { - listeners.addItem(listener); - } - - public function getResourceSets():Array { - var resourceSets:Array = []; - for (var resourceSet:String in resourceSetToNodeRegistries) { - resourceSets.push(resourceSet); - } - return resourceSets; - } - - public function getNodeRegistriesForResourceSet(resourceSet:String):Array { - var nodeRegistries:Array = resourceSetToNodeRegistries[resourceSet]; - if (nodeRegistries == null) { - nodeRegistries = []; - } - return nodeRegistries; - } - - public function getResourceUrisForNodeRegistry(nodeRegistry:NodeRegistry):Array { - var resourceUris:Array = nodeRegistryToResourceUris[nodeRegistry]; - if (resourceUris == null) { - resourceUris = []; - } - return resourceUris; - } - - public function getResourceUrisForResourceSet(resourceSet:String):Array { - var resourceUris:Array = resourceSetToResourceUris[resourceSet]; - if (resourceSet == null) { - resourceUris = []; - } - return resourceUris; - } - - public function getNodeRegistries():Array { - var nodeRegistries:Array = []; - for (var nodeRegistry:Object in nodeRegistryToResourceUris) { - nodeRegistries.push(NodeRegistry(nodeRegistry)); - } - return nodeRegistries; - } - - public function getResourceUris():Array { - var resourceUris:Array = []; - for (var resourceUri:String in resourceUriToResourceSet) { - resourceUris.push(resourceUri); - } - return resourceUris; - } - - public function linkResourceNodeWithNodeRegistry(resourceUri:String, resourceSet:String, nodeRegistry:NodeRegistry):void { - // add resourceUri to resourceSet - var resourceUris:Array = resourceSetToResourceUris[resourceSet]; - if (resourceUris == null) { - resourceUris = []; - resourceSetToResourceUris[resourceSet] = resourceUris; - } - resourceUris.push(resourceUri); - resourceUriToResourceSet[resourceUri] = resourceSet; - - // add resourceUri to registry - resourceUris = nodeRegistryToResourceUris[nodeRegistry]; - if (resourceUris == null) { - resourceUris = []; - nodeRegistryToResourceUris[nodeRegistry] = resourceUris; - } - resourceUris.push(resourceUri); - - // add resourceSet to registry - var nodeRegistries:Array = resourceSetToNodeRegistries[resourceSet]; - if (nodeRegistries == null) { - nodeRegistries = []; - resourceSetToNodeRegistries[resourceSet] = nodeRegistries; - } - nodeRegistries.push(nodeRegistry); - - // listen for resourceNode properties modifications like isDirty - var resourceNode:Node = nodeRegistry.getNodeById(resourceUri); - resourceNode.properties.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, resourceNodeUpdated); - resourceNodeUpdated(PropertyChangeEvent.createUpdateEvent(resourceNode, CoreConstants.IS_DIRTY, false, resourceNode.properties[CoreConstants.IS_DIRTY])); - } - - public function unlinkResourceNodeFromNodeRegistry(resourceUri:String, nodeRegistry:NodeRegistry):void { - // change isDirty to false and dispatch event - var resourceNodeFromRegistry:Node = nodeRegistry.getNodeById(resourceUri); - nodeRegistry.setPropertyValue(resourceNodeFromRegistry, CoreConstants.IS_DIRTY, false); - - resourceNodeFromRegistry.removeEventListener(PropertyChangeEvent.PROPERTY_CHANGE, resourceNodeUpdated); - - var resourceSet:String = resourceUriToResourceSet[resourceUri]; - - // remove resourceUri from resourceSet - var resourceUris:Array = resourceSetToResourceUris[resourceSet]; - if (resourceUris != null) { - resourceUris.splice(resourceUris.indexOf(resourceUri), 1); - if (resourceUris.length == 0) { - delete resourceSetToResourceUris[resourceSet]; - } - } - - // remove resourceUri from registry - resourceUris = nodeRegistryToResourceUris[nodeRegistry]; - if (resourceUris != null) { - resourceUris.splice(resourceUris.indexOf(resourceUri), 1); - if (resourceUris.length == 0) { - delete nodeRegistryToResourceUris[nodeRegistry]; - } - if (resourceNodeFromRegistry.nodeUri != nodeRegistry.getRootNodeUri() && - resourceNodeFromRegistry.parent == null && resourceUris.indexOf(resourceUri) < 0) { - nodeRegistry.mx_internal::unregisterNode(resourceNodeFromRegistry); - } - } - - // remove resourceSet from registry - var nodeRegistries:Array = resourceSetToNodeRegistries[resourceSet]; - if (nodeRegistries != null) { - nodeRegistries.splice(nodeRegistries.indexOf(nodeRegistry), 1); - if (nodeRegistries.length == 0 && resourceSetToResourceUris[resourceSet] == null) { - delete resourceSetToNodeRegistries[resourceSet]; - delete resourceUriToResourceSet[resourceUri]; - } - } - } - - public function expand(nodeRegistry:NodeRegistry, node:Node, context:Object):void { - if (node == null || !node.properties[CoreConstants.AUTO_SUBSCRIBE_ON_EXPAND]) { - nodeRegistry.expand(node, context); - } else { - var subscribableResources:ArrayCollection = node == null ? null : ArrayCollection(node.properties[CoreConstants.SUBSCRIBABLE_RESOURCES]); - var nodeUri:String; - if (subscribableResources != null && subscribableResources.length > 0) { - // a subscribable node => subscribe to the first resource - var subscribableResource:Pair = Pair(subscribableResources.getItemAt(0)); - nodeUri = String(subscribableResource.a); - } else { - nodeUri = node.nodeUri; - } - subscribe(String(nodeUri), nodeRegistry, function(rootNode:Node, resourceNode:Node):void { - nodeRegistry.expand(node, context); - }); - } - } - - public function collapse(nodeRegistry:NodeRegistry, node:Node, refreshChildren:Boolean = true):void { - // get all the resources starting from node - var dirtyResourceUris:Array = []; - var savedResourceUris:Array = []; - - getResourceUrisForSubTree(node, nodeRegistry, dirtyResourceUris, savedResourceUris); - - if (dirtyResourceUris.length > 0) { // at least one dirty resourceNode found -> show dialog - resourceOperationsManager.showSaveDialog([this], getResourceSetsForResourceUris(dirtyResourceUris), - function():void { - // wait for server response before collapse - collapseHandler(node, nodeRegistry, refreshChildren, dirtyResourceUris, savedResourceUris); - } - ); - } else { - collapseHandler(node, nodeRegistry, refreshChildren, dirtyResourceUris, savedResourceUris); - } - } - - private function collapseHandler(node:Node, nodeRegistry:NodeRegistry,refreshChildren:Boolean, - dirtyResourceUris:Array, savedResoureUris:Array):void { - for each (var dirtyResourceUri:String in dirtyResourceUris) { - unlinkResourceNodeFromNodeRegistry(dirtyResourceUri, nodeRegistry); - } - for each (var savedResourceUri:String in savedResoureUris) { - unlinkResourceNodeFromNodeRegistry(savedResourceUri, nodeRegistry); - } - nodeRegistry.collapse(node, refreshChildren); - } - - /** - * Iterate the subtree starting from node and add all the resources to the dirty or saved resource arrays. - * - * @author Mariana Gheorghe - */ - private function getResourceUrisForSubTree(node:Node, nodeRegistry:NodeRegistry, dirtyResourceUris:Array, savedResourceUris:Array):void { - var subscribableResources:ArrayCollection = ArrayCollection(node.properties[CoreConstants.SUBSCRIBABLE_RESOURCES]); - if (subscribableResources != null) { - for each (var pair:Pair in subscribableResources) { - var resourceUri:String = String(pair.a); - var resourceNode:Node = nodeRegistry.getNodeById(resourceUri); - if (resourceNode != null) { - if (resourceNode.properties[CoreConstants.IS_DIRTY]) { - dirtyResourceUris.push(resourceUri); - } else { - savedResourceUris.push(resourceUri); - } - } - } - } - - // recurse - for each (var child:Node in node.children) { - getResourceUrisForSubTree(child, nodeRegistry, dirtyResourceUris, savedResourceUris); - } - } - - private function hasSubscribableResource(node:Node, resourceUri:String):Boolean { - var subscribableResources:ArrayCollection = ArrayCollection(node.properties[CoreConstants.SUBSCRIBABLE_RESOURCES]); - if (subscribableResources == null || subscribableResources.length == 0) { - return false; - } - for each (var pair:Pair in subscribableResources) { - if (pair.a == resourceUri) { - return true; - } - } - return false; - } - - /** - * Calls subscribe for nodeId on server. Callback functions: - *
    - *
  • subscribeResultCallback(resourceNode:Node):void - *
  • subscribeFaultCallback(event:FaultEvent):void - *
- */ - public function subscribe(nodeId:String, nodeRegistry:NodeRegistry, subscribeResultCallback:Function = null, subscribeFaultCallback:Function = null):void { - serviceInvocator.invoke("resourceService.subscribeToParentResource", [nodeId], - function(subscriptionInfo:SubscriptionInfo):void { - subscriptionInfo.rootNode = nodeRegistry.mx_internal::mergeOrRegisterNode(subscriptionInfo.rootNode); - if (subscriptionInfo.resourceNode != null) { - subscriptionInfo.resourceNode = nodeRegistry.mx_internal::mergeOrRegisterNode(subscriptionInfo.resourceNode); - linkResourceNodeWithNodeRegistry(subscriptionInfo.resourceNode.nodeUri, subscriptionInfo.resourceSet, nodeRegistry); - } - if (subscribeResultCallback != null) { - subscribeResultCallback(subscriptionInfo.rootNode, subscriptionInfo.resourceNode); - } - }, - function(event:FaultEvent):void { - externalInvocator.showMessageBox(Resources.getMessage("editor.error.subscribe.message", [event.fault.faultString]), Resources.getMessage("editor.error.subscribe.title")); - - if (subscribeFaultCallback != null) { - subscribeFaultCallback(event); - } - }); - } - - /** - * Closes all editors without dispatching events and updates global state for save actions. - */ - public function removeNodeRegistries(nodeRegistries:Array):void { - for (var i:int = 0; i < nodeRegistries.length; i++) { - var nodeRegistry:NodeRegistry = NodeRegistry(nodeRegistries[i]); - for each (var resourceNodeId:Object in getResourceUrisForNodeRegistry(nodeRegistry)) { - unlinkResourceNodeFromNodeRegistry(String(resourceNodeId), nodeRegistry); - } - for each (var listener:INodeRegistryManagerListener in listeners) { - listener.nodeRegistryRemoved(nodeRegistry); - } - } - - resourceOperationsManager.resourceOperationsHandler.updateGlobalDirtyState(false); - } - - public function getResourceSetsForResourceUris(resourceUris:Array):Array { - var resourceSets:Array = []; - for each (var resourceUri:String in resourceUris) { - var resourceSet:String = resourceUriToResourceSet[resourceUri]; - if (resourceSets.indexOf(resourceSet) < 0) { - resourceSets.push(resourceSet); - } - } - return resourceSets; - } - - /** - * @param dirtyResourceNodeHandler function will be executed each time a dirty resourceNode is found. - * @return all dirty resourceUris found in nodeRegistries, without duplicates. - */ - public function getDirtyResourceSetsFromNodeRegistries(nodeRegistries:Array, dirtyResourceNodeHandler:Function = null):Array { - var dirtyResourceSets:Array = []; - for (var i:int = 0; i < nodeRegistries.length; i++) { - var nodeRegistry:NodeRegistry = NodeRegistry(nodeRegistries[i]); - for each (var obj:Object in getResourceUrisForNodeRegistry(nodeRegistry)) { - var resourceUri:String = String(obj); - var resourceSet:String = resourceUriToResourceSet[resourceUri]; - if (isResourceNodeDirty(resourceUri, nodeRegistry) && dirtyResourceSets.indexOf(resourceSet) == -1) { - if (dirtyResourceNodeHandler != null) { - dirtyResourceNodeHandler(resourceSet); - } - dirtyResourceSets.push(resourceSet); - } - } - } - return dirtyResourceSets; - } - - /** - * @param returnIfAtLeastOneDirtyResourceNodeFound if true, returns the first dirty resourceNodeId found. - * @param dirtyResourceNodeHandler function will be executed each time a dirty resourceNode is found. - * @return all dirty resourceUris, without duplicates. - */ - public function getAllDirtyResourceSets(returnIfAtLeastOneDirtyResourceNodeFound:Boolean = false, dirtyResourceNodeHandler:Function = null):Array { - var dirtyResourceSets:Array = []; - for each (var nodeRegistry:NodeRegistry in getNodeRegistries()) { - for each (var resourceUri:String in getResourceUrisForNodeRegistry(nodeRegistry)) { - var resourceSet:String = resourceUriToResourceSet[resourceUri]; - if (isResourceNodeDirty(resourceUri, nodeRegistry) && dirtyResourceSets.indexOf(resourceSet) == -1) { - if (returnIfAtLeastOneDirtyResourceNodeFound) { - return [resourceSet]; - } - if (dirtyResourceNodeHandler != null) { - dirtyResourceNodeHandler(resourceSet); - } - dirtyResourceSets.push(resourceSet); - } - } - } - return dirtyResourceSets; - } - - public function processUpdates(resourceNodeIdToUpdates:Object):void { - for (var resourceNodeId:String in resourceNodeIdToUpdates) { - var updates:ArrayCollection = resourceNodeIdToUpdates[resourceNodeId]; - for each (var nodeRegistry:NodeRegistry in getNodeRegistriesForResourceSet(resourceNodeId)) { - nodeRegistry.processUpdates(updates); - } - } - } - - /** - * Unlink resourceUris from node registries. - * - *

- * Dispatches NodeRegistry_ResourceNodeRemovedEvent for each NodeRegistry found. - * Note: Additional behavior can be added by listening to this event (e.g. in case of an editor, close it). - */ - public function unlinkResourceNodesForcefully(resourceUris:ArrayCollection):void { - var idsList:String = ""; - for each (var resourceNodeId:String in resourceUris) { - var nodeRegistries:Array = getNodeRegistriesForResourceSet(resourceNodeId); - for each (var nodeRegistry:NodeRegistry in nodeRegistries) { - unlinkResourceNodeFromNodeRegistry(resourceNodeId, nodeRegistry); - for each (var listener:INodeRegistryManagerListener in listeners) { - listener.resourceNodeRemoved(resourceNodeId, nodeRegistry); - } - } - idsList += "\n* " + resourceNodeId; - } - externalInvocator.showMessageBox(Resources.getMessage("editor.error.subscribe.message", [idsList]), Resources.getMessage("editor.error.subscribe.title")); - } - - public function isResourceNodeDirty(resourceNodeId:String, nodeRegistry:NodeRegistry):Boolean { - var node:Node = nodeRegistry.getNodeById(resourceNodeId); - return node == null ? false : node.properties[CoreConstants.IS_DIRTY]; - } - - protected function resourceNodeUpdated(event:PropertyChangeEvent):void { - if (event.property == CoreConstants.IS_DIRTY) { - resourceOperationsManager.resourceOperationsHandler.updateGlobalDirtyState(event.newValue); - } - } - - } -} diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/ResourceOperationsManagerJs.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/ResourceOperationsManagerJs.as deleted file mode 100644 index 97d4838a..00000000 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/ResourceOperationsManagerJs.as +++ /dev/null @@ -1,103 +0,0 @@ -/* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ -package org.flowerplatform.flex_client.core.node { - - import mx.collections.ArrayList; - - import org.flowerplatform.flex_client.core.editor.resource.ResourceNode; - - /** - * @author Cristina Constantinescu - */ - public class ResourceOperationsManagerJs { - - public var resourceOperationsHandler:IResourceOperationsHandler; - - protected var nodeRegistryManager:NodeRegistryManager; - - public function ResourceOperationsManagerJs(nodeRegistryManager:NodeRegistryManager, resourceOperationsHandler:IResourceOperationsHandler) { - this.nodeRegistryManager = nodeRegistryManager; - this.resourceOperationsHandler = resourceOperationsHandler; - this.resourceOperationsHandler.nodeRegistryManager = this.nodeRegistryManager; - } - - public function showSaveDialog(nodeRegistries:Array = null, dirtyResourceNodeIds:Array = null, handler:Function = null):void { - if (nodeRegistries == null) { - nodeRegistries = nodeRegistryManager.getNodeRegistries(); - } - - var dirtyResourceNodes:ArrayList = new ArrayList(); - if (dirtyResourceNodeIds == null) { - nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries(nodeRegistries, function(dirtyResourceNodeId:String):void { - dirtyResourceNodes.addItem(new ResourceNode(dirtyResourceNodeId, true)); - }); - } else { - for (var i:int = 0; i < dirtyResourceNodeIds.length; i++) { - dirtyResourceNodes.addItem(new ResourceNode(dirtyResourceNodeIds[i], true)); - } - } - if (dirtyResourceNodes.length == 0) { - if (handler != null) { - handler(); - } else { - nodeRegistryManager.removeNodeRegistries(nodeRegistries); - } - return; - } - resourceOperationsHandler.showSaveDialog(nodeRegistries, dirtyResourceNodes, handler); - } - - public function showReloadDialog(nodeRegistries:Array = null, resourceSets:Array = null):void { - if (nodeRegistries == null) { - nodeRegistries = nodeRegistryManager.getNodeRegistries(); - } - if (resourceSets == null) { - resourceSets = nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries(nodeRegistries); - } - resourceOperationsHandler.showReloadDialog(nodeRegistries, resourceSets); - } - - public function save(nodeRegistry:NodeRegistry):void { - var dirtyResourceNodeIds:Array = nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries([nodeRegistry]); - if (dirtyResourceNodeIds.length == 1) { - // single resourceNode to save -> save without asking - nodeRegistryManager.serviceInvocator.invoke("resourceService.save", [dirtyResourceNodeIds[0]]); - } else { - // multiple resourceNodes to save -> show dialog - showSaveDialog([nodeRegistry], dirtyResourceNodeIds, function():void {}); - } - } - - public function saveAll():void { - nodeRegistryManager.getAllDirtyResourceSets(false, function(dirtyResourceNodeId:String):void { - // for each dirty resourceNode found -> save it - nodeRegistryManager.serviceInvocator.invoke("resourceService.save", [dirtyResourceNodeId]); - }); - } - - public function reload(nodeRegistry:NodeRegistry):void { - var resourceSets:Array = nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries([nodeRegistry]); - if (resourceSets.length == 1) { - // single resourceNode to reload -> reload without asking - nodeRegistryManager.serviceInvocator.invoke("resourceService.reload", [resourceSets[0]]); - } else { - // multiple resourceNodes -> show dialog - showReloadDialog([nodeRegistry], resourceSets); - } - } - - } -} \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/ResourceDebugControllers.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/ResourceDebugControllers.as index 4ce7b56c..59b1d582 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/ResourceDebugControllers.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/ResourceDebugControllers.as @@ -16,11 +16,8 @@ package org.flowerplatform.flex_client.core.node.controller { import mx.collections.ArrayCollection; - import org.flowerplatform.flex_client.core.CoreConstants; import org.flowerplatform.flex_client.core.CorePlugin; import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.node.NodeRegistry; - import org.flowerplatform.flexdiagram.FlexDiagramConstants; /** * @author Mariana Gheorghe @@ -67,7 +64,6 @@ import mx.collections.IList; import mx.core.mx_internal; import org.flowerplatform.flex_client.core.editor.remote.Node; -import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flex_client.core.node.controller.ResourceDebugControllers; import org.flowerplatform.flexdiagram.DiagramShellContext; import org.flowerplatform.flexdiagram.mindmap.MindMapDiagramShell; @@ -95,7 +91,7 @@ class ResourceNodeController extends MindMapModelController { } override public function setExpanded(context:DiagramShellContext, model:Object, value:Boolean):void { - var nodeRegistry:NodeRegistry = Object(context.diagramShell).nodeRegistry; + var nodeRegistry:* = Object(context.diagramShell).nodeRegistry; var node:Node = Node(model); if (value) { var children:ArrayCollection; diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/TypeDescriptorRegistryDebugControllers.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/TypeDescriptorRegistryDebugControllers.as index 058d7418..420eda90 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/TypeDescriptorRegistryDebugControllers.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node/controller/TypeDescriptorRegistryDebugControllers.as @@ -175,7 +175,6 @@ import mx.collections.IList; import mx.core.mx_internal; import org.flowerplatform.flex_client.core.editor.remote.Node; -import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flex_client.core.node.controller.TypeDescriptorRegistryDebugControllers; import org.flowerplatform.flexdiagram.DiagramShellContext; import org.flowerplatform.flexdiagram.mindmap.MindMapDiagramShell; @@ -203,7 +202,7 @@ class FlexTypesNodeController extends MindMapModelController { } override public function setExpanded(context:DiagramShellContext, model:Object, value:Boolean):void { - var nodeRegistry:NodeRegistry = Object(context.diagramShell).nodeRegistry; + var nodeRegistry:* = Object(context.diagramShell).nodeRegistry; var node:Node = Node(model); if (value) { var children:ArrayCollection; diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node_tree/NodeTreeComponent.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node_tree/NodeTreeComponent.as index 6c5056f8..3330ff52 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node_tree/NodeTreeComponent.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/node_tree/NodeTreeComponent.as @@ -20,7 +20,6 @@ package org.flowerplatform.flex_client.core.node_tree { import org.flowerplatform.flex_client.core.CorePlugin; import org.flowerplatform.flex_client.core.editor.remote.Node; import org.flowerplatform.flex_client.core.node.INodeChangeListener; - import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flexutil.tree.TreeList; /** @@ -29,7 +28,7 @@ package org.flowerplatform.flex_client.core.node_tree { */ public class NodeTreeComponent extends TreeList implements INodeChangeListener { - protected var nodeRegistry:NodeRegistry; + protected var nodeRegistry:*; protected var _nodeUri:String; @@ -47,6 +46,8 @@ package org.flowerplatform.flex_client.core.node_tree { addEventListener("itemOpen", treeListItemOpenCloseHandler); addEventListener("itemClose", treeListItemOpenCloseHandler); + + CorePlugin.getInstance().nodeRegistryManager.addListener(this); } public function initializeTree(nodeUri:String):void { @@ -56,6 +57,7 @@ package org.flowerplatform.flex_client.core.node_tree { public function finalizeTree():void { CorePlugin.getInstance().nodeRegistryManager.unlinkResourceNodeFromNodeRegistry(nodeUri, nodeRegistry); + CorePlugin.getInstance().nodeRegistryManager.removeListener(this); } protected function subscribeResultCallback(rootNode:Node, resourceNode:Node):void { @@ -88,5 +90,9 @@ package org.flowerplatform.flex_client.core.node_tree { invalidateDisplayList(); } + public function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:*):void { + // do nothing + } + } } \ No newline at end of file diff --git a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/service/UpdatesProcessingServiceLocator.as b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/service/UpdatesProcessingServiceLocator.as index 41a5196d..da986c79 100644 --- a/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/service/UpdatesProcessingServiceLocator.as +++ b/org.flowerplatform.flex_client.core/src/org/flowerplatform/flex_client/core/service/UpdatesProcessingServiceLocator.as @@ -20,6 +20,7 @@ package org.flowerplatform.flex_client.core.service { import mx.collections.ArrayCollection; import mx.messaging.ChannelSet; import mx.rpc.AbstractOperation; + import mx.rpc.Fault; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.remoting.RemoteObject; @@ -114,15 +115,15 @@ package org.flowerplatform.flex_client.core.service { } } - override public function faultHandler(event:FaultEvent, responder:ServiceResponder):void { - if (event.fault.faultCode == "Channel.Call.Failed" /*|| event.fault.faultCode == "Client.Error.MessageSend")*/) { + override public function faultHandler(fault:Fault, responder:ServiceResponder):void { + if (fault.faultCode == "Channel.Call.Failed" /*|| fault.faultCode == "Client.Error.MessageSend")*/) { if (communicationErrorViewContent == null) { communicationErrorViewContent = new ReconnectingViewContent(); FlexUtilGlobals.getInstance().popupHandlerFactory.createPopupHandler() .setViewContent(communicationErrorViewContent) .showModalOverAllApplication(); } - } else if (event.fault.faultCode == "Client.Error.MessageSend") { + } else if (fault.faultCode == "Client.Error.MessageSend") { if (communicationErrorViewContent == null) { if (FlexUtilGlobals.getInstance().clientCommunicationErrorViewContent == null) { communicationErrorViewContent = new ReconnectingViewContent(); @@ -134,7 +135,7 @@ package org.flowerplatform.flex_client.core.service { .showModalOverAllApplication(); } }else { - super.faultHandler(event, responder); + super.faultHandler(fault, responder); } } diff --git a/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorDiagramShell.as b/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorDiagramShell.as index 5caa3d19..25174680 100644 --- a/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorDiagramShell.as +++ b/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorDiagramShell.as @@ -15,12 +15,9 @@ */ package org.flowerplatform.flex_client.mindmap { - import flash.events.MouseEvent; - import org.flowerplatform.flex_client.core.editor.action.OpenAction; import org.flowerplatform.flex_client.core.editor.remote.Node; import org.flowerplatform.flex_client.core.node.INodeChangeListener; - import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flex_client.core.node.controller.GenericValueProviderFromDescriptor; import org.flowerplatform.flex_client.core.node.controller.NodeControllerUtils; import org.flowerplatform.flex_client.mindmap.action.ExpandCollapseAction; @@ -41,7 +38,7 @@ package org.flowerplatform.flex_client.mindmap { */ public class MindMapEditorDiagramShell extends MindMapDiagramShell implements INodeChangeListener { - private var _nodeRegistry:NodeRegistry; + private var _nodeRegistry:*; public function MindMapEditorDiagramShell() { super(); @@ -54,11 +51,11 @@ package org.flowerplatform.flex_client.mindmap { registerTool(ExpandCollapseAction.ID, new FactoryWithInitialization(ActionTool, {"action": new ExpandCollapseAction(), "eventType": WakeUpTool.CLICK})); } - public function get nodeRegistry():NodeRegistry { + public function get nodeRegistry():* { return _nodeRegistry; } - public function set nodeRegistry(value:NodeRegistry):void { + public function set nodeRegistry(value:*):void { _nodeRegistry = value; _nodeRegistry.addNodeChangeListener(this); } diff --git a/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorFrontend.as b/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorFrontend.as index 79ad3cb5..530c9ae5 100644 --- a/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorFrontend.as +++ b/org.flowerplatform.flex_client.mindmap/src/org/flowerplatform/flex_client/mindmap/MindMapEditorFrontend.as @@ -20,7 +20,6 @@ package org.flowerplatform.flex_client.mindmap { import org.flowerplatform.flex_client.core.editor.action.InplaceEditorAction; import org.flowerplatform.flex_client.core.editor.action.OpenWithEditorActionProvider; import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flex_client.mindmap.action.NodeDownAction; import org.flowerplatform.flex_client.mindmap.action.NodeLeftAction; import org.flowerplatform.flex_client.mindmap.action.NodePageDownAction; @@ -100,7 +99,7 @@ package org.flowerplatform.flex_client.mindmap { } } - override public function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:NodeRegistry):void { + override public function resourceNodeRemoved(resourceNodeUri:String, nodeRegistry:*):void { super.resourceNodeRemoved(resourceNodeUri, nodeRegistry); if (this.nodeRegistry == nodeRegistry) { var rootModel:MindMapRootModelWrapper = MindMapRootModelWrapper(diagramShell.rootModel); diff --git a/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/CheckoutAction.as b/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/CheckoutAction.as index 3210d102..9f998dac 100644 --- a/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/CheckoutAction.as +++ b/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/CheckoutAction.as @@ -20,6 +20,7 @@ */ package org.flowerplatform.flex_client.team.git.action { + import mx.rpc.Fault; import mx.rpc.events.FaultEvent; import org.flowerplatform.flex_client.core.CorePlugin; @@ -72,11 +73,11 @@ package org.flowerplatform.flex_client.team.git.action .showMessageBox(); } - public function FaultCallback(event:FaultEvent):void { - if (event != null) { - var index:Number = event.fault.faultString.search("CheckoutConflictException"); + public function FaultCallback(fault:Fault):void { + if (fault != null) { + var index:Number = fault.faultString.search("CheckoutConflictException"); if (index != -1) - uncommitedChanges(event.fault.faultString.substring(index)); + uncommitedChanges(fault.faultString.substring(index)); } } diff --git a/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/DeleteBranchAction.as b/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/DeleteBranchAction.as index 04a23312..fd5c3f6e 100644 --- a/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/DeleteBranchAction.as +++ b/org.flowerplatform.flex_client.team.git/src/org/flowerplatform/flex_client/team/git/action/DeleteBranchAction.as @@ -15,8 +15,6 @@ */ package org.flowerplatform.flex_client.team.git.action { - import mx.rpc.events.FaultEvent; - import org.flowerplatform.flex_client.core.CorePlugin; import org.flowerplatform.flex_client.core.editor.remote.Node; import org.flowerplatform.flex_client.resources.Resources; diff --git a/org.flowerplatform.flex_client.text/src/org/flowerplatform/flex_client/text/TextEditorFrontend.as b/org.flowerplatform.flex_client.text/src/org/flowerplatform/flex_client/text/TextEditorFrontend.as index 1d308cf9..0a36d2ce 100644 --- a/org.flowerplatform.flex_client.text/src/org/flowerplatform/flex_client/text/TextEditorFrontend.as +++ b/org.flowerplatform.flex_client.text/src/org/flowerplatform/flex_client/text/TextEditorFrontend.as @@ -22,7 +22,6 @@ package org.flowerplatform.flex_client.text { import org.flowerplatform.flex_client.core.editor.EditorFrontend; import org.flowerplatform.flex_client.core.editor.remote.Node; - import org.flowerplatform.flex_client.core.node.NodeRegistry; import org.flowerplatform.flex_client.text.codemirror_editor.ICodeMirrorEditor; import org.flowerplatform.flex_client.text.codemirror_editor.MobileCodeMirrorEditor; import org.flowerplatform.flex_client.text.codemirror_editor.WebCodeMirrorEditor; @@ -68,7 +67,7 @@ package org.flowerplatform.flex_client.text { ICodeMirrorEditor(editor).load(FlexUtilGlobals.getInstance().createAbsoluteUrl(TextPlugin.getInstance().getResourceUrl(getURL()))); } - override public function nodeRegistryRemoved(nodeRegistry:NodeRegistry):void { + override public function nodeRegistryRemoved(nodeRegistry:*):void { if (this.nodeRegistry == nodeRegistry) { ICodeMirrorEditor(editor).dispose(); } diff --git a/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceLocator.as b/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceLocator.as index 4e0b2c60..a4a91089 100644 --- a/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceLocator.as +++ b/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceLocator.as @@ -19,6 +19,7 @@ package org.flowerplatform.flexutil.service { import mx.messaging.ChannelSet; import mx.rpc.AbstractOperation; import mx.rpc.AsyncToken; + import mx.rpc.Fault; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; import mx.rpc.remoting.RemoteObject; @@ -58,15 +59,15 @@ package org.flowerplatform.flexutil.service { return remoteObject; } - public function faultHandler(event:FaultEvent, responder:ServiceResponder):void { + public function faultHandler(fault:Fault, responder:ServiceResponder):void { if (responder.faultHandler != null) { - responder.faultHandler(event); + responder.faultHandler(fault); } else { FlexUtilGlobals.getInstance().messageBoxFactory.createMessageBox() .setWidth(300) .setHeight(200) .setTitle(FlexUtilAssets.INSTANCE.getMessage("service.fault.title")) - .setText(FlexUtilAssets.INSTANCE.getMessage("service.fault.message", [event.fault.faultString, event.fault.content])) + .setText(FlexUtilAssets.INSTANCE.getMessage("service.fault.message", [fault.faultString, fault.content])) .showMessageBox(); } } diff --git a/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceResponder.as b/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceResponder.as index e4e419c7..b70ae231 100644 --- a/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceResponder.as +++ b/org.flowerplatform.flexutil/src/org/flowerplatform/flexutil/service/ServiceResponder.as @@ -14,14 +14,10 @@ * license-end */ package org.flowerplatform.flexutil.service { - import mx.collections.ArrayCollection; import mx.rpc.IResponder; import mx.rpc.events.FaultEvent; import mx.rpc.events.ResultEvent; - import org.flowerplatform.flexutil.FlexUtilGlobals; - import org.flowerplatform.flexutil.layout.ViewLayoutData; - /** * @author Cristian Spiescu * @author Cristina Constantinescu @@ -53,7 +49,7 @@ package org.flowerplatform.flexutil.service { } public function fault(info:Object):void { - serviceLocator.faultHandler(FaultEvent(info), this); + serviceLocator.faultHandler(info != null ? FaultEvent(info).fault : null, this); } } diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistry.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistry.js new file mode 100644 index 00000000..619359be --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistry.js @@ -0,0 +1,387 @@ +/* license-start + * + * Copyright (C) 2008 - 2013 Crispico Software, . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, at . + * + * license-end + */ + +var NodeRegistry = function(nodeRegistryManager) { + this.nodeRegistryManager = nodeRegistryManager; + this.nodeChangeListeners = []; + this.rootNodeUri = null; + this.registry = {}; +}; + +NodeRegistry.prototype.getRootNodeUri = function() { + return this.rootNodeUri; +}; + +NodeRegistry.prototype.getNodeById = function(id) { + return this.registry[id]; +}; + +NodeRegistry.prototype.addNodeChangeListener = function(listener) { + this.nodeChangeListeners.push(listener); +}; + +NodeRegistry.prototype.removeNodeChangeListener = function(listener) { + var i = this.nodeChangeListeners.indexOf(listener); + if(i != -1) { + this.nodeChangeListeners.splice(i, 1); + } +}; + +NodeRegistry.prototype.unregisterNode = function(node, parent) { + if (parent != null && (parent.children == null || !parent.children.contains(node))) { + // not expanded or child already removed + return; + } + // remove children recursive + this.collapse(node, false); + + var nodeFromRegistry = this.registry[node.nodeUri]; + if (nodeFromRegistry != null) { + delete this.registry[node.nodeUri]; + } + + if (parent != null) { + // remove from parent list of children + parent.children.removeItemAt(parent.children.getItemIndex(node)); + if (parent.children.length == 0) { // parent has no children left -> parent is leaf + parent.children = null; + } + } + for (var i=0; i < this.nodeChangeListeners.length; i++){ + this.nodeChangeListeners[i].nodeRemoved(node); + } +}; + +NodeRegistry.prototype.collapse = function(node, refreshChildren) { + if (!(node.nodeUri in this.registry)) { + return; + } + if (node.children == null) { + return; + } + while (node.children != null) { + this.unregisterNode(node.children.getItemAt(0), node); + } +}; + +NodeRegistry.prototype.expand = function(node, context) { + if (!(node.nodeUri in this.registry)) { + return; + } + + var serviceContext = this.nodeRegistryManager.externalInvocator.getServiceContextInstance(); + if (context != null) { + for (var key in context) { + serviceContext.context[key] = context[key]; + } + } + serviceContext.add("populateWithProperties", true); + + var self = this; + this.nodeRegistryManager.serviceInvocator.invoke( + "nodeService.getChildren", + [node.nodeUri, serviceContext], + function (result) { + self.expandCallbackHandler(node, result); + + // additional handler to be executed + if (context != null && ("handler" in context)) { + context["handler"](); + } + }); +}; + +/** + * Handles updates received from server. + * + * There are 2 cases: + *

    + *
  • updates == null (server cannot provide any updates because no updates were registered before timestampOfLastRequest), a full refresh is needed
  • + *
  • otherwise + *
      + *
    • property update (PropertyUpdate) -> set/unset property from Node.properties
      + * A NodeUpdatedEvent is dispatched at the end; it contains all updated & removed properties keys. + *
    • child added (ChildrenUpdate.ADDED) -> adds new node in parent as last child OR, if targetNodeAddedBefore set, before given child's index. + *
    • child removed (ChildrenUpdate.REMOVED) -> removes node from parent + *
    + *
+ * + * Note: If a given fullNodeId doesn't exist in nodeRegistry, it means it isn't visible for current client, so ignore it. + */ +NodeRegistry.prototype.processUpdates = function(updates) { + if (updates == null) { + // refresh all from root node (node.parent == null) + for (var fullNodeId in this.registry) { + var node = this.registry[fullNodeId]; + if (node.parent == null) { + this.refresh(node); + } + } + return; + } + + for (var i = updates.length - 1; i >= 0; i--) { + var update = updates.getItemAt(i); + var nodeFromRegistry = this.getNodeById(update.fullNodeId); + if (nodeFromRegistry == null) { // node not registered, probably it isn't visible for this client + continue; + } + + switch (update.type) { + case "UPDATED": + var propertyUpdate = update; + + if (propertyUpdate.isUnset) { + delete this.nodeFromRegistry.properties[propertyUpdate.key]; + } else { + this.setPropertyValue(nodeFromRegistry, propertyUpdate.key, propertyUpdate.value); + } + break; + case "ADDED": + var targetNodeInRegistry = this.getNodeById(update.targetNode.nodeUri); + + if (nodeFromRegistry.children != null && !nodeFromRegistry.children.contains(targetNodeInRegistry)) { + var index = -1; // -> add it last + if (update.fullTargetNodeAddedBeforeId != null) { + // get targetNodeAddedBefore from registry + var targetNodeAddedBeforeInRegistry = this.getNodeById(update.fullTargetNodeAddedBeforeId); + if (targetNodeAddedBeforeInRegistry != null) { // exists, get its index in children list + index = nodeFromRegistry.children.getItemIndex(targetNodeAddedBeforeInRegistry); + } + } + this.registerNode(update.targetNode, nodeFromRegistry, index); + } else { + // child already added, probably after refresh + // e.g. I add a children, I expand => I get the list with the new children; when the + // client polls for data, this children will be received as well, and thus duplicated. + // NOTE: since the instant notifications for the client that executed => this doesn't apply + // for him; but for other clients yes + + // Nothing to do + } + break; + case "REMOVED": + var targetNodeInRegistry = this.getNodeById(update.targetNode.nodeUri); + + if (targetNodeInRegistry != null) { + this.unregisterNode(targetNodeInRegistry, nodeFromRegistry); + } else { + // node not registered, probably it isn't visible for this client + // Nothing to do + } + break; + case "REQUEST_REFRESH": + this.refresh(nodeFromRegistry); + break; + default: + update.apply(this, nodeFromRegistry); + } + } +}; + +NodeRegistry.prototype.expandCallbackHandler = function(node, children) { + if (children == null) { + return; + } + // register each child + for (var i = 0; i < children.length; i++) { + this.registerNode((Object.prototype.toString.call(children) == "[object Array]") ? children[i] : children.getItemAt(i), node, -1); + } +}; + +NodeRegistry.prototype.refresh = function(node) { + if (!(node.nodeUri in this.registry)) { + return; + } + var self = this; + this.nodeRegistryManager.serviceInvocator.invoke( + "nodeService.refresh", + [this.getFullNodeIdWithChildren(node)], + function (result) { + self.refreshHandler(node, result); + }); +}; + +/** + * @return an hierarchical structure of fullNodeIds starting from node. + */ +NodeRegistry.prototype.getFullNodeIdWithChildren = function(node) { + var fullNodeIdWithChildren = this.nodeRegistryManager.externalInvocator.getNewFullNodeIdWithChildrenInstance(); + fullNodeIdWithChildren.fullNodeId = node.nodeUri; + + if (node.children != null) { + for (var i = 0; i < node.children.length; i++) { + if (fullNodeIdWithChildren.visibleChildren == null) { + fullNodeIdWithChildren.visibleChildren = this.nodeRegistryManager.externalInvocator.getNewListInstance(); + } + fullNodeIdWithChildren.visibleChildren.addItem(this.getFullNodeIdWithChildren(node.children.getItemAt(i))); + } + } + return fullNodeIdWithChildren; +}; + +/** + * Handles refresh response from server. + * + * For each node: + *
    + *
  • re-set its properties and dispatch a NodeUpdateEvent without specifying the updated & removed properties keys + *
  • if no new children, remove all current node's children + *
  • else, iterate on current list + *
      + *
    • if current child id exists in new list -> get its new structure + *
    • else -> remove current child + *
    + *
  • at this point, the current list will contain only the children that haven't been removed + *
  • next, iterate on new list, there are 2 cases: + *
      + *
    • child added -> add new child in current list at the same index + *
    • child moved to a different index -> remove child from current index, add it to new index + *
    + *
+ */ +NodeRegistry.prototype.refreshHandler = function(node, nodeWithVisibleChildren) { + // set new node properties and dispatch event + var nodeFromRegistry = this.getNodeById(node.nodeUri); + this.setNodeProperties(nodeFromRegistry, nodeWithVisibleChildren.node.properties); + + var newNodeToCurrentNodeIndex = []; + var i; + var currentChildNode; + + // no children -> remove the old ones + if (nodeWithVisibleChildren.children == null) { + this.collapse(node, false); + return; + } + + if (node.children != null) { // node has children -> merge current list with new list + // serch for children that doesn't exist in new list + var currentChildren = node.children != null ? node.children.slice() : []; + for (i = 0; i < currentChildren.length; i++) { + var exists = false; + currentChildNode = currentChildren.getItemAt(i); + for (var newChildWithVisibleChildren in nodeWithVisibleChildren.children) { + if (currentChildNode.nodeUri == newChildWithVisibleChildren.node.nodeUri) { + exists = true; + break; + } + } + if (exists) { + // child exists -> refresh its structure + this.refreshHandler(currentChildNode, newChildWithVisibleChildren); + // store, for the new child, its index in current list + newNodeToCurrentNodeIndex[newChildWithVisibleChildren.node.nodeUri] = i; + } else { + // child doesn't exist in new list -> remove it from parent + this.unregisterNode(currentChildNode, node); + } + } + } + + for (i = 0; i < nodeWithVisibleChildren.children.length; i++) { + var newChildNode = nodeWithVisibleChildren.children.getItemAt(i).node; + if (!(newChildNode.nodeUri in newNodeToCurrentNodeIndex)) { // new child doesn't exist in current list -> add it + this.registerNode(newChildNode, node, i); + } else if (newNodeToCurrentNodeIndex[newChildNode.nodeUri] != i) { // new child exists in current list, but different indexes -> get current child and move it to new index + currentChildNode = this.getNodeById(newChildNode.nodeUri); + this.unregisterNode(currentChildNode, node); + this.registerNode(currentChildNode, node, i); + } + } +}; + +NodeRegistry.prototype.mergeOrRegisterNode = function(node) { + var existingNode = this.getNodeById(node.nodeUri); + if (existingNode == null) { + this.registerNode(node, null, -1); + return node; + } + this.setNodeProperties(existingNode, node.properties); + + return existingNode; +}; + +/** + * Adds node to parent at given index and registers it in registry.
+ * + * If parent is null, the node will only be registered + * If index is -1, the node will be added last. + */ +NodeRegistry.prototype.registerNode = function(node, parent, index) { + if (this.rootNodeUri == null) { + this.rootNodeUri = node.nodeUri; + } + + this.registry[node.nodeUri] = node; + + if (parent != null) { + node.parent = parent; + if (parent.children == null) { + parent.children = this.nodeRegistryManager.externalInvocator.getNewListInstance(); + } + if (index != -1) { + parent.children.addItemAt(node, index); + } else { + parent.children.addItem(node); + } + } + + for (var i = 0; i < this.nodeChangeListeners.length; i++){ + this.nodeChangeListeners[i].nodeAdded(node); + } + +}; + +NodeRegistry.prototype.unregisterNode = function(node, parent) { + if (parent != null && (parent.children == null || !parent.children.contains(node))) { + // not expanded or child already removed + return; + } + // remove children recursive + this.collapse(node, false); + + var nodeFromRegistry = this.registry[node.nodeUri]; + if (nodeFromRegistry != null) { + delete this.registry[node.nodeUri]; + } + + if (parent != null) { + // remove from parent list of children + parent.children.removeItemAt(parent.children.getItemIndex(node)); + if (parent.children.length == 0) { // parent has no children left -> parent is leaf + parent.children = null; + } + } + for (var i = 0; i < this.nodeChangeListeners.length; i++){ + this.nodeChangeListeners[i].nodeRemoved(node); + } +}; + +NodeRegistry.prototype.setPropertyValue = function(node, property, newValue) { + var oldValue = (property in node.properties) ? node.properties[property] : null; + node.properties[property] = newValue; + + for (var i = 0; i < this.nodeChangeListeners.length; i++){ + this.nodeChangeListeners[i].nodeUpdated(node, property, oldValue, newValue); + } +}; + +NodeRegistry.prototype.setNodeProperties = function(node, newProperties) { + for (var property in newProperties) { + this.setPropertyValue(node, property, newProperties[property]); + } +}; diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistryManager.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistryManager.js new file mode 100644 index 00000000..9892f76b --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/NodeRegistryManager.js @@ -0,0 +1,406 @@ +/* license-start + * + * Copyright (C) 2008 - 2013 Crispico Software, . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, at . + * + * license-end + */ + +var NodeRegistryManager = function(resourceOperationsHandler, serviceInvocator, externalInvocator) { + this.resourceOperationsManager = new ResourceOperationsManager(this, resourceOperationsHandler); + this.serviceInvocator = serviceInvocator; + this.externalInvocator = externalInvocator; + + this.resourceSetToNodeRegistries = {}; + + this.resourceSetToResourceUris = {}; + this.resourceUriToResourceSet = {}; + + this.listeners = []; +}; + +NodeRegistryManager.prototype.createNodeRegistry = function() { + return new NodeRegistry(this); +}; + +NodeRegistryManager.prototype.addListener = function(listener) { + this.listeners.push(listener); +}; + +NodeRegistryManager.prototype.removeListener = function(listener) { + var i = this.listeners.indexOf(listener); + if (i != -1) { + this.listeners.splice(i, 1); + } +}; + +NodeRegistryManager.prototype.getResourceSets = function() { + var resourceSets = []; + for (var resourceSet in this.resourceSetToNodeRegistries) { + resourceSets.push(resourceSet); + } + return resourceSets; +}; + +NodeRegistryManager.prototype.getNodeRegistriesForResourceSet = function(resourceSet) { + var nodeRegistries = this.resourceSetToNodeRegistries[resourceSet]; + if (nodeRegistries == null) { + nodeRegistries = []; + } + return nodeRegistries; +}; + +NodeRegistryManager.prototype.getResourceUrisForNodeRegistry = function(nodeRegistry) { + var resourceUris = []; + for (var resourceUri in this.resourceUriToResourceSet) { + var nodeRegistries = this.resourceSetToNodeRegistries[this.resourceUriToResourceSet[resourceUri]]; + if (this.contains(nodeRegistries, nodeRegistry)) { + resourceUris.push(resourceUri); + } + } + return resourceUris; +}; + +NodeRegistryManager.prototype.getResourceUrisForResourceSet = function(resourceSet) { + var resourceUris = this.resourceSetToResourceUris[resourceSet]; + if (resourceSet == null) { + resourceUris = []; + } + return resourceUris; +}; + +NodeRegistryManager.prototype.getNodeRegistries = function() { + var list = []; + for (var resourceSet in this.resourceSetToNodeRegistries) { + var nodeRegistries = this.resourceSetToNodeRegistries[resourceSet]; + for (var i=0; i < nodeRegistries.length; i++) { + if (!this.contains(list, nodeRegistries[i])) { + list.push(nodeRegistries[i]); + } + } + } + return list; +}; + +NodeRegistryManager.prototype.getResourceUris = function() { + var resourceUris = []; + for (var resourceUri in this.resourceUriToResourceSet) { + resourceUris.push(resourceUri); + } + return resourceUris; +}; + +NodeRegistryManager.prototype.linkResourceNodeWithNodeRegistry = function(resourceUri, resourceSet, nodeRegistry) { + // add resourceUri to resourceSet + var resourceUris = this.resourceSetToResourceUris[resourceSet]; + if (resourceUris == null) { + resourceUris = []; + this.resourceSetToResourceUris[resourceSet] = resourceUris; + } + resourceUris.push(resourceUri); + this.resourceUriToResourceSet[resourceUri] = resourceSet; + + // add resourceSet to registry + var nodeRegistries = this.resourceSetToNodeRegistries[resourceSet]; + if (nodeRegistries == null) { + nodeRegistries = []; + this.resourceSetToNodeRegistries[resourceSet] = nodeRegistries; + } + nodeRegistries.push(nodeRegistry); + + // listen for resourceNode properties modifications like isDirty + var resourceNode = nodeRegistry.getNodeById(resourceUri); + _nodeRegistryManager.resourceOperationsManager.resourceOperationsHandler.updateGlobalDirtyState(resourceNode.properties[Constants.IS_DIRTY]); +}; + +NodeRegistryManager.prototype.unlinkResourceNodeFromNodeRegistry = function(resourceUri, nodeRegistry) { + // change isDirty to false and dispatch event + var resourceNodeFromRegistry = nodeRegistry.getNodeById(resourceUri); + nodeRegistry.setPropertyValue(resourceNodeFromRegistry, Constants.IS_DIRTY, false); + + var resourceSet = this.resourceUriToResourceSet[resourceUri]; + + // remove resourceUri from resourceSet + var resourceUris = this.resourceSetToResourceUris[resourceSet]; + if (resourceUris != null) { + resourceUris.splice(resourceUris.indexOf(resourceUri), 1); + if (resourceUris.length == 0) { + delete this.resourceSetToResourceUris[resourceSet]; + } + } + + // remove resourceUri from registry + resourceUris = this.getResourceUrisForNodeRegistry(nodeRegistry); + if (resourceUris != null) { + resourceUris.splice(resourceUris.indexOf(resourceUri), 1); + if (resourceNodeFromRegistry.nodeUri != nodeRegistry.getRootNodeUri() && + resourceNodeFromRegistry.parent == null && resourceUris.indexOf(resourceUri) < 0) { + nodeRegistry.unregisterNode(resourceNodeFromRegistry); + } + } + + // remove resourceSet from registry + var nodeRegistries = this.resourceSetToNodeRegistries[resourceSet]; + if (nodeRegistries != null) { + nodeRegistries.splice(nodeRegistries.indexOf(nodeRegistry), 1); + if (nodeRegistries.length == 0 && this.resourceSetToResourceUris[resourceSet] == null) { + delete this.resourceSetToNodeRegistries[resourceSet]; + delete this.resourceUriToResourceSet[resourceUri]; + } + } +}; + +NodeRegistryManager.prototype.expand = function(nodeRegistry, node, context) { + if (node == null || !node.properties[Constants.AUTO_SUBSCRIBE_ON_EXPAND]) { + nodeRegistry.expand(node, context); + } else { + var subscribableResources = node == null ? null : node.properties[Constants.SUBSCRIBABLE_RESOURCES]; + if (subscribableResources != null && subscribableResources.length > 0) { + // a subscribable node => subscribe to the first resource + var subscribableResource = subscribableResources.getItemAt(0); + this.subscribe(subscribableResource.a, nodeRegistry, function(rootNode, resourceNode) { + nodeRegistry.expand(node, context); + }); + } + } +}; + +NodeRegistryManager.prototype.collapse = function(nodeRegistry, node, refreshChildren) { + // get all the resources starting from node + var dirtyResourceUris = []; + var savedResourceUris = []; + + this.getResourceUrisForSubTree(node, nodeRegistry, dirtyResourceUris, savedResourceUris); + + if (dirtyResourceUris.length > 0) { // at least one dirty resourceNode found -> show dialog + this.resourceOperationsManager.showSaveDialog([this], this.getResourceSetsForResourceUris(dirtyResourceUris), + function() { + // wait for server response before collapse + this.collapseHandler(node, nodeRegistry, refreshChildren, dirtyResourceUris, savedResourceUris); + } + ); + } else { + this.collapseHandler(node, nodeRegistry, refreshChildren, dirtyResourceUris, savedResourceUris); + } +}; + +NodeRegistryManager.prototype.collapseHandler = function(node, nodeRegistry, refreshChildren, dirtyResourceUris, savedResourceUris) { + for (var i=0; i < dirtyResourceUris.length; i++) { + this.unlinkResourceNodeFromNodeRegistry(dirtyResourceUris[i], nodeRegistry); + } + for (var i=0; i < savedResourceUris.length; i++) { + this.unlinkResourceNodeFromNodeRegistry(savedResourceUris[i], nodeRegistry); + } + nodeRegistry.collapse(node, refreshChildren); +}; + +/** + * Iterate the subtree starting from node and add all the resources to the dirty or saved resource arrays. + */ +NodeRegistryManager.prototype.getResourceUrisForSubTree = function(node, nodeRegistry, dirtyResourceUris, savedResourceUris) { + var subscribableResources = node.properties[Constants.SUBSCRIBABLE_RESOURCES]; + if (subscribableResources != null) { + for (var i = 0; i < subscribableResources.length; i++){ + var resourceUri = subscribableResources.getItemAt(i).a; + var resourceNode = nodeRegistry.getNodeById(resourceUri); + if (resourceNode != null) { + if (resourceNode.properties[Constants.IS_DIRTY]) { + dirtyResourceUris.push(resourceUri); + } else { + savedResourceUris.push(resourceUri); + } + } + } + } + + // recurse + if (node.children != null) { + for (var i = 0; i < node.children.length; i++){ + this.getResourceUrisForSubTree(node.children.getItemAt(i), nodeRegistry, dirtyResourceUris, savedResourceUris); + } + } +}; + +NodeRegistryManager.prototype.hasSubscribableResource = function(node, resourceUri) { + var subscribableResources = node.properties[Constants.SUBSCRIBABLE_RESOURCES]; + if (subscribableResources == null || subscribableResources.length == 0) { + return false; + } + for (var i = 0; i < subscribableResources.length; i++) { + if (subscribableResources.getItemAt[i].a == resourceUri) { + return true; + } + } + return false; +}; + +/** + * Calls subscribe for nodeId on server. Callback functions: + *
    + *
  • subscribeResultCallback(resourceNode:Node):void + *
  • subscribeFaultCallback(event:FaultEvent):void + *
+ */ +NodeRegistryManager.prototype.subscribe = function(nodeId, nodeRegistry, subscribeResultCallback, subscribeFaultCallback) { + var self = this; + this.serviceInvocator.invoke("resourceService.subscribeToParentResource", [nodeId], + function (subscriptionInfo) { + subscriptionInfo.rootNode = nodeRegistry.mergeOrRegisterNode(subscriptionInfo.rootNode); + if (subscriptionInfo.resourceNode != null) { + subscriptionInfo.resourceNode = nodeRegistry.mergeOrRegisterNode(subscriptionInfo.resourceNode); + self.linkResourceNodeWithNodeRegistry(subscriptionInfo.resourceNode.nodeUri, subscriptionInfo.resourceSet, nodeRegistry); + } + if (subscribeResultCallback != null) { + subscribeResultCallback.call(null, subscriptionInfo.rootNode, subscriptionInfo.resourceNode); + } + }, + function(fault) { + self.externalInvocator.showMessageBox("editor.error.subscribe.title", "editor.error.subscribe.message", [fault.faultString]); + + if (subscribeFaultCallback != null) { + subscribeFaultCallback.call(null, fault); + } + }); +}; + +/** + * Closes all editors without dispatching events and updates global state for save actions. + */ +NodeRegistryManager.prototype.removeNodeRegistries = function(nodeRegistries) { + for (var i = 0; i < nodeRegistries.length; i++) { + var nodeRegistry = nodeRegistries[i]; + var resourceUris = this.getResourceUrisForNodeRegistry(nodeRegistry); + for (var j=0; j < resourceUris.length; j++) { + this.unlinkResourceNodeFromNodeRegistry(resourceUris[j], nodeRegistry); + } + for (var j=0; j < this.listeners.length; j++) { + this.listeners[j].nodeRegistryRemoved(nodeRegistry); + } + } + + this.resourceOperationsManager.resourceOperationsHandler.updateGlobalDirtyState(false); +}; + +NodeRegistryManager.prototype.getResourceSetsForResourceUris = function(resourceUris) { + var resourceSets = []; + for (var i = 0; i < resourceUris.length; i++) { + var resourceSet = this.resourceUriToResourceSet[resourceUris[i]]; + if (resourceSets.indexOf(resourceSet) < 0) { + resourceSets.push(resourceSet); + } + } + return resourceSets; +}; + +/** + * @param dirtyResourceNodeHandler function will be executed each time a dirty resourceNode is found. + * @return all dirty resourceUris found in nodeRegistries, without duplicates. + */ +NodeRegistryManager.prototype.getDirtyResourceSetsFromNodeRegistries = function(nodeRegistries, dirtyResourceNodeHandler) { + var dirtyResourceSets = []; + for (var i = 0; i < nodeRegistries.length; i++) { + var nodeRegistry = nodeRegistries[i]; + var resourceUris = this.getResourceUrisForNodeRegistry(nodeRegistry); + for (var j=0; j < resourceUris.length; j++) { + var resourceUri = resourceUris[j]; + var resourceSet = this.resourceUriToResourceSet[resourceUri]; + if (this.isResourceNodeDirty(resourceUri, nodeRegistry) && dirtyResourceSets.indexOf(resourceSet) == -1) { + if (dirtyResourceNodeHandler != null) { + dirtyResourceNodeHandler(resourceSet); + } + dirtyResourceSets.push(resourceSet); + } + } + } + return dirtyResourceSets; +}; + +/** + * @param returnIfAtLeastOneDirtyResourceNodeFound if true, returns the first dirty resourceNodeId found. + * @param dirtyResourceNodeHandler function will be executed each time a dirty resourceNode is found. + * @return all dirty resourceUris, without duplicates. + */ +NodeRegistryManager.prototype.getAllDirtyResourceSets = function(returnIfAtLeastOneDirtyResourceNodeFound, dirtyResourceNodeHandler) { + var dirtyResourceSets = []; + var nodeRegistries = this.getNodeRegistries(); + for (var i = 0; i < nodeRegistries.length; i++) { + var resourceUris = this.getResourceUrisForNodeRegistry(nodeRegistries[i]); + for (var j = 0; j < resourceUris.length; j++) { + var resourceSet = this.resourceUriToResourceSet[resourceUris[j]]; + if (this.isResourceNodeDirty(resourceUris[j], nodeRegistries[i]) && dirtyResourceSets.indexOf(resourceSet) == -1) { + if (returnIfAtLeastOneDirtyResourceNodeFound) { + return [resourceSet]; + } + if (dirtyResourceNodeHandler != null) { + dirtyResourceNodeHandler(resourceSet); + } + dirtyResourceSets.push(resourceSet); + } + } + } + return dirtyResourceSets; +}; + +NodeRegistryManager.prototype.processUpdates = function(resourceNodeIdToUpdates) { + for (var resourceNodeId in resourceNodeIdToUpdates) { + var updates = resourceNodeIdToUpdates[resourceNodeId]; + var nodeRegistries = this.getNodeRegistriesForResourceSet(resourceNodeId); + for (var i = 0; i < nodeRegistries.length; i++) { + nodeRegistries[i].processUpdates(updates); + } + } +}; + +/** + * Unlink resourceUris from node registries. + * + *

+ * Dispatches resourceNodeRemoved for each NodeRegistry found. + * Note: Additional behavior can be added by listening to this event (e.g. in case of an editor, close it). + */ +NodeRegistryManager.prototype.unlinkResourceNodesForcefully = function(resourceUris) { + var idsList = ""; + for (var i = 0; i < resourceUris.length; i++) { + var nodeRegistries = this.getNodeRegistriesForResourceSet(resourceUris[i]); + for (var j = 0; j < nodeRegistries.length; j++) { + this.unlinkResourceNodeFromNodeRegistry(resourceUris[i], nodeRegistries[j]); + for (var k = 0; k < this.listeners.length; k++) { + this.listeners[k].resourceNodeRemoved(resourceUris[i], nodeRegistries[j]); + } + } + idsList += "\n* " + resourceUris[i]; + } + this.externalInvocator.showMessageBox("editor.error.subscribe.title", "editor.error.subscribe.message", [idsList]); +}; + +NodeRegistryManager.prototype.isResourceNodeDirty = function(resourceNodeId, nodeRegistry) { + var node = nodeRegistry.getNodeById(resourceNodeId); + return node == null ? false : node.properties[Constants.IS_DIRTY]; +}; + +NodeRegistryManager.prototype.resourceNodeUpdated = function(event) { + if (event.property == Constants.IS_DIRTY) { + _nodeRegistryManager.resourceOperationsManager.resourceOperationsHandler.updateGlobalDirtyState(event.newValue); + } +}; + +NodeRegistryManager.prototype.contains = function(list, obj) { + for (var i=0; i < list.length; i++) { + if (list[i] == obj) { + return true; + } + } + return false; +}; + +var Constants = {IS_DIRTY: "isDirty", SUBSCRIBABLE_RESOURCES: "subscribableResources", AUTO_SUBSCRIBE_ON_EXPAND: "autoSubscribeOnExpand"}; + +var _nodeRegistryManager; \ No newline at end of file diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/ResourceOperationsManager.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/ResourceOperationsManager.js new file mode 100644 index 00000000..aae232d8 --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/ResourceOperationsManager.js @@ -0,0 +1,87 @@ +/* license-start + * + * Copyright (C) 2008 - 2013 Crispico Software, . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, at . + * + * license-end + */ + +var ResourceOperationsManager = function(nodeRegistryManager, resourceOperationsHandler) { + this.nodeRegistryManager = nodeRegistryManager; + this.resourceOperationsHandler = resourceOperationsHandler; + this.resourceOperationsHandler.nodeRegistryManager = nodeRegistryManager; +}; + +ResourceOperationsManager.prototype.showSaveDialog = function(nodeRegistries, dirtyResourceNodeIds, handler) { + if (nodeRegistries == null) { + nodeRegistries = this.nodeRegistryManager.getNodeRegistries(); + } + + var dirtyResourceNodes = this.nodeRegistryManager.externalInvocator.getNewListInstance(); + if (dirtyResourceNodeIds == null) { + this.nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries(nodeRegistries, function(dirtyResourceNodeId) { + dirtyResourceNodes.addItem({resourceNodeId: dirtyResourceNodeId, selected: true}); + }); + } else { + for (var i = 0; i < dirtyResourceNodeIds.length; i++) { + dirtyResourceNodes.addItem({resourceNodeId: dirtyResourceNodeIds[i], selected: true}); + } + } + if (dirtyResourceNodes.length == 0) { + if (handler != null) { + handler.call(); + } else { + this.nodeRegistryManager.removeNodeRegistries(nodeRegistries); + } + return; + } + this.resourceOperationsHandler.showSaveDialog(nodeRegistries, dirtyResourceNodes, handler); +}; + +ResourceOperationsManager.prototype.showReloadDialog = function(nodeRegistries, resourceSets) { + if (nodeRegistries == null) { + nodeRegistries = this.nodeRegistryManager.getNodeRegistries(); + } + if (resourceSets == null) { + resourceSets = this.nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries(nodeRegistries); + } + this.resourceOperationsHandler.showReloadDialog(nodeRegistries, resourceSets); +}; + +ResourceOperationsManager.prototype.save = function(nodeRegistry) { + var dirtyResourceNodeIds = this.nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries([nodeRegistry]); + if (dirtyResourceNodeIds.length == 1) { + // single resourceNode to save -> save without asking + this.nodeRegistryManager.serviceInvocator.invoke("resourceService.save", [dirtyResourceNodeIds[0]]); + } else { + // multiple resourceNodes to save -> show dialog + this.showSaveDialog([nodeRegistry], dirtyResourceNodeIds, function() {}); + } +}; + +ResourceOperationsManager.prototype.saveAll = function() { + var self = this; + this.nodeRegistryManager.getAllDirtyResourceSets(false, function(dirtyResourceNodeId) { + // for each dirty resourceNode found -> save it + self.nodeRegistryManager.serviceInvocator.invoke("resourceService.save", [dirtyResourceNodeId]); + }); +}; + +ResourceOperationsManager.prototype.reload = function(nodeRegistry) { + var resourceSets = this.nodeRegistryManager.getDirtyResourceSetsFromNodeRegistries([nodeRegistry]); + if (resourceSets.length == 1) { + // single resourceNode to reload -> reload without asking + this.nodeRegistryManager.serviceInvocator.invoke("resourceService.reload", [resourceSets[0]]); + } else { + // multiple resourceNodes -> show dialog + this.showReloadDialog([nodeRegistry], resourceSets); + } +}; \ No newline at end of file diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IExternalInvocator.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IExternalInvocator.js new file mode 100644 index 00000000..18a507ab --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IExternalInvocator.js @@ -0,0 +1,14 @@ +/* +IExternalInvocator { + + getNewListInstance(); + + getNewFullNodeIdWithChildrenInstance(); + + getServiceContextInstance(); + + showMessageBox(titleKeyMessage, textKeyMessage, textParams); + +} + +*/ \ No newline at end of file diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IList.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IList.js new file mode 100644 index 00000000..770a36c4 --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IList.js @@ -0,0 +1,17 @@ +/* +IList { + + function contains(obj:Object); + + function getItemAt(index:int); + function getItemIndex(obj:Object); + + function removeItemAt(index:int); + + function length(); + + function addItem(obj:Object); + function addItemAt(obj:Object, index:int); + +} +*/ \ No newline at end of file diff --git a/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IServiceInvocator.js b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IServiceInvocator.js new file mode 100644 index 00000000..fb3a7498 --- /dev/null +++ b/org.flowerplatform.js_client.core/WebContent/js/node_registry/skeleton/IServiceInvocator.js @@ -0,0 +1,8 @@ +/* +IServiceInvocator { + + invoke(serviceIdAndMethodName, parameters, resultCallback, faultCallback); + +} + +*/ \ No newline at end of file diff --git a/org.flowerplatform.js_client.java/.classpath b/org.flowerplatform.js_client.java/.classpath new file mode 100644 index 00000000..59f8ccfe --- /dev/null +++ b/org.flowerplatform.js_client.java/.classpath @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.flowerplatform.js_client.java/.gitignore b/org.flowerplatform.js_client.java/.gitignore new file mode 100644 index 00000000..5e56e040 --- /dev/null +++ b/org.flowerplatform.js_client.java/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/org.flowerplatform.js_client.java/.project b/org.flowerplatform.js_client.java/.project new file mode 100644 index 00000000..73511566 --- /dev/null +++ b/org.flowerplatform.js_client.java/.project @@ -0,0 +1,28 @@ + + + org.flowerplatform.js_client.java + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.flowerplatform.js_client.java/META-INF/MANIFEST.MF b/org.flowerplatform.js_client.java/META-INF/MANIFEST.MF new file mode 100644 index 00000000..949a9529 --- /dev/null +++ b/org.flowerplatform.js_client.java/META-INF/MANIFEST.MF @@ -0,0 +1,35 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Java +Bundle-SymbolicName: org.flowerplatform.js_client.java;singleton:=true +Bundle-Version: 1.0.0.qualifier +Require-Bundle: org.flowerplatform.js_client.core, + org.flowerplatform.util, + org.eclipse.core.runtime, + org.flowerplatform.core +Export-Package: org.flowerplatform.js_client.java, + org.mozilla.javascript +Bundle-ClassPath: lib-from-maven/aopalliance-repackaged-2.3.0-b05.jar, + lib-from-maven/hk2-api-2.3.0-b05.jar, + lib-from-maven/hk2-locator-2.3.0-b05.jar, + lib-from-maven/hk2-utils-2.3.0-b05.jar, + lib-from-maven/jackson-annotations-2.3.2.jar, + lib-from-maven/jackson-core-2.3.2.jar, + lib-from-maven/jackson-databind-2.3.2.jar, + lib-from-maven/jackson-jaxrs-base-2.3.2.jar, + lib-from-maven/jackson-jaxrs-json-provider-2.3.2.jar, + lib-from-maven/jackson-module-jaxb-annotations-2.3.2.jar, + lib-from-maven/javassist-3.18.1-GA.jar, + lib-from-maven/javax.annotation-api-1.2.jar, + lib-from-maven/javax.inject-2.3.0-b05.jar, + lib-from-maven/jersey-client-2.11.jar, + lib-from-maven/jersey-common-2.11.jar, + lib-from-maven/jersey-container-servlet-2.11.jar, + lib-from-maven/jersey-container-servlet-core-2.11.jar, + lib-from-maven/jersey-guava-2.11.jar, + lib-from-maven/jersey-media-json-jackson-2.11.jar, + lib-from-maven/jersey-server-2.11.jar, + lib-from-maven/osgi-resource-locator-1.0.1.jar, + lib-from-maven/rhino-1.7R4.jar, + lib-from-maven/validation-api-1.1.0.Final.jar, + . diff --git a/org.flowerplatform.js_client.java/build.properties b/org.flowerplatform.js_client.java/build.properties new file mode 100644 index 00000000..6fa627db --- /dev/null +++ b/org.flowerplatform.js_client.java/build.properties @@ -0,0 +1,27 @@ +source.. = src/ +bin.includes = META-INF/,\ + .,\ + lib-from-maven/aopalliance-repackaged-2.3.0-b05.jar,\ + lib-from-maven/hk2-api-2.3.0-b05.jar,\ + lib-from-maven/hk2-locator-2.3.0-b05.jar,\ + lib-from-maven/hk2-utils-2.3.0-b05.jar,\ + lib-from-maven/jackson-annotations-2.3.2.jar,\ + lib-from-maven/jackson-core-2.3.2.jar,\ + lib-from-maven/jackson-databind-2.3.2.jar,\ + lib-from-maven/jackson-jaxrs-base-2.3.2.jar,\ + lib-from-maven/jackson-jaxrs-json-provider-2.3.2.jar,\ + lib-from-maven/jackson-module-jaxb-annotations-2.3.2.jar,\ + lib-from-maven/javassist-3.18.1-GA.jar,\ + lib-from-maven/javax.annotation-api-1.2.jar,\ + lib-from-maven/javax.inject-2.3.0-b05.jar,\ + lib-from-maven/jersey-client-2.11.jar,\ + lib-from-maven/jersey-common-2.11.jar,\ + lib-from-maven/jersey-container-servlet-2.11.jar,\ + lib-from-maven/jersey-container-servlet-core-2.11.jar,\ + lib-from-maven/jersey-guava-2.11.jar,\ + lib-from-maven/jersey-media-json-jackson-2.11.jar,\ + lib-from-maven/jersey-server-2.11.jar,\ + lib-from-maven/osgi-resource-locator-1.0.1.jar,\ + lib-from-maven/rhino-1.7R4.jar,\ + lib-from-maven/validation-api-1.1.0.Final.jar,\ + plugin.xml diff --git a/org.flowerplatform.js_client.java/lib-from-maven-pom.xml b/org.flowerplatform.js_client.java/lib-from-maven-pom.xml new file mode 100644 index 00000000..cf74035c --- /dev/null +++ b/org.flowerplatform.js_client.java/lib-from-maven-pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + org.flowerplatform + org.flowerplatform.js_client.server + 1.0 + + + + org.glassfish.jersey.containers + jersey-container-servlet + 2.11 + provided + + + + + javax.ws.rs + javax.ws.rs-api + + + + + org.glassfish.jersey.media + jersey-media-json-jackson + 2.11 + + + org.mozilla + rhino + 1.7R4 + + + \ No newline at end of file diff --git a/org.flowerplatform.js_client.java/lib-from-maven/aopalliance-repackaged-2.3.0-b05.jar b/org.flowerplatform.js_client.java/lib-from-maven/aopalliance-repackaged-2.3.0-b05.jar new file mode 100644 index 00000000..7d0010d0 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/aopalliance-repackaged-2.3.0-b05.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/hk2-api-2.3.0-b05.jar b/org.flowerplatform.js_client.java/lib-from-maven/hk2-api-2.3.0-b05.jar new file mode 100644 index 00000000..7d848188 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/hk2-api-2.3.0-b05.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/hk2-locator-2.3.0-b05.jar b/org.flowerplatform.js_client.java/lib-from-maven/hk2-locator-2.3.0-b05.jar new file mode 100644 index 00000000..0a87a823 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/hk2-locator-2.3.0-b05.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/hk2-utils-2.3.0-b05.jar b/org.flowerplatform.js_client.java/lib-from-maven/hk2-utils-2.3.0-b05.jar new file mode 100644 index 00000000..2db5eea5 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/hk2-utils-2.3.0-b05.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-annotations-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-annotations-2.3.2.jar new file mode 100644 index 00000000..7ea186fd Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-annotations-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-core-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-core-2.3.2.jar new file mode 100644 index 00000000..0b000af5 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-core-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-databind-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-databind-2.3.2.jar new file mode 100644 index 00000000..0449f39c Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-databind-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-base-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-base-2.3.2.jar new file mode 100644 index 00000000..0dc889a8 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-base-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-json-provider-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-json-provider-2.3.2.jar new file mode 100644 index 00000000..ce761765 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-jaxrs-json-provider-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jackson-module-jaxb-annotations-2.3.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/jackson-module-jaxb-annotations-2.3.2.jar new file mode 100644 index 00000000..af3bde58 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jackson-module-jaxb-annotations-2.3.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/javassist-3.18.1-GA.jar b/org.flowerplatform.js_client.java/lib-from-maven/javassist-3.18.1-GA.jar new file mode 100644 index 00000000..d5f19ac5 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/javassist-3.18.1-GA.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/javax.annotation-api-1.2.jar b/org.flowerplatform.js_client.java/lib-from-maven/javax.annotation-api-1.2.jar new file mode 100644 index 00000000..9ab39ffa Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/javax.annotation-api-1.2.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/javax.inject-2.3.0-b05.jar b/org.flowerplatform.js_client.java/lib-from-maven/javax.inject-2.3.0-b05.jar new file mode 100644 index 00000000..762e113e Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/javax.inject-2.3.0-b05.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-client-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-client-2.11.jar new file mode 100644 index 00000000..f18e3f7a Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-client-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-common-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-common-2.11.jar new file mode 100644 index 00000000..180468cc Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-common-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-2.11.jar new file mode 100644 index 00000000..ddda1f97 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-core-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-core-2.11.jar new file mode 100644 index 00000000..17b9cd16 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-container-servlet-core-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-guava-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-guava-2.11.jar new file mode 100644 index 00000000..4c1189a8 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-guava-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-media-json-jackson-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-media-json-jackson-2.11.jar new file mode 100644 index 00000000..bc62a9c9 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-media-json-jackson-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/jersey-server-2.11.jar b/org.flowerplatform.js_client.java/lib-from-maven/jersey-server-2.11.jar new file mode 100644 index 00000000..413262a9 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/jersey-server-2.11.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/osgi-resource-locator-1.0.1.jar b/org.flowerplatform.js_client.java/lib-from-maven/osgi-resource-locator-1.0.1.jar new file mode 100644 index 00000000..bd6aa17e Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/osgi-resource-locator-1.0.1.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/rhino-1.7R4.jar b/org.flowerplatform.js_client.java/lib-from-maven/rhino-1.7R4.jar new file mode 100644 index 00000000..6f0dafbb Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/rhino-1.7R4.jar differ diff --git a/org.flowerplatform.js_client.java/lib-from-maven/validation-api-1.1.0.Final.jar b/org.flowerplatform.js_client.java/lib-from-maven/validation-api-1.1.0.Final.jar new file mode 100644 index 00000000..de854038 Binary files /dev/null and b/org.flowerplatform.js_client.java/lib-from-maven/validation-api-1.1.0.Final.jar differ diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/ClientObjectMapperProvider.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/ClientObjectMapperProvider.java new file mode 100644 index 00000000..3d4c7fd1 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/ClientObjectMapperProvider.java @@ -0,0 +1,33 @@ +package org.flowerplatform.js_client.java; + +import javax.ws.rs.ext.ContextResolver; +import javax.ws.rs.ext.Provider; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; + +/** + * @see JsServiceInvocator + * @author Cristina Constantinescu + */ +@Provider +public class ClientObjectMapperProvider implements ContextResolver { + + private ObjectMapper objectMapper; + + public ClientObjectMapperProvider() { + objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JaxbAnnotationModule()); + objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + } + + @Override + public ObjectMapper getContext(Class type) { + return objectMapper; + } + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/Fault.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/Fault.java new file mode 100644 index 00000000..2060ba92 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/Fault.java @@ -0,0 +1,40 @@ +package org.flowerplatform.js_client.java; + +import javax.ws.rs.core.Response.StatusType; + +/** + * Used as parameter in a faultCallback handler. + * + *

+ * Corresponds to mx.rpc.Fault. + * + * @author Cristina Constantinescu + */ +//TODO CC: this class can be improved to show exception message too +public class Fault { + + private StatusType status; + + public Fault(StatusType status) { + this.status = status; + } + + public int faultCode() { + return status.getStatusCode(); + } + + public String faultString() { + return status.getReasonPhrase(); + } + + public String faultContent() { + return ""; + } + + @Override + public String toString() { + return "Fault [faultCode()=" + faultCode() + ", faultString()=" + + faultString() + ", faultContent()=" + faultContent() + "]"; + } + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/IFunctionInvoker.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/IFunctionInvoker.java new file mode 100644 index 00000000..63aad6ae --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/IFunctionInvoker.java @@ -0,0 +1,15 @@ +package org.flowerplatform.js_client.java; + +/** + * Used when needed to send a method as parameter. + * + *

+ * Corresponds to flex Function. + * + * @author Cristina Constantinescu + */ +public interface IFunctionInvoker { + + public void call(Object instance, Object... params); + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeChangeListener.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeChangeListener.java new file mode 100644 index 00000000..8ac83ef2 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeChangeListener.java @@ -0,0 +1,14 @@ +package org.flowerplatform.js_client.java; + +/** + * @author Cristina Constantinescu + */ +public interface INodeChangeListener { + + void nodeRemoved(Object node); + + void nodeAdded(Object node); + + void nodeUpdated(Object node, String property, Object oldValue, Object newValue); + +} \ No newline at end of file diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeRegistryManagerListener.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeRegistryManagerListener.java new file mode 100644 index 00000000..6efbfc40 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/INodeRegistryManagerListener.java @@ -0,0 +1,12 @@ +package org.flowerplatform.js_client.java; + +/** + * @author Cristina Constantinescu + */ +public interface INodeRegistryManagerListener { + + void nodeRegistryRemoved(Object nodeRegistry); + + void resourceNodeRemoved(String resourceNodeUri, Object nodeRegistry); + +} \ No newline at end of file diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsExternalInvocator.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsExternalInvocator.java new file mode 100644 index 00000000..62a2b2dd --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsExternalInvocator.java @@ -0,0 +1,31 @@ +package org.flowerplatform.js_client.java; + +import org.flowerplatform.core.node.remote.FullNodeIdWithChildren; +import org.flowerplatform.core.node.remote.ServiceContext; + +/** + * @author Cristina Constantinescu + */ +public class JsExternalInvocator { + + /** + * Used to instantiate children in node object. + */ + public JsList getNewListInstance() { + return new JsList<>(); + } + + public FullNodeIdWithChildren getNewFullNodeIdWithChildrenInstance() { + return new FullNodeIdWithChildren(); + } + + public ServiceContext getServiceContextInstance() { + return new ServiceContext<>(); + } + + public void showMessageBox(String titleKeyMessage, String textKeyMessage, String[] textParams) { + // TODO implement + System.out.println("showMessageBox(" + titleKeyMessage + " " + textKeyMessage + " " + textParams); + } + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsList.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsList.java new file mode 100644 index 00000000..f8a2d317 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsList.java @@ -0,0 +1,42 @@ +package org.flowerplatform.js_client.java; + +import java.util.ArrayList; + +/** + * Provides additional behavior to match mx.collections.IList. + * @author Cristina Constantinescu + */ +public class JsList extends ArrayList { + + private static final long serialVersionUID = 1L; + + @Override + public boolean contains(Object o) { + return super.contains(o); + } + + public int getItemIndex(Object o) { + return indexOf(o); + } + + public E getItemAt(int index) { + return get(index); + } + + public E removeItemAt(int index) { + return remove(index); + } + + public int length() { + return super.size(); + } + + public void addItem(E o) { + add(o); + } + + public void addItemAt(E o, int index) { + add(index, o); + } + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsResourceOperationsHandler.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsResourceOperationsHandler.java new file mode 100644 index 00000000..b0eb1933 --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsResourceOperationsHandler.java @@ -0,0 +1,24 @@ +package org.flowerplatform.js_client.java; + +import org.mozilla.javascript.Function; + +/** + * @author Cristina Constantinescu + */ +public class JsResourceOperationsHandler { + + public Object nodeRegistryManager; + + public void updateGlobalDirtyState(Boolean someResourceNodeHasBecomeDirty) { + // TODO implement + } + + public void showSaveDialog(Object[] nodeRegistries, JsList dirtyResourceNodes, Function handler) { + // TODO implement + } + + public void showReloadDialog(Object[] nodeRegistries, Object[] resourceSets) { + // TODO implement + } + +} diff --git a/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsServiceInvocator.java b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsServiceInvocator.java new file mode 100644 index 00000000..7893107a --- /dev/null +++ b/org.flowerplatform.js_client.java/src/org/flowerplatform/js_client/java/JsServiceInvocator.java @@ -0,0 +1,107 @@ +package org.flowerplatform.js_client.java; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; + +import org.flowerplatform.core.CoreConstants; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.mozilla.javascript.Callable; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.NativeJSON; +import org.mozilla.javascript.Scriptable; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; + +/** + * @author Cristina Constantinescu + */ +public class JsServiceInvocator { + + private static final String METHOD_INVOCATION_SERVICE = "/ws-dispatcher/javaClientMethodInvocationService"; + private static final String SERVICE_DOT_METHOD_NAME = "serviceDotMethodName"; + private static final String PARAMETERS = "parameters"; + + private WebTarget client; + + public WebTarget getClient() { + if (client == null) { + client = ClientBuilder.newClient() + .register(JacksonFeature.class) + .register(JacksonJaxbJsonProvider.class) + .register(ClientObjectMapperProvider.class) + .target(getBaseURI()); + client = client.path(METHOD_INVOCATION_SERVICE); + } + return client; + } + + // TODO CC: temp URI + private static URI getBaseURI() { + return UriBuilder.fromUri("http://localhost:8080/org.flowerplatform.host.web_app/").build(); + } + + public void invoke(String serviceIdAndMethodName, Object[] parameters) { + this.invoke(serviceIdAndMethodName, parameters, null, null); + } + + public void invoke(String serviceIdAndMethodName, Object[] parameters, Function resultCallback) { + this.invoke(serviceIdAndMethodName, parameters, resultCallback, null); + } + + public void invoke(String serviceIdAndMethodName, Object[] parameters, Function resultCallback, Function faultCallback) { + // create the map sent as parameter + Map requestParams = new HashMap<>(); + requestParams.put(SERVICE_DOT_METHOD_NAME, serviceIdAndMethodName); + requestParams.put(PARAMETERS, parameters); + + // send request + Response response = getClient().request().post(Entity.entity(requestParams, MediaType.APPLICATION_JSON_TYPE)); + + if (response.getStatus() != Status.OK.getStatusCode()) { + // request failed + if (faultCallback != null) { + Context cx = Context.enter(); + Scriptable scope = cx.initStandardObjects(); + try { + faultCallback.call(cx, scope, scope, new Object[] {new Fault(response.getStatusInfo())}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } else if (resultCallback != null) { + // get result + HashMap node = response.readEntity(HashMap.class); + Object result = node.get(CoreConstants.MESSAGE_RESULT); + + Context cx = Context.enter(); + Scriptable scope = cx.initStandardObjects(); + try { + // convert result to json + String json = new ObjectMapper().writeValueAsString(result); + + // convert json to js compatible object + Object jsonObj = NativeJSON.parse(cx, scope, json, new Callable() { + @Override + public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + return args[1]; + } + }); + resultCallback.call(cx, scope, scope, new Object[] {jsonObj}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + +} diff --git a/org.flowerplatform.js_client.server/META-INF/MANIFEST.MF b/org.flowerplatform.js_client.server/META-INF/MANIFEST.MF index 14ddca43..f8362354 100644 --- a/org.flowerplatform.js_client.server/META-INF/MANIFEST.MF +++ b/org.flowerplatform.js_client.server/META-INF/MANIFEST.MF @@ -35,3 +35,4 @@ Import-Package: javax.servlet, javax.servlet.http Eclipse-RegisterBuddy: org.flowerplatform.util Bundle-ActivationPolicy: lazy +Export-Package: com.fasterxml.jackson.databind diff --git a/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/ObjectMapperProvider.java b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/ObjectMapperProvider.java index 5d881bb1..34828a2e 100644 --- a/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/ObjectMapperProvider.java +++ b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/ObjectMapperProvider.java @@ -3,6 +3,7 @@ import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; @@ -21,6 +22,9 @@ public ObjectMapperProvider() { objectMapper = new ObjectMapper(); objectMapper.registerModule(new JaxbAnnotationModule()); objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // CC: probably this will generate problems on web app!!! + objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); } @Override diff --git a/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/WebServicesConfig.java b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/WebServicesConfig.java index 354db783..e2c9c775 100644 --- a/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/WebServicesConfig.java +++ b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/WebServicesConfig.java @@ -1,6 +1,7 @@ package org.flowerplatform.js_client.server; import org.flowerplatform.core.CorePlugin; +import org.flowerplatform.js_client.server.remote.JavaClientMethodInvocationService; import org.glassfish.jersey.filter.LoggingFilter; import org.glassfish.jersey.jackson.JacksonFeature; import org.glassfish.jersey.server.ResourceConfig; @@ -14,11 +15,12 @@ */ public class WebServicesConfig extends ResourceConfig { - public WebServicesConfig() throws ClassNotFoundException { + public WebServicesConfig() throws ClassNotFoundException { for (Object service : CorePlugin.getInstance().getServiceRegistry().getMap().values()) { register(service); } - + register(new JavaClientMethodInvocationService()); + register(new RemoteMethodInvocationFilter()); register(new RemoteMethodInvocationWriterInterceptor()); diff --git a/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/remote/JavaClientMethodInvocationService.java b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/remote/JavaClientMethodInvocationService.java new file mode 100644 index 00000000..adce2b30 --- /dev/null +++ b/org.flowerplatform.js_client.server/src/org/flowerplatform/js_client/server/remote/JavaClientMethodInvocationService.java @@ -0,0 +1,69 @@ +package org.flowerplatform.js_client.server.remote; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.flowerplatform.core.CorePlugin; + +/** + * All java client methods invoked from js will be handled by this service. + * + *

+ * requestParams contains: + *

    + *
  • {@value #SERVICE_DOT_METHOD_NAME} -> serviceId.methodName + *
  • {@value #PARAMETERS} -> Object[] + *
+ * + * We use this solution because: + *
    + *
  • Jersey server doesn't support multiple normal parameters for get/post/put... + *
  • with {@link QueryParam}s we must put annotations to all additional service method's parameters + *
  • it is possible to have different resource paths for service or method (not the exact id or method name). + *
+ * + * @author Cristina Constantinescu + */ +@Path("/javaClientMethodInvocationService") +public class JavaClientMethodInvocationService { + + private static final String SERVICE_DOT_METHOD_NAME = "serviceDotMethodName"; + private static final String PARAMETERS = "parameters"; + + @POST + @Produces(MediaType.APPLICATION_JSON) + public Object invoke(HashMap requestParams) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + String serviceAndMethod = (String) requestParams.get(SERVICE_DOT_METHOD_NAME); + Object[] parameters = (Object[]) requestParams.get(PARAMETERS); + + String[] tokens = serviceAndMethod.split("\\."); + String serviceName = tokens[0]; + String methodName = tokens[1]; + + Object service = CorePlugin.getInstance().getServiceRegistry().getService(serviceName); + if (service == null) { + throw new RuntimeException(String.format("The service with id='%s' was not found in the service registry.", serviceName)); + } + // find the method + Method foundMethod = null; + for (Method method : service.getClass().getMethods()) { + if (method.getName().equals(methodName)) { + foundMethod = method; + break; + } + } + if (foundMethod == null) { + throw new RuntimeException(String.format("The service with id='%s' doesn't contain the method '%s'", serviceName, methodName)); + } + // invoke the method + return foundMethod.invoke(service, parameters); + } + +} diff --git a/org.flowerplatform.product/flowerplatform.product b/org.flowerplatform.product/flowerplatform.product index d1f545e9..c17943a2 100644 --- a/org.flowerplatform.product/flowerplatform.product +++ b/org.flowerplatform.product/flowerplatform.product @@ -78,6 +78,7 @@ + @@ -138,6 +139,7 @@ + diff --git a/org.flowerplatform.tests/META-INF/MANIFEST.MF b/org.flowerplatform.tests/META-INF/MANIFEST.MF index 118df01f..1c29f312 100644 --- a/org.flowerplatform.tests/META-INF/MANIFEST.MF +++ b/org.flowerplatform.tests/META-INF/MANIFEST.MF @@ -20,7 +20,9 @@ Require-Bundle: org.eclipse.jdt.core, org.eclipse.equinox.common, org.eclipse.osgi, org.eclipse.compare.core, - com.ibm.icu + com.ibm.icu, + org.flowerplatform.js_client.java, + org.flowerplatform.js_client.server Bundle-Activator: org.flowerplatform.tests.TestActivator Bundle-ActivationPolicy: lazy Bundle-ClassPath: lib-from-maven/mockito-all-1.9.5.jar, diff --git a/org.flowerplatform.tests/src/org/flowerplatform/tests/core/INodeChangedListener.java b/org.flowerplatform.tests/src/org/flowerplatform/tests/core/INodeChangedListener.java deleted file mode 100644 index eca235b6..00000000 --- a/org.flowerplatform.tests/src/org/flowerplatform/tests/core/INodeChangedListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ -package org.flowerplatform.tests.core; - -import org.flowerplatform.core.node.remote.Node; - -/** - * @author Cristina Constantinescu - */ -public interface INodeChangedListener { - - void nodeChanged(Node node); - -} \ No newline at end of file diff --git a/org.flowerplatform.tests/src/org/flowerplatform/tests/core/NodeRegistryScriptTest.java b/org.flowerplatform.tests/src/org/flowerplatform/tests/core/NodeRegistryScriptTest.java index 8e544c13..0cbadb2b 100644 --- a/org.flowerplatform.tests/src/org/flowerplatform/tests/core/NodeRegistryScriptTest.java +++ b/org.flowerplatform.tests/src/org/flowerplatform/tests/core/NodeRegistryScriptTest.java @@ -1,70 +1,117 @@ -/* license-start - * - * Copyright (C) 2008 - 2013 Crispico Software, . - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 3. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, at . - * - * license-end - */ package org.flowerplatform.tests.core; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; - -import javax.script.Invocable; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; -import org.flowerplatform.core.node.remote.Node; -import org.flowerplatform.tests.TestUtil; -import org.junit.Assert; +import org.flowerplatform.js_client.java.IFunctionInvoker; +import org.flowerplatform.js_client.java.INodeChangeListener; +import org.flowerplatform.js_client.java.INodeRegistryManagerListener; +import org.flowerplatform.js_client.java.JsExternalInvocator; +import org.flowerplatform.js_client.java.JsResourceOperationsHandler; +import org.flowerplatform.js_client.java.JsServiceInvocator; import org.junit.Test; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Function; +import org.mozilla.javascript.NativeObject; +import org.mozilla.javascript.Scriptable; /** * @author Cristina Constantinescu */ public class NodeRegistryScriptTest { + + private static String BASE_URL = "http://localhost:8080/org.flowerplatform.host.web_app"; - public static final String DIR = TestUtil.getResourcesDir(NodeRegistryScriptTest.class); - - ScriptEngine engine; + class NodeChangedListener implements INodeChangeListener { + @Override + public void nodeRemoved(Object node) { + System.out.println(String.format("nodeRemoved -> %s", ((NativeObject) node).get("nodeUri"))); + } + @Override + public void nodeAdded(Object node) { + System.out.println(String.format("nodeAdded -> %s", ((NativeObject) node).get("nodeUri"))); + } + @Override + public void nodeUpdated(Object node, String property, Object oldValue, Object newValue) { + System.out.println(String.format("nodeUpdated -> %s, property=%s, oldValue=%s, newValue=%s", ((NativeObject) node).get("nodeUri"), property, oldValue, newValue)); + } + } - class NodeChangedListener implements INodeChangedListener { - + class NodeRegistryManagerListener implements INodeRegistryManagerListener { @Override - public void nodeChanged(Node node) { - Assert.assertEquals(node.getType(), "newType"); + public void nodeRegistryRemoved(Object nodeRegistry) { + System.out.println("nodeRegistryRemoved"); + } + @Override + public void resourceNodeRemoved(String resourceNodeUri, Object nodeRegistry) { + System.out.println("resourceNodeRemoved"); } } + private void load(Context cx, Scriptable scope) throws Exception { + URL url = new URL(BASE_URL + "/js_client.core/js/node_registry/NodeRegistry.js"); + cx.evaluateReader(scope, new BufferedReader(new InputStreamReader(url.openStream())), null, 1, null); + + url = new URL(BASE_URL + "/js_client.core/js/node_registry/ResourceOperationsManager.js"); + cx.evaluateReader(scope, new BufferedReader(new InputStreamReader(url.openStream())), null, 1, null); + + url = new URL(BASE_URL + "/js_client.core/js/node_registry/NodeRegistryManager.js"); + cx.evaluateReader(scope, new BufferedReader(new InputStreamReader(url.openStream())), null, 1, null); + } + @Test - public void runJavaScriptFunction() { - try { - ScriptEngineManager manager = new ScriptEngineManager(); - engine = manager.getEngineByName("JavaScript"); - // read script file - engine.eval(Files.newBufferedReader(Paths.get(DIR + "/jsFile.js"), StandardCharsets.UTF_8)); - - Object nodeRegistry = engine.get("nodeRegistry"); + public void runJavaScriptFunction() throws Exception { + Context cx = Context.enter(); + Function fct; + try { + Scriptable scope = cx.initStandardObjects(); + + // load scripts + load(cx, scope); + + // create nodeRegistryManager + Scriptable nodeRegistryManager = cx.newObject(scope, "NodeRegistryManager", new Object[] {new JsResourceOperationsHandler(), new JsServiceInvocator(), new JsExternalInvocator()}); + ((Scriptable) scope).put("_nodeRegistryManager", scope, nodeRegistryManager); + + // add NodeRegistryManagerListener in nodeRegistryManager + fct = (Function) nodeRegistryManager.getPrototype().get("addListener", nodeRegistryManager.getPrototype()); + fct.call(cx, scope, nodeRegistryManager, new Object[] {new NodeRegistryManagerListener()}); + + // create nodeRegistry + NativeObject nodeRegistry = (NativeObject) cx.evaluateString(scope, "_nodeRegistryManager.createNodeRegistry();", null, 1, null); + + // add NodeChangedListener in nodeRegistry + fct = (Function) nodeRegistry.getPrototype().get("addNodeChangeListener", nodeRegistry.getPrototype()); + fct.call(cx, scope, nodeRegistry, new Object[] {new NodeChangedListener()}); + + // subscribe + fct = (Function) nodeRegistryManager.getPrototype().get("subscribe", nodeRegistryManager.getPrototype()); + fct.call(cx, scope, nodeRegistryManager, new Object[] {"fpm:user1/repo-1|tt.mm", nodeRegistry, + new IFunctionInvoker() { + @Override + public void call(Object instance, Object... params) { + System.out.println("subscribeOKCallback -> " + params); + } + }, + new IFunctionInvoker() { + @Override + public void call(Object instance, Object... params) { + System.out.println("subscribeFailedCallback -> " + params[0].toString()); + } + }}); - ((Invocable) engine).invokeMethod(nodeRegistry, "addListener", new NodeChangedListener()); - - Node node = new Node("myNodeUri", "myType"); - Assert.assertEquals(((Invocable) engine).invokeMethod(nodeRegistry, "registerNode", node), "Node " + "[" + node.getType() + ", " + node.getNodeUri() + "] registered!"); + // get root node + fct = (Function) nodeRegistry.getPrototype().get("getNodeById", nodeRegistry.getPrototype()); + NativeObject node = (NativeObject) fct.call(cx, scope, nodeRegistry, new Object[] {"fpm:user1/repo-1|tt.mm"}); + + // expand root node + fct = (Function) nodeRegistryManager.getPrototype().get("expand", nodeRegistryManager.getPrototype()); + fct.call(cx, scope, nodeRegistryManager, new Object[] {nodeRegistry, node, null}); - // this will trigger INodeChangedListener.nodeChanged - ((Invocable) engine).invokeMethod(nodeRegistry, "setType", node, "newType"); - - } catch (Exception e) { - throw new RuntimeException(e); + System.out.println(node.get("children")); + } finally { + Context.exit(); } }