Add write handler hive functionality

Change-Id: I50380286f5145fc2f00c2f5d5886724f453dae58
diff --git a/org.eclipse.scada.da.server.common/META-INF/MANIFEST.MF b/org.eclipse.scada.da.server.common/META-INF/MANIFEST.MF
index 29a088d..190b8dc 100644
--- a/org.eclipse.scada.da.server.common/META-INF/MANIFEST.MF
+++ b/org.eclipse.scada.da.server.common/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Common DA Server Components (Incubation)
 Bundle-SymbolicName: org.eclipse.scada.da.server.common
-Bundle-Version: 0.3.0.qualifier
+Bundle-Version: 0.4.0.qualifier
 Bundle-Vendor: Eclipse NeoSCADA Project
 Export-Package: org.eclipse.scada.da.server.browser.common;version="0.1.0";uses:="org.eclipse.scada.da.core.browser,org.eclipse.scada.da.server.common,org.eclipse.scada.da.core",
  org.eclipse.scada.da.server.browser.common.query;version="0.1.0";uses:="org.eclipse.scada.da.server.common,org.eclipse.scada.da.server.browser.common",
@@ -26,7 +26,7 @@
    org.eclipse.scada.utils.lang",
  org.eclipse.scada.da.server.common.factory;version="0.1.0",
  org.eclipse.scada.da.server.common.hive;version="0.1.0";uses:="org.eclipse.scada.utils.concurrent,org.eclipse.scada.core.server,org.eclipse.scada.core",
- org.eclipse.scada.da.server.common.impl;version="0.2.0";
+ org.eclipse.scada.da.server.common.impl;version="0.4.0";
   uses:="org.eclipse.scada.da.server.common.factory,
    org.eclipse.scada.core.server.common.session,
    org.eclipse.scada.da.server.common.impl.stats,
diff --git a/org.eclipse.scada.da.server.common/pom.xml b/org.eclipse.scada.da.server.common/pom.xml
index b3079f7..0716756 100644
--- a/org.eclipse.scada.da.server.common/pom.xml
+++ b/org.eclipse.scada.da.server.common/pom.xml
@@ -9,6 +9,6 @@
 	</parent>
 	<groupId>org.eclipse.scada.core</groupId>
 	<artifactId>org.eclipse.scada.da.server.common</artifactId>
-	<version>0.3.0-SNAPSHOT</version>
+	<version>0.4.0-SNAPSHOT</version>
 	<packaging>eclipse-plugin</packaging>
 </project>
\ No newline at end of file
diff --git a/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/HiveCommon.java b/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/HiveCommon.java
index e58f7f4..9a03f54 100644
--- a/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/HiveCommon.java
+++ b/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/HiveCommon.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2014 TH4 SYSTEMS GmbH and others.
+ * Copyright (c) 2010, 2016 TH4 SYSTEMS GmbH and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
  *     Jens Reimann - additional work
  *     IBH SYSTEMS GmbH - clean up subscription manager, change shutdown handling
  *     IBH SYSTEMS GmbH - add context information, use exported executors
+ *     Red Hat Inc - add write handler functionality
  *******************************************************************************/
 package org.eclipse.scada.da.server.common.impl;
 
@@ -90,13 +91,13 @@
  * }
  * </code>
  */
-public abstract class HiveCommon extends ServiceCommon<Session, SessionCommon>implements Hive
+public abstract class HiveCommon extends ServiceCommon<Session, SessionCommon> implements Hive
 {
     private final static Logger logger = LoggerFactory.getLogger ( HiveCommon.class );
 
-    private final Set<SessionCommon> sessions = new HashSet<SessionCommon> ();
+    private final Set<SessionCommon> sessions = new HashSet<> ();
 
-    private final Map<String, DataItem> itemMap = new HashMap<String, DataItem> ( 1000 );
+    private final Map<String, DataItem> itemMap = new HashMap<> ( 1000 );
 
     private Lock itemMapReadLock;
 
@@ -106,15 +107,15 @@
 
     private Folder rootFolder;
 
-    private final Set<SessionListener> sessionListeners = new CopyOnWriteArraySet<SessionListener> ();
+    private final Set<SessionListener> sessionListeners = new CopyOnWriteArraySet<> ();
 
     private volatile ExecutorService operationService;
 
-    private final List<DataItemFactory> factoryList = new CopyOnWriteArrayList<DataItemFactory> ();
+    private final List<DataItemFactory> factoryList = new CopyOnWriteArrayList<> ();
 
     private ListenableSubscriptionManager<String> itemSubscriptionManager;
 
-    private final Set<DataItemValidator> itemValidators = new CopyOnWriteArraySet<DataItemValidator> ();
+    private final Set<DataItemValidator> itemValidators = new CopyOnWriteArraySet<> ();
 
     private ValidationStrategy validationStrategy = ValidationStrategy.GRANT_ALL;
 
@@ -185,7 +186,7 @@
         }
 
         this.operationService = ExportedExecutorService.newSingleThreadExportedExecutor ( "HiveCommon/" + getHiveId () );
-        this.itemSubscriptionManager = new ListenableSubscriptionManager<String> ( this.operationService, this.subscriptionValidator );
+        this.itemSubscriptionManager = new ListenableSubscriptionManager<> ( this.operationService, this.subscriptionValidator );
 
         if ( this.autoEnableStats && this.rootFolder instanceof FolderCommon )
         {
@@ -418,7 +419,7 @@
 
         final NotifyFuture<UserInformation> loginFuture = loginUser ( properties, contextInformation, callbackHandler );
 
-        return new CallingFuture<UserInformation, Session> ( loginFuture) {
+        return new CallingFuture<UserInformation, Session> ( loginFuture ) {
 
             @Override
             public Session call ( final Future<UserInformation> future ) throws Exception
@@ -434,7 +435,7 @@
 
         logger.debug ( "Create Session - user: {}", user );
 
-        final Map<String, String> sessionProperties = new HashMap<String, String> ();
+        final Map<String, String> sessionProperties = new HashMap<> ();
 
         fillSessionProperties ( user, sessionProperties );
 
@@ -744,7 +745,7 @@
     {
         final SessionCommon sessionCommon = validateSession ( session );
 
-        return new AuthorizedOperation<WriteAttributeResults, AbstractSessionImpl> ( this.authorizationProvider, sessionCommon, DATA_ITEM_OBJECT_TYPE, itemId, "WRITE_ATTRIBUTES", makeSetAttributesContext ( attributes ), operationParameters, sessionCommon.wrapCallbackHandler ( callbackHandler ), DEFAULT_RESULT) {
+        return new AuthorizedOperation<WriteAttributeResults, AbstractSessionImpl> ( this.authorizationProvider, sessionCommon, DATA_ITEM_OBJECT_TYPE, itemId, "WRITE_ATTRIBUTES", makeSetAttributesContext ( attributes ), operationParameters, sessionCommon.wrapCallbackHandler ( callbackHandler ), DEFAULT_RESULT ) {
 
             @Override
             protected NotifyFuture<WriteAttributeResults> granted ( final org.eclipse.scada.core.server.OperationParameters effectiveOperationParameters )
@@ -762,7 +763,7 @@
 
         if ( item == null )
         {
-            return new InstantErrorFuture<WriteAttributeResults> ( new InvalidItemException ( itemId ).fillInStackTrace () );
+            return new InstantErrorFuture<> ( new InvalidItemException ( itemId ).fillInStackTrace () );
         }
 
         // stats
@@ -780,20 +781,20 @@
         }
         catch ( final InvalidSessionException e )
         {
-            return new InstantErrorFuture<WriteAttributeResults> ( e );
+            return new InstantErrorFuture<> ( e );
         }
     }
 
     private Map<String, Object> makeSetAttributesContext ( final Map<String, Variant> attributes )
     {
-        final Map<String, Object> context = new HashMap<String, Object> ( 1 );
+        final Map<String, Object> context = new HashMap<> ( 1 );
         context.put ( "attributes", attributes );
         return context;
     }
 
     private Map<String, Object> makeWriteValueContext ( final Variant value )
     {
-        final Map<String, Object> context = new HashMap<String, Object> ( 1 );
+        final Map<String, Object> context = new HashMap<> ( 1 );
         context.put ( "value", value );
         return context;
     }
@@ -803,7 +804,7 @@
     {
         final SessionCommon sessionCommon = validateSession ( session );
 
-        return new AuthorizedOperation<WriteResult, AbstractSessionImpl> ( this.authorizationProvider, sessionCommon, DATA_ITEM_OBJECT_TYPE, itemId, "WRITE", makeWriteValueContext ( value ), operationParameters, sessionCommon.wrapCallbackHandler ( callbackHandler ), DEFAULT_RESULT) {
+        return new AuthorizedOperation<WriteResult, AbstractSessionImpl> ( this.authorizationProvider, sessionCommon, DATA_ITEM_OBJECT_TYPE, itemId, "WRITE", makeWriteValueContext ( value ), operationParameters, sessionCommon.wrapCallbackHandler ( callbackHandler ), DEFAULT_RESULT ) {
 
             @Override
             protected NotifyFuture<WriteResult> granted ( final org.eclipse.scada.core.server.OperationParameters effectiveOperationParameters )
@@ -817,11 +818,11 @@
     {
         logger.debug ( "Processing write - granted - itemId: {}, value: {}", itemId, value );
 
-        final DataItem item = retrieveItem ( itemId );
+        final WriteHandler writeHandler = getWriteHandler ( session, itemId );
 
-        if ( item == null )
+        if ( writeHandler == null )
         {
-            return new InstantErrorFuture<WriteResult> ( new InvalidItemException ( itemId ).fillInStackTrace () );
+            return new InstantErrorFuture<> ( new InvalidItemException ( itemId ) );
         }
 
         // stats
@@ -831,7 +832,7 @@
         }
 
         // go
-        final NotifyFuture<WriteResult> future = item.startWriteValue ( value, effectiveOperationParameters );
+        final NotifyFuture<WriteResult> future = writeHandler.startWriteValue ( value, effectiveOperationParameters );
         try
         {
             session.addFuture ( future );
@@ -839,10 +840,26 @@
         }
         catch ( final InvalidSessionException e )
         {
-            return new InstantErrorFuture<WriteResult> ( e );
+            return new InstantErrorFuture<> ( e );
         }
     }
 
+    protected WriteHandler getWriteHandler ( final SessionCommon session, final String itemId )
+    {
+        final DataItem item = retrieveItem ( itemId );
+        if ( item != null )
+        {
+            return new WriteHandler () {
+                @Override
+                public NotifyFuture<WriteResult> startWriteValue ( final Variant value, final org.eclipse.scada.core.server.OperationParameters effectiveOperationParameters )
+                {
+                    return item.startWriteValue ( value, effectiveOperationParameters );
+                }
+            };
+        }
+        return null;
+    }
+
     @Override
     public HiveBrowser getBrowser ()
     {
@@ -867,10 +884,10 @@
             {
                 return this.browser;
             }
-            this.browser = new HiveBrowserCommon ( this) {
+            this.browser = new HiveBrowserCommon ( this ) {
 
                 @Override
-                public Folder getRootFolder ( )
+                public Folder getRootFolder ()
                 {
                     return HiveCommon.this.rootFolder;
                 }
diff --git a/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/WriteHandler.java b/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/WriteHandler.java
new file mode 100644
index 0000000..92758c7
--- /dev/null
+++ b/org.eclipse.scada.da.server.common/src/org/eclipse/scada/da/server/common/impl/WriteHandler.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 IBH SYSTEMS GmbH and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBH SYSTEMS GmbH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.scada.da.server.common.impl;
+
+import org.eclipse.scada.core.Variant;
+import org.eclipse.scada.da.core.WriteResult;
+import org.eclipse.scada.utils.concurrent.NotifyFuture;
+
+public interface WriteHandler
+{
+    public NotifyFuture<WriteResult> startWriteValue ( Variant value, org.eclipse.scada.core.server.OperationParameters effectiveOperationParameters );
+}