Merge "Update build scripts"
authorPatrick Lankswert <patrick.lankswert@intel.com>
Thu, 11 Dec 2014 14:20:55 +0000 (06:20 -0800)
committerGerrit Code Review <gerrit@oicreview.vlan14.01.org>
Thu, 11 Dec 2014 14:20:55 +0000 (06:20 -0800)
151 files changed:
.gitignore
resource/csdk/makefile
resource/csdk/occoap/src/occoap.c
resource/csdk/ocmalloc/include/ocmalloc.h
resource/csdk/ocmalloc/src/ocmalloc.c
resource/csdk/ocmalloc/test/linux/makefile
resource/csdk/ocmalloc/test/linux/unittest.cpp
resource/csdk/ocsocket/include/ocsocket.h
resource/csdk/ocsocket/src/ocsocket.c
resource/csdk/ocsocket/test/sendrecv.cpp
resource/csdk/stack/include/internal/occlientcb.h
resource/csdk/stack/include/internal/occollection.h
resource/csdk/stack/include/internal/ocresource.h
resource/csdk/stack/include/internal/ocresourcehandler.h [new file with mode: 0644]
resource/csdk/stack/include/internal/ocstackinternal.h
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlient.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/occlientslow.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserver.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp
resource/csdk/stack/src/occlientcb.c
resource/csdk/stack/src/occollection.c
resource/csdk/stack/src/ocobserve.c
resource/csdk/stack/src/ocresource.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/examples/fridgeclient.cpp
resource/examples/garageclient.cpp
resource/examples/garageserver.cpp
resource/examples/makefile
resource/examples/ocicuc/Makefile
resource/examples/presenceclient.cpp
resource/examples/presenceserver.cpp
resource/examples/roomclient.cpp
resource/examples/roomserver.cpp
resource/examples/simpleclient.cpp
resource/examples/simpleclientHQ.cpp
resource/examples/simpleclientserver.cpp
resource/examples/simpleserver.cpp
resource/examples/simpleserverHQ.cpp
resource/examples/threadingsample.cpp
resource/include/AttributeValue.h
resource/include/OCApi.h
resource/include/OCRepresentation.h
resource/include/OCSerialization.h
resource/include/OicJsonSerializer.hpp
resource/oc_logger/examples/test_logging.cpp
resource/src/InProcClientWrapper.cpp
resource/src/InProcServerWrapper.cpp
resource/src/OCRepresentation.cpp
resource/unittests/makefile
service/protocol-plugin/build/linux/Makefile
service/protocol-plugin/lib/rapidxml/rapidxml.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp [new file with mode: 0644]
service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/build/linux/Makefile
service/protocol-plugin/plugin-manager/src/Config.cpp [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/Config.h [new file with mode: 0644]
service/protocol-plugin/plugin-manager/src/CpluffAdapter.cpp
service/protocol-plugin/plugin-manager/src/CpluffAdapter.h
service/protocol-plugin/plugin-manager/src/FelixAdapter.cpp
service/protocol-plugin/plugin-manager/src/FelixAdapter.h
service/protocol-plugin/plugin-manager/src/Plugin.cpp
service/protocol-plugin/plugin-manager/src/Plugin.h
service/protocol-plugin/plugin-manager/src/PluginManager.cpp
service/protocol-plugin/plugin-manager/src/PluginManager.h
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.cpp
service/protocol-plugin/plugin-manager/src/PluginManagerImpl.h
service/protocol-plugin/plugins/mqtt-fan/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/Makefile
service/protocol-plugin/plugins/mqtt-fan/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-fan/src/fanserver.cpp
service/protocol-plugin/plugins/mqtt-light/build/linux/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/Makefile
service/protocol-plugin/plugins/mqtt-light/lib/python/Makefile
service/protocol-plugin/plugins/mqtt-light/src/lightserver.cpp
service/protocol-plugin/readme
service/protocol-plugin/sample-app/linux/mqtt/Makefile [moved from service/protocol-plugin/sample-app/linux/fan-control/Makefile with 69% similarity]
service/protocol-plugin/sample-app/linux/mqtt/mqttclient.cpp [moved from service/protocol-plugin/sample-app/linux/fan-control/fanclient.cpp with 83% similarity]
service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml [new file with mode: 0644]
service/soft-sensor-manager/SDK/build/linux/Makefile
service/soft-sensor-manager/SDK/include/SSMClient.h
service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp [new file with mode: 0644]
service/soft-sensor-manager/SDK/src/SSMClient.cpp
service/soft-sensor-manager/SSMCore/build/linux/Makefile
service/soft-sensor-manager/SSMCore/include/SSMInterface.h [new file with mode: 0644]
service/soft-sensor-manager/SSMCore/src/Common/InternalInterface.h
service/soft-sensor-manager/SSMCore/src/Common/ThreadManager.cpp
service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.cpp
service/soft-sensor-manager/SSMCore/src/QueryProcessor/PropagationEngine.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMCore_JNI.h
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SSMResourceServer.h [moved from service/soft-sensor-manager/SSMCore/include/SSMResourceServer.h with 85% similarity]
service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.cpp
service/soft-sensor-manager/SSMCore/src/SSMInterface/SoftSensorManager.h
service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextExecutor.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ContextRepository.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h [deleted file]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.cpp
service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceFinder.h
service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.cpp [moved from service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResponseReactor.cpp with 81% similarity]
service/soft-sensor-manager/SSMCore/src/SensorProcessor/SensingEngine.h [moved from service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResponseReactor.h with 84% similarity]
service/soft-sensor-manager/SampleApp/linux/Makefile
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/build/Makefile [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/build/Makefile with 62% similarity]
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/include/SSMTestApp.h [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/include/SSMTestApp.h with 88% similarity]
service/soft-sensor-manager/SampleApp/linux/SSMTesterApp/src/SSMTestApp.cpp [moved from service/soft-sensor-manager/SampleApp/linux/ClientApp/src/SSMTestApp.cpp with 79% similarity]
service/soft-sensor-manager/SampleApp/linux/THSensorApp/build/Makefile
service/soft-sensor-manager/SampleApp/linux/THSensorApp/include/ThingResourceServer.h
service/soft-sensor-manager/SampleApp/linux/THSensorApp/src/ThingResourceServer.cpp
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/build/Makefile
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/include/ThingResourceServer1.h
service/soft-sensor-manager/SampleApp/linux/THSensorApp1/src/ThingResourceServer1.cpp
service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h [deleted file]
service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service [deleted file]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/README [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/README with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/RELEASE.txt [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/RELEASE.txt with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/makefile_org [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/makefile_org with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/CMakeLists.txt [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/CMakeLists.txt with 87% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml [new file with mode: 0644]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-log.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-log.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.cpp [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-test.cpp with 76% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-test.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-test.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.c [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-utils.c with 96% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/src/oicapp-utils.h [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/oicapp-utils.h with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.manifest [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.manifest with 100% similarity]
service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/packaging/ssm.spec [moved from service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.spec with 65% similarity]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml [new file with mode: 0644]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml [deleted file]
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/Makefile
service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/src/DiscomfortIndexSensor.cpp
service/soft-sensor-manager/build/linux/Makefile
service/soft-sensor-manager/build/linux/environment.mk

index c8d1cf5..a5463f0 100644 (file)
@@ -1,16 +1,30 @@
 # Ignore output dirs
 /release
-/csdk/release
-/csdk/libcoap-4.1.1/release/
-/examples/release
+resource/release
+resource/csdk/release
+resource/csdk/libcoap-4.1.1/release/
+resource/examples/release
+resource/examples/debug
 
 /debug
-csdk/debug/
-csdk/libcoap-4.1.1/debug/
-/examples/debug
-csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/debug
+resource/csdk/debug/
+resource/csdk/libcoap-4.1.1/debug/
+resource/csdk/libcoap-4.1.1/linux/
+resource/csdk/linux
+resource/csdk/stack/samples/linux/SimpleClientServer/debug/
+resource/csdk/stack/samples/linux/SimpleClientServer/release/
 
+resource/csdk/connectivity/build/out/
 
+resource/oc_logger/bin/
+resource/oc_logger/lib/
+resource/oc_logger/samples/linux/release/
+resource/oc_logger/samples/linux/debug
+
+service/things-manager/build/linux/release
+service/things-manager/build/linux/debug
+service/things-manager/sdk/build/linux/
 # Ignore any object files
 *.o
 *.obj
@@ -22,4 +36,11 @@ csdk/stack/samples/linux/SimpleClientServer/debug/
 *.project
 
 # Ignore dependencies folder, which should be generated
-/dependencies
+dependencies/
+
+#ignore Klocwork stuff
+.kwlp/
+.kwps/
+
+#ignore various swap files
+*.swp
index d3cf077..238a65d 100644 (file)
@@ -145,10 +145,10 @@ all:      make_lcoap objdirs obj_build liboctbstack.a
 
 buildScript_all: objdirs obj_build liboctbstack.a
 
-make_lcoap: 
+make_lcoap:
        $(MAKE) -C $(LCOAP_DIR) "BUILD=$(BUILD)" "PLATFORM=$(PLATFORM)" "ARDUINOWIFI=$(ARDUINOWIFI)"
 
-objdirs: 
+objdirs:
        mkdir -p $(PLATFORM)
        mkdir -p $(PLATFORM)/$(ARDUINO_SHIELD_TYPE)
        mkdir -p $(OUT_DIR)
@@ -160,12 +160,12 @@ obj_build:
        $(foreach source,$(SOURCES), $(CC) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/%, $(notdir $(source))));)
 
 liboctbstack.a: obj_build
-       @echo "Building $@" 
+       @echo "Building $@"
        # Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location
        @cd $(OBJ_DIR) && $(AR) -x $(PLATFORM_SPECIFIC_BACKOUT)$(LCOAP_DIR)/$(PLATFORM)$(ARDUINO_SHIELD_TYPE)/$(BUILD)/libcoap.a
        # Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.).
        $(AR) -r $(OUT_DIR)/$@ $(OBJ_DIR)/*.o
-    
+
     ifeq ($(PLATFORM),linux)
      ifneq ($(wildcard $(TINYDTLS_DIR)/libtinydtls.a),)
                        $(info "Building liboctbstack with DTLS support")
index 87d28fe..cc9c95a 100644 (file)
@@ -126,8 +126,7 @@ static void HandleCoAPRequests(struct coap_context_t *ctx,
 {
     // silence warnings
     (void) ctx;
-    OCServerProtocolRequest protocolRequest;
-    memset(&protocolRequest, 0, sizeof(OCServerProtocolRequest));
+    OCServerProtocolRequest protocolRequest = {(OCMethod)0};
     coap_block_t rcvdBlock1;
     coap_block_t rcvdBlock2;
     memset(&rcvdBlock1, COAP_BLOCK_FILL_VALUE, sizeof(coap_block_t));
@@ -292,8 +291,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         const coap_queue_t * rcvdResponse) {
     OCResponse * response = NULL;
     OCCoAPToken rcvdToken;
-    OCClientResponse clientResponse;
-    memset(&clientResponse, 0, sizeof(OCClientResponse));
+    OCClientResponse clientResponse = {0};
     ClientCB * cbNode = NULL;
     unsigned char bufRes[MAX_RESPONSE_LENGTH] = {0};
     uint32_t sequenceNumber = OC_OBSERVE_NO_OPTION;
@@ -343,28 +341,30 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     if(!strcmp((char *)rcvdUri, (char *)OC_PRESENCE_URI)){
         isPresenceNotification = 1;
         OC_LOG(INFO, TAG, PCF("Received a presence notification"));
-        tok = strtok((char *)bufRes, "[:]");
-        tok = strtok(NULL, "[:]");
+        tok = strtok((char *)bufRes, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
+        bufRes[strlen((char *)bufRes)] = ':';
         VERIFY_NON_NULL(tok);
         sequenceNumber = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received NONCE is %u", sequenceNumber);
-        tok = strtok(NULL, "[:]");
+        tok = strtok(NULL, "[:]}");
         VERIFY_NON_NULL(tok);
         maxAge = (uint32_t )atol(tok);
         OC_LOG_V(DEBUG, TAG, "The received TTL is %u", maxAge);
-        tok = strtok(NULL, "[:]");
-        bufRes[strlen((char *)bufRes)] = ':';
+        tok = strtok(NULL, "[:]}");
         if(tok) {
+            bufRes[strlen((char *)bufRes)] = ':';
             resourceTypeName = (char *)OCMalloc(strlen(tok));
             if(!resourceTypeName)
             {
                 goto exit;
             }
             strcpy(resourceTypeName, tok);
-            bufRes[strlen((char *)bufRes)] = ':';
             OC_LOG_V(DEBUG, TAG, "----------------resourceTypeName %s",
                     resourceTypeName);
         }
+        bufRes[strlen((char *)bufRes)] = ']';
     }
     #endif
 
@@ -381,7 +381,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
     cbNode = GetClientCB(&rcvdToken, NULL, NULL);
 
     #ifdef WITH_PRESENCE
-    // Check if the application subcribed for presence
+    // Check if the application subscribed for presence
     if(!cbNode)
     {
         // get the address of the remote
@@ -400,6 +400,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         sprintf((char *)fullUri, "%s%s", OC_MULTICAST_IP, rcvdUri);
         cbNode = GetClientCB(NULL, NULL, fullUri);
         isMulticastPresence = 1;
+        isPresenceNotification = 0;
     }
     #endif
 
@@ -511,12 +512,11 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     cbNode->sequenceNumber = clientResponse.sequenceNumber;;
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
@@ -531,7 +531,18 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     remotePortNu);
                 mcNode = GetMCPresenceNode(senderUri);
 
-                if(mcNode != NULL)
+                if(maxAge == 0)
+                {
+                    OC_LOG(INFO, TAG, PCF("===============Stopping presence"));
+                    response->clientResponse->result = OC_STACK_PRESENCE_STOPPED;
+                    if(cbNode->presence)
+                    {
+                        OCFree(cbNode->presence->timeOut);
+                        OCFree(cbNode->presence);
+                        cbNode->presence = NULL;
+                    }
+                }
+                else if(mcNode != NULL)
                 {
                     if(mcNode->nonce == clientResponse.sequenceNumber)
                     {
@@ -564,16 +575,14 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
                     }
                 }
 
+                // Ensure that a filter is actually applied.
                 if(resourceTypeName && response->cbNode->filterResourceType)
                 {
-                    if(strcmp(resourceTypeName,
-                            (const char *)response->cbNode->filterResourceType)!=0)
+                    if(!findResourceType(response->cbNode->filterResourceType, resourceTypeName))
                     {
-                        //Ignore presence callback if resource type does not match filter.
                         goto exit;
                     }
                 }
-
             }
             #endif
         }
@@ -609,6 +618,7 @@ static void HandleCoAPResponses(struct coap_context_t *ctx,
         VERIFY_SUCCESS(result, OC_STACK_OK);
     }
     exit:
+        OCFree(resourceTypeName);
         OCFree(response);
 }
 
index 66291d0..7019982 100644 (file)
@@ -58,9 +58,6 @@ extern "C" {
  * Allocates a block of size bytes, returning a pointer to the beginning of
  * the allocated block.
  *
- * NOTE: This function is intended to be used internally by the TB Stack.
- *       It is not intended to be used by applications.
- *
  * @param size - Size of the memory block in bytes, where size > 0
  *
  * @return
@@ -70,10 +67,20 @@ extern "C" {
 void *OCMalloc(size_t size);
 
 /**
- * Deallocate a block of memory previously allocated by a call to OCMalloc
+ * Allocates a block of memory for an array of num elements, each of them
+ * size bytes long and initializes all its bits to zero.
+ *
+ * @param num - The number of elements
+ * @param size - Size of the element type in bytes, where size > 0
  *
- * NOTE: This function is intended to be used internally by the TB Stack.
- *       It is not intended to be used by applications.
+ * @return
+ *     on success, a pointer to the allocated memory block
+ *     on failure, a null pointer is returned
+ */
+void *OCCalloc(size_t num, size_t size);
+
+/**
+ * Deallocate a block of memory previously allocated by a call to OCMalloc
  *
  * @param ptr - Pointer to block of memory previously allocated by OCMalloc.
  *              If ptr is a null pointer, the function does nothing.
index e9e109a..fe62c15 100644 (file)
 
 void *OCMalloc(size_t size)
 {
-#ifdef ENABLE_MALLOC_DEBUG
-    void *ptr = 0;
-
     if (0 == size)
     {
         return NULL;
     }
 
+#ifdef ENABLE_MALLOC_DEBUG
+    void *ptr = 0;
+
     ptr = malloc(size);
     OC_LOG_V(INFO, TAG, "malloc: ptr=%p, size=%u", ptr, size);
     return ptr;
 #else
-    if (0 == size)
+    return malloc(size);
+#endif
+}
+
+void *OCCalloc(size_t num, size_t size)
+{
+    if(0 == size || 0 == num)
     {
         return NULL;
     }
-    return malloc(size);
+
+#ifdef ENABLE_MALLOC_DEBUG
+    void *ptr = 0;
+
+    ptr = calloc(num, size);
+    OC_LOG_V(INFO, TAG, "calloc: ptr=%p, num=%u, size=%u", ptr, num, size);
+    return ptr;
+#else
+    return calloc(num, size);
 #endif
 }
 
index 7a39d6c..31dd9a0 100644 (file)
@@ -71,12 +71,13 @@ INC_DIRS    += -I$(OCTBSTACK_INC)/internal
 INC_DIRS  += -I$(GTEST_DIR)/include
 
 CC_FLAGS.debug      := -g -O0 -g3 -Wall -ffunction-sections -fdata-sections -fno-exceptions \
-                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) -DTB_LOG
+                        -std=c++0x -pedantic $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD) -DTB_LOG
 CC_FLAGS.release    := -Os -Wall -fdata-sections -Wl,--gc-sections -Wl,-s -fno-exceptions \
-                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/$(BUILD) 
-                                       
-LDLIBS         += -loctbstack -lgtest -lgtest_main -lpthread
-CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) -L$(GTEST_DIR)/lib/.libs
+                        -std=c++0x $(INC_DIRS) -L$(ROOT_DIR)/linux/$(BUILD)
+
+LDLIBS         += -loctbstack -lpthread
+CPPFLAGS       += $(CC_FLAGS.$(BUILD)) $(LDLIBS) $(GTEST_DIR)/lib/.libs/libgtest.a \
+                          $(GTEST_DIR)/lib/.libs/libgtest_main.a
 
 SOURCES := unittest.cpp
 
@@ -84,7 +85,7 @@ OBJECTS:= $(patsubst %.c, $(OBJ_DIR)/%.o, $(SOURCES))
 
 PROGRAMS := unittest
 
-all:   prep_dirs $(OBJECTS) $(PROGRAMS) 
+all:   prep_dirs $(OBJECTS) $(PROGRAMS)
 
 prep_dirs:
        -mkdir -p $(OUT_DIR)
@@ -93,7 +94,7 @@ prep_dirs:
 $(OBJ_DIR)/%.o: %.cpp
        $(CC) -c $(CPPFLAGS) $< -o $@
 
-unittest: $(OBJ_DIR)/unittest.o 
+unittest: $(OBJ_DIR)/unittest.o
        $(CC) $^ $(CPPFLAGS) -o $(OUT_DIR)/$(BUILD)/$@
 
 .PHONY: clean
index c485b26..acd9573 100644 (file)
@@ -82,3 +82,59 @@ TEST(OCMalloc, MallocFail2)
     EXPECT_TRUE(NULL == pBuffer);
     OCFree(pBuffer);
 }
+
+TEST(OCCalloc, CallocPass1)
+{
+    // Try to allocate a small buffer
+    pBuffer = (uint8_t *)OCCalloc(1, 1);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass2)
+{
+    // Try to allocate a small buffer
+    pBuffer = (uint8_t *)OCCalloc(1, 128);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocPass3)
+{
+    // Try to allocate a buffer for an array
+    pBuffer = (uint8_t *)OCCalloc(5, 128);
+    EXPECT_TRUE(pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail1)
+{
+    // Try to allocate a buffer of size 0
+    pBuffer = (uint8_t *)OCCalloc(1, 0);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail2)
+{
+    // Try to allocate a buffer with num of 0
+    pBuffer = (uint8_t *)OCCalloc(0, 5);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail3)
+{
+    // Try to allocate a buffer with size and num 0
+    pBuffer = (uint8_t *)OCCalloc(0, 0);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
+
+TEST(OCCalloc, CallocFail4)
+{
+    // Try to allocate a ridiculous amount of RAM
+    pBuffer = (uint8_t *)OCCalloc(1, (size_t)0x7FFFFFFFFFFFFFFF);
+    EXPECT_TRUE(NULL == pBuffer);
+    OCFree(pBuffer);
+}
index ec6c0b7..9bad9ed 100644 (file)
@@ -242,6 +242,25 @@ int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addr
              uint8_t *addrv4,  uint32_t addrLen);
 
 
+//-- OCDevAddrToString ----------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to convert the OCDevAddr to string format
+ *
+ * @param[in]   addr
+ *               OCDevAddr address.
+ * @param[out]  stringAddress the target string where the address
+ *               is to be stored. Memory for this parameter is
+ *               allocated by the caller.
+ *
+ * Note: The length of stringAddress may not exceed DEV_ADDR_SIZE_MAX
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToString(OCDevAddr *addr, char *stringAddress);
+
+
 //-- OCDevAddrToIPv4Addr -------------------------------------------------
 /** @ingroup ocsocket
  *
index 205eba1..a857546 100644 (file)
@@ -245,11 +245,10 @@ int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
     }
 
     // bind to multicast port
-    struct sockaddr_in sa;
+    struct sockaddr_in sa = {0};
     struct sockaddr_in *sin;
 
     sin = (struct sockaddr_in *)(ipmcastaddr->addr);
-    memset(&sa, 0, sizeof(sa));
     sa.sin_family = AF_INET;
     sa.sin_addr.s_addr = sin->sin_addr.s_addr;
     sa.sin_port = sin->sin_port;
@@ -260,8 +259,7 @@ int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
     }
 
     // add membership to receiving socket
-    struct ip_mreq mreq;
-    memset(&mreq, 0, sizeof(struct ip_mreq));
+    struct ip_mreq mreq = {0};
     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
     mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
     if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
@@ -354,6 +352,30 @@ int32_t OCClose(int32_t sockfd)
     return (close(sockfd));
 }
 
+//convert OCDevAddr to String
+int32_t OCDevAddrToString(OCDevAddr* addr, char* stringAddress)
+{
+    uint8_t a;
+    uint8_t b;
+    uint8_t c;
+    uint8_t d;
+
+    if(OCDevAddrToIPv4Addr(addr, &a, &b, &c, &d) == 0)
+    {
+        if (!stringAddress)
+        {
+            return ERR_INVALID_INPUT;
+        }
+
+        sprintf(stringAddress, "%u.%u.%u.%u",
+                a, b, c, d);
+        return ERR_SUCCESS;
+    }
+    else
+    {
+        return ERR_INVALID_INPUT;
+    }
+}
 
 /// Retrieve the IPv4 address embedded inside OCDev address data structure
 int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
index 52ea37e..e657d6b 100644 (file)
@@ -70,7 +70,7 @@ int multicast_test(int argc, char* argv[])
     int32_t sfd;
     char loopch=0;
     int set_option_on = 1;
-    struct sockaddr_in mcastsock, peer;
+    struct sockaddr_in mcastsock = {0}, peer;
     uint8_t recvbuf[MAX_BUF];
     uint32_t len, bufLen, fromlen;
 
@@ -90,7 +90,6 @@ int multicast_test(int argc, char* argv[])
     }
 
     //Initialize the group sockaddr structure with a
-    memset((char *) &mcastsock, 0, sizeof(mcastsock));
     mcastsock.sin_family = AF_INET;
     mcastsock.sin_addr.s_addr = inet_addr(argv[2]);
     mcastsock.sin_port = htons(atoi(argv[3]));
@@ -118,8 +117,7 @@ int multicast_test(int argc, char* argv[])
         return -1;
     }
 
-    struct ip_mreq mreq;
-    memset(&mreq, 0, sizeof(struct ip_mreq));
+    struct ip_mreq mreq = {0};
     mreq.imr_interface.s_addr = htonl(INADDR_ANY);
     mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr;
     if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
index 0f3a49f..67c58a9 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <ocstack.h>
 #include <occoaptoken.h>
+#include <ocresource.h>
 
 typedef struct OCPresence {
     // This is the TTL associated with presence
@@ -61,7 +62,7 @@ typedef struct ClientCB {
     // Struct to hold TTL info for presence
     #ifdef WITH_PRESENCE
     OCPresence * presence;
-    unsigned char * filterResourceType;
+    OCResourceType * filterResourceType;
     #endif
     // next node in this list
     struct ClientCB    *next;
@@ -85,7 +86,7 @@ extern struct ClientCB *cbList;
  * @param[in] requestUri
  *              the resource uri of the request.
  * @param[in] resourceType
- *              the resourceType associated with this request.
+ *              the resourceType associated with a presence request.
  *
  * @brief If the handle you're looking for does not exist, the stack will reply with a RST message.
  *
@@ -93,7 +94,7 @@ extern struct ClientCB *cbList;
  */
 //------------------------------------------------------------------------
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
         unsigned char * requestUri, unsigned char * resourceType);
 
 //-- DeleteClientCB -----------------------------------------------------------
@@ -127,6 +128,20 @@ void DeleteClientCB(ClientCB *cbNode);
 //------------------------------------------------------------------------
 ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * requestUri);
 
+
+/**
+ * Inserts a new resource type filter into this clientCB node.
+ *
+ * @param cbNode - the node to add the new resourceType filter to
+ * @param resourceTypeName - the value to create the new resourceType filter from
+ *
+ * @return
+ *      OC_STACK_OK on success
+ *      OC_STACK_ERROR with invalid parameters
+ *      OC_STACK_NO_MEMORY when out of memory
+ */
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName);
+
 //-- DeleteClientCBList --------------------------------------------------
 /** @ingroup ocstack
  *
index 512ec93..e421d06 100644 (file)
@@ -22,7 +22,7 @@
 #define OC_COLLECTION_H
 
 #include "ocstack.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 
 uint8_t GetNumOfResourcesInCollection (OCResource *resource);
 
index 62d5363..542cfb6 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_RESOURCE_H
-#define OC_RESOURCE_H
-
-#include "ocstack.h"
-#include "ocstackinternal.h"
-#include "ocserverrequest.h"
-
-#define OC_RSRVD_OC                     "oc"
-#define OC_RSRVD_PAYLOAD                "payload"
-#define OC_RSRVD_HREF                   "href"
-#define OC_RSRVD_RESOURCE_TYPE          "rt"
-#define OC_RSRVD_INTERFACE              "if"
-#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
-#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
-#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
-#define OC_RSRVD_OBSERVABLE             "obs"
-#define OC_RSRVD_SECURE                 "sec"
-#define OC_RSRVD_HOSTING_PORT           "port"
-
-#define OC_JSON_PREFIX                     "{\"oc\":["
-#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
-#define OC_JSON_SUFFIX                     "]}"
-#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
-#define OC_JSON_SEPARATOR                  ','
-
-#define OC_RESOURCE_OBSERVABLE   1
-#define OC_RESOURCE_SECURE       1
+#ifndef OCRESOURCE_H_
+#define OCRESOURCE_H_
 
-typedef enum {
-    STACK_RES_DISCOVERY_NOFILTER = 0,
-    STACK_RES_DISCOVERY_IF_FILTER,
-    STACK_RES_DISCOVERY_RT_FILTER
-} StackQueryTypes;
+#define OC_OBSERVER_NOT_INTERESTED       (0)
+#define OC_OBSERVER_STILL_INTERESTED     (1)
+#define OC_OBSERVER_FAILED_COMM          (2)
+
+//-----------------------------------------------------------------------------
+// Virtual Resource Presence Attributes
+//-----------------------------------------------------------------------------
+#ifdef WITH_PRESENCE
+typedef struct PRESENCERESOURCE{
+    OCResourceHandle handle;
+    uint32_t presenceTTL;
+} PresenceResource;
+#endif
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
 
+// IF here stands for Interface
 typedef enum {
-    OC_RESOURCE_VIRTUAL = 0,
-    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
-    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
-    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
-    OC_RESOURCE_NOT_SPECIFIED
-} ResourceHandling;
+    STACK_IF_DEFAULT = 0,
+    STACK_IF_LL,
+    STACK_IF_BATCH,
+    STACK_IF_INVALID
+} OCStackIfTypes;
+
+typedef struct resourcetype_t {
+    struct resourcetype_t *next; // linked list; for multiple types on resource
+
+    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the type; type and sub-types can be separate with
+    // ‘-‘ (dash) usually only two segments would be defined. Either way this string is meant to be
+    // human friendly and is used opaquely and not parsed by code. This name is used in the “rt=”
+    // parameter of a resource description when resources are introspected and is also use in the
+    // <base URI>/types list of available types.
+    char *resourcetypename;
+} OCResourceType;
+
+typedef struct attr_t {
+    struct attr_t *next; // Points to next resource in list
+
+    // The name of the attribute; used to look up the attribute in list;
+    // for a given attribute SHOULD not be changed once assigned
+    const char *attrName;
+    char *attrValue; // value of the attribute as string
+} OCAttribute;
 
-OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * request);
+typedef struct resourceinterface_t {
+    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
 
-const char * GetVirtualResourceUri( OCVirtualResources resource);
-OCResource *FindResourceByUri(const char* resourceUri);
-uint8_t IsVirtualResource(const char* resourceUri);
+    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is a
+    // namespace and the final segment is the interface; usually only two segments would be
+    // defined. Either way this string is opaque and not parsed by segment
+    char *name ;
 
-OCStackResult DetermineResourceHandling (OCServerRequest *request,
-                                         ResourceHandling *handling,
-                                         OCResource **resource);
+    // Supported content types to serialize request and response on this interface
+    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+    char *inputContentType ;
+    char *outputContentType ;
+#endif
+    /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
 
-OCStackResult
-ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+typedef struct rsrc_t {
+    struct rsrc_t *next; // Points to next resource in list
+    // Relative path on the device; will be combined with base url to create fully qualified path
+    char *host;
+    char *uri;
+    OCResourceType *rsrcType; // Resource type(s); linked list
+    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+    // Array of pointers to resources; can be used to represent a container of resources
+    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+    //struct rsrc_t *rsrcResources;
+    // Pointer to function that handles the entity bound to the resource.
+    // This handler has to be explicitly defined by the programmer
+    OCEntityHandler entityHandler;
+    // Properties on the resource – defines meta information on the resource
+    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+    // Pointer to an opaque object where app/user specific data can be placed with the resource;
+    // this could be information for the entity handler between invocations
+    void *context;
+    // NOTE: Methods supported by this resource should be based on the interface targeted
+    // i.e. look into the interface structure based on the query request Can be removed here;
+    // place holder for the note above
+    /* method_t methods; */
+    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
+    uint32_t sequenceNum;
+} OCResource;
 
-OCStackResult
-BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
-                        char *filterValue, char * out, uint16_t *remaining);
 
-OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
 
-#endif //OC_RESOURCE_H
+#endif /* OCRESOURCE_H_ */
diff --git a/resource/csdk/stack/include/internal/ocresourcehandler.h b/resource/csdk/stack/include/internal/ocresourcehandler.h
new file mode 100644 (file)
index 0000000..e5a24bc
--- /dev/null
@@ -0,0 +1,86 @@
+//******************************************************************
+//
+// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_RESOURCEHANDLER_H
+#define OC_RESOURCEHANDLER_H
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+
+#define OC_RSRVD_OC                     "oc"
+#define OC_RSRVD_PAYLOAD                "payload"
+#define OC_RSRVD_HREF                   "href"
+#define OC_RSRVD_RESOURCE_TYPE          "rt"
+#define OC_RSRVD_RESOURCE_TYPE_PRESENCE "core.presence"
+#define OC_RSRVD_INTERFACE              "if"
+#define OC_RSRVD_INTERFACE_DEFAULT      "oc.mi.def"
+#define OC_RSRVD_INTERFACE_LL           "oc.mi.ll"
+#define OC_RSRVD_INTERFACE_BATCH        "oc.mi.b"
+#define OC_RSRVD_OBSERVABLE             "obs"
+#define OC_RSRVD_SECURE                 "sec"
+#define OC_RSRVD_HOSTING_PORT           "port"
+
+#define OC_JSON_PREFIX                     "{\"oc\":["
+#define OC_JSON_PREFIX_LEN                 (sizeof(OC_JSON_PREFIX) - 1)
+#define OC_JSON_SUFFIX                     "]}"
+#define OC_JSON_SUFFIX_LEN                 (sizeof(OC_JSON_SUFFIX) - 1)
+#define OC_JSON_SEPARATOR                  ','
+
+#define OC_RESOURCE_OBSERVABLE   1
+#define OC_RESOURCE_SECURE       1
+
+typedef enum {
+    STACK_RES_DISCOVERY_NOFILTER = 0,
+    STACK_RES_DISCOVERY_IF_FILTER,
+    STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+typedef enum {
+    OC_RESOURCE_VIRTUAL = 0,
+    OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_NOT_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER,
+    OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER,
+    OC_RESOURCE_DEFAULT_DEVICE_ENTITYHANDLER,
+    OC_RESOURCE_NOT_SPECIFIED
+} ResourceHandling;
+
+OCEntityHandlerResult defaultResourceEHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest * request);
+
+const char * GetVirtualResourceUri( OCVirtualResources resource);
+OCResource *FindResourceByUri(const char* resourceUri);
+uint8_t IsVirtualResource(const char* resourceUri);
+
+OCStackResult DetermineResourceHandling (OCServerRequest *request,
+                                         ResourceHandling *handling,
+                                         OCResource **resource);
+
+OCStackResult
+ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerRequest *request);
+
+OCStackResult
+BuildVirtualResourceResponse(OCResource *resourcePtr, uint8_t filterOn,
+                        char *filterValue, char * out, uint16_t *remaining);
+
+OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult);
+
+#endif //OC_RESOURCEHANDLER_H
index 713b123..2a4d8f6 100644 (file)
@@ -51,102 +51,6 @@ extern OCDeviceEntityHandler defaultDeviceHandler;
 #define OC_COAP_SCHEME "coap://"
 #define OC_OFFSET_SEQUENCE_NUMBER (4) // the first outgoing sequence number will be 5
 
-#define OC_OBSERVER_NOT_INTERESTED       (0)
-#define OC_OBSERVER_STILL_INTERESTED     (1)
-#define OC_OBSERVER_FAILED_COMM          (2)
-
-//-----------------------------------------------------------------------------
-// Virtual Resource Presence Attributes
-//-----------------------------------------------------------------------------
-#ifdef WITH_PRESENCE
-typedef struct PRESENCERESOURCE{
-    OCResourceHandle handle;
-    uint32_t presenceTTL;
-} PresenceResource;
-#endif
-
-//-----------------------------------------------------------------------------
-// Forward declarations
-//-----------------------------------------------------------------------------
-struct rsrc_t;
-
-//-----------------------------------------------------------------------------
-// Typedefs
-//-----------------------------------------------------------------------------
-
-// IF here stands for Interface
-typedef enum {
-    STACK_IF_DEFAULT = 0,
-    STACK_IF_LL,
-    STACK_IF_BATCH,
-    STACK_IF_INVALID
-} OCStackIfTypes;
-
-typedef struct resourcetype_t {
-    struct resourcetype_t *next; // linked list; for multiple types on resource
-
-    // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
-    // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
-    // usually only two segments would be defined. Either way this string is meant to be human friendly
-    // and is used opaquely and not parsed by code
-    // This name is used in the “rt=” parameter of a resource description when resources are introspected
-    // and is also use in the <base URI>/types list of available types
-    char *resourcetypename;
-} OCResourceType;
-
-typedef struct attr_t {
-    struct attr_t *next; // Points to next resource in list
-
-    // The name of the attribute; used to look up the attribute in list;
-    // for a given attribute SHOULD not be changed once assigned
-    const char *attrName;
-    char *attrValue; // value of the attribute as string
-} OCAttribute;
-
-typedef struct resourceinterface_t {
-    struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
-
-    // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
-    // a namespace and the final segment is the interface; usually only two segments would be defined.
-    // Either way this string is opaque and not parsed by segment
-    char *name ;
-
-    // Supported content types to serialize request and response on this interface
-    // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
-#if 0
-    char *inputContentType ;
-    char *outputContentType ;
-#endif
-    /*** Future placeholder for access control and policy ***/
-} OCResourceInterface;
-
-typedef struct rsrc_t {
-    struct rsrc_t *next; // Points to next resource in list
-    // Relative path on the device; will be combined with base url to create fully qualified path
-    char *host;
-    char *uri;
-    OCResourceType *rsrcType; // Resource type(s); linked list
-    OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
-    OCAttribute *rsrcAttributes; // Resource interface(s); linked list
-    // Array of pointers to resources; can be used to represent a container of resources
-    // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
-    struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
-    //struct rsrc_t *rsrcResources;
-    // Pointer to function that handles the entity bound to the resource.
-    // This handler has to be explicitly defined by the programmer
-    OCEntityHandler entityHandler;
-    // Properties on the resource – defines meta information on the resource
-    OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
-    // Pointer to an opaque object where app/user specific data can be placed with the resource;
-    // this could be information for the entity handler between invocations
-    void *context;
-    // NOTE: Methods supported by this resource should be based on the interface targeted
-    // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
-    /* method_t methods; */
-    // Sequence number for observable resources. Per the CoAP standard it is a 24 bit value.
-    uint32_t sequenceNum;
-} OCResource;
-
 typedef struct {
     // Observe option field
     uint32_t option;
@@ -160,6 +64,8 @@ typedef struct {
 
 // following structure will be created in occoap and passed up the stack on the server side
 typedef struct {
+    // Observe option field
+    uint32_t observationOption;
     // the REST method retrieved from received request PDU
     OCMethod method;
     // resourceUrl will be filled in occoap using the path options in received request PDU
@@ -170,8 +76,6 @@ typedef struct {
     unsigned char reqJSONPayload[MAX_REQUEST_LENGTH];
     // qos is indicating if the request is CON or NON
     OCQualityOfService qos;
-    // Observe option field
-    uint32_t observationOption;
     // An array of the received vendor specific header options
     uint8_t numRcvdVendorSpecificHeaderOptions;
     OCHeaderOption rcvdVendorSpecificHeaderOptions[MAX_HEADER_OPTIONS];
@@ -196,10 +100,10 @@ typedef struct {
 
 typedef struct
 {
-    // qos is indicating if the request is CON or NON
-    OCQualityOfService qos;
     // Observe option field
     uint32_t observationOption;
+    // qos is indicating if the request is CON or NON
+    OCQualityOfService qos;
     // Allow the entity handler to pass a result with the response
     OCStackResult result;
     // IP address & port of client registered for observe
@@ -250,6 +154,7 @@ OCStackResult BindResourceInterfaceToResource(OCResource* resource,
 
 OCStackResult BindResourceTypeToResource(OCResource* resource,
                                             const char *resourceTypeName);
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName);
 
 #ifdef WITH_PRESENCE
 //TODO: should the following function be public?
index 343a874..085f497 100644 (file)
@@ -263,10 +263,10 @@ typedef struct {
  * Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
  */
 typedef struct {
-    // the is the result of our stack, OCStackResult should contain coap/other error codes;
-    OCStackResult result;
     // Address of remote server
     OCDevAddr * addr;
+    // the is the result of our stack, OCStackResult should contain coap/other error codes;
+    OCStackResult result;
     // If associated with observe, this will represent the sequence of notifications from server.
     uint32_t sequenceNumber;
     // resJSONPayload is retrieved from the payload of the received request PDU
@@ -395,9 +395,11 @@ OCStackResult OCStop();
 OCStackResult OCProcess();
 
 /**
- * Discover or Perform requests on a specified resource (specified by that Resource's respective URI).
+ * Discover or Perform requests on a specified resource (specified by that Resource's respective
+ * URI).
  *
- * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of calling this API.
+ * @param handle             - @ref OCDoHandle to refer to the request sent out on behalf of
+ *                             calling this API.
  * @param method             - @ref OCMethod to perform on the resource
  * @param requiredUri        - URI of the resource to interact with
  * @param referenceUri       - URI of the reference resource
@@ -409,6 +411,10 @@ OCStackResult OCProcess();
  *                             header options to be sent with the request
  * @param numOptions         - Number of header options to be included
  *
+ * Note: Presence subscription amendments (ie. adding additional resource type filters by calling
+ * this API again) require the use of the same base URI as the original request to successfully
+ * amend the presence filters.
+ *
  * @return
  *     OC_STACK_OK               - no errors
  *     OC_STACK_INVALID_CALLBACK - invalid callback function pointer
index 52cd7d6..e5cd93f 100644 (file)
@@ -45,18 +45,20 @@ const char *getResult(OCStackResult result);
 
 PROGMEM const char TAG[] = "ArduinoServer";
 
-int gLEDUnderObservation = 0;
-void createLEDResource();
-typedef struct LEDRESOURCE{
+int gLightUnderObservation = 0;
+void createLightResource();
+
+/* Structure to represent a Light resource */
+typedef struct LIGHTRESOURCE{
     OCResourceHandle handle;
     bool state;
     int power;
-} LEDResource;
+} LightResource;
 
-static LEDResource LED;
+static LightResource Light;
 
-static char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
-static char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
+static char responsePayloadGet[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+static char responsePayloadPut[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"off\",\"power\":0}}";
 
 /// This is the port which Arduino Server will use for all unicast communication with it's peers
 static uint16_t OC_WELL_KNOWN_PORT = 5683;
@@ -134,7 +136,7 @@ int ConnectToNetwork()
 // http://www.atmel.com/webdoc/AVRLibcReferenceManual/malloc_1malloc_intro.html
 void PrintArduinoMemoryStats()
 {
-#ifdef ARDUINO_AVR_MEGA2560
+    #ifdef ARDUINO_AVR_MEGA2560
     //This var is declared in avr-libc/stdlib/malloc.c
     //It keeps the largest address not allocated for heap
     extern char *__brkval;
@@ -142,8 +144,8 @@ void PrintArduinoMemoryStats()
     int tmp;
     OC_LOG_V(INFO, TAG, "Stack: %u         Heap: %u", (unsigned int)&tmp, (unsigned int)__brkval);
     OC_LOG_V(INFO, TAG, "Unallocated Memory between heap and stack: %u",
-             ((unsigned int)&tmp - (unsigned int)__brkval));
-#endif
+            ((unsigned int)&tmp - (unsigned int)__brkval));
+    #endif
 }
 
 // This is the entity handler for the registered resource.
@@ -182,7 +184,7 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
             {
                 ehRet = OC_EH_ERROR;
             }
-         }
+        }
 
         if (ehRet == OC_EH_OK)
         {
@@ -211,7 +213,7 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
         if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
         {
             OC_LOG (INFO, TAG, PCF("Received OC_OBSERVE_REGISTER from client"));
-            gLEDUnderObservation = 1;
+            gLightUnderObservation = 1;
         }
         else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
         {
@@ -222,40 +224,35 @@ OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag, OCEntityHandle
     return ehRet;
 }
 
-
 // This method is used to display 'Observe' functionality of OC Stack.
 static uint8_t modCounter = 0;
-void *ChangeLEDRepresentation (void *param)
+void *ChangeLightRepresentation (void *param)
 {
     (void)param;
     OCStackResult result = OC_STACK_ERROR;
     modCounter += 1;
     if(modCounter % 10 == 0)  // Matching the timing that the Linux Sample Server App uses for the same functionality.
     {
-        LED.power += 5;
-        if (gLEDUnderObservation)
+        Light.power += 5;
+        if (gLightUnderObservation)
         {
-            OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power);
-            result = OCNotifyAllObservers (LED.handle, OC_NA_QOS);
+            OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
+            result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
             if (OC_STACK_NO_OBSERVERS == result)
             {
-                gLEDUnderObservation = 0;
+                gLightUnderObservation = 0;
             }
         }
     }
     return NULL;
 }
 
-
-
 //The setup function is called once at startup of the sketch
 void setup()
 {
     // Add your initialization code here
-
     // Note : This will initialize Serial port on Arduino at 115200 bauds
     OC_LOG_INIT();
-
     OC_LOG(DEBUG, TAG, PCF("OCServer is starting..."));
     uint16_t port = OC_WELL_KNOWN_PORT;
 
@@ -273,9 +270,8 @@ void setup()
         return;
     }
 
-    // Declare and create the example resource: LED
-    createLEDResource();
-
+    // Declare and create the example resource: Light
+    createLightResource();
 }
 
 // The loop function is called in an endless loop
@@ -294,19 +290,19 @@ void loop()
         OC_LOG(ERROR, TAG, PCF("OCStack process error"));
         return;
     }
-    ChangeLEDRepresentation(NULL);
+    ChangeLightRepresentation(NULL);
 }
 
-void createLEDResource()
+void createLightResource()
 {
-    LED.state = false;
-    OCStackResult res = OCCreateResource(&LED.handle,
-            "core.led",
+    Light.state = false;
+    OCStackResult res = OCCreateResource(&Light.handle,
+            "core.light",
             "oc.mi.def",
-            "/a/led",
+            "/a/light",
             OCEntityHandlerCb,
             OC_DISCOVERABLE|OC_OBSERVABLE);
-    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+    OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
 }
 
 const char *getResult(OCStackResult result) {
index 095647c..9f70f52 100644 (file)
@@ -162,18 +162,22 @@ OCStackApplicationResult deleteReqCB(void *ctx, OCDoHandle handle, OCClientRespo
     return OC_STACK_DELETE_TRANSACTION;
 }
 
-OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
+OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
+{
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
 
-    if(clientResponse)
-    {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
-    }
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response", clientResponse->resJSONPayload);
+
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
     {
index 7ae7d29..a526935 100644 (file)
@@ -115,18 +115,21 @@ OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientRespons
 
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
 
-    if(clientResponse)
-    {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
-                clientResponse->resJSONPayload);
-    }
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+            clientResponse->resJSONPayload);
+
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
     {
index 523057b..e8db15a 100644 (file)
@@ -120,7 +120,11 @@ void PrintUsage()
 }
 
 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
-    if(clientResponse) {}
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
     if(ctx == (void*)DEFAULT_CONTEXT_VALUE) {
         OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
         OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
index 5fc9108..689b015 100644 (file)
@@ -83,18 +83,21 @@ OCStackResult InvokeOCDoResource(std::ostringstream &query,
 
 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse)
 {
+    if(clientResponse == NULL)
+    {
+        OC_LOG(INFO, TAG, "The clientResponse is NULL");
+        return   OC_STACK_DELETE_TRANSACTION;
+    }
     if(ctx == (void*)DEFAULT_CONTEXT_VALUE)
     {
         OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
     }
 
-    if(clientResponse)
-    {
-        OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
-        OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
-        OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
-                clientResponse->resJSONPayload);
-    }
+    OC_LOG_V(INFO, TAG, "StackResult: %s",  getResult(clientResponse->result));
+    OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+    OC_LOG_V(INFO, TAG, "JSON = %s =============> Get Response",
+            clientResponse->resJSONPayload);
+
     if(clientResponse->rcvdVendorSpecificHeaderOptions &&
             clientResponse->numRcvdVendorSpecificHeaderOptions)
     {
index 061bb81..1bed2bf 100644 (file)
@@ -30,6 +30,9 @@
 #include "cJSON.h"
 #include "ocserver.h"
 
+//string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
+// 9 + 9 + 1 = 19
+const int URI_MAXSIZE = 19;
 
 static int gObserveNotifyType = 3;
 
@@ -168,8 +171,9 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCE
         if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
         {
             // Create new Light instance
-            char newLightUri[15] = "/a/light/";
-            sprintf (newLightUri + strlen(newLightUri), "%d", gCurrLightInstance);
+            char newLightUri[URI_MAXSIZE];
+            snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
+
             json = cJSON_CreateObject();
             cJSON_AddStringToObject(json,"href",gResourceUri);
             cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
@@ -234,6 +238,11 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCE
 
 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
 {
+    if(ehRequest == NULL)
+    {
+        OC_LOG(INFO, TAG, "The ehRequest is NULL");
+        return OC_EH_ERROR;
+    }
     OCEntityHandlerResult ehResult = OC_EH_OK;
 
     OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
@@ -599,7 +608,7 @@ void *ChangeLightRepresentation (void *param)
     uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
     OCObservationId obsNotify[numNotifies];
 
-    while (1)
+    while (!gQuitFlag)
     {
         sleep(10);
         Light.power += 5;
index e7f092b..bcd741c 100644 (file)
 #include "cJSON.h"
 #include "ocserverbasicops.h"
 
+//string length of "/a/led/" + std::numeric_limits<int>::digits10 + '\0'"
+// 7 + 9 + 1 = 17
+const int URI_MAXSIZE = 17;
+
 volatile sig_atomic_t gQuitFlag = 0;
 
 static LEDResource LED;
@@ -148,8 +152,8 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, cha
         if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
         {
             // Create new LED instance
-            char newLedUri[15] = "/a/led/";
-            sprintf (newLedUri + strlen(newLedUri), "%d", gCurrLedInstance);
+            char newLedUri[URI_MAXSIZE ];
+            snprintf(newLedUri, URI_MAXSIZE, "/a/led/%d", gCurrLedInstance);
 
             json = cJSON_CreateObject();
 
index 364d7a1..75124bb 100644 (file)
@@ -421,13 +421,14 @@ void *ChangeLightRepresentation (void *param)
     (void)param;
     OCStackResult result = OC_STACK_ERROR;
 
-    while (1)
+    while (!gQuitFlag)
     {
         sleep(10);
         light.power += 5;
         if (gLightUnderObservation)
         {
-     OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", light.power);
+            OC_LOG_V(INFO, TAG,
+                " =====> Notifying stack of new power level %d\n", light.power);
             result = OCNotifyAllObservers (light.handle, OC_NA_QOS);
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -570,5 +571,3 @@ void createResources()
     res = OCBindResource(room, fan);
     OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res));
 }
-
-
index e5e98e3..9e0b232 100644 (file)
@@ -33,29 +33,65 @@ struct ClientCB *cbList = NULL;
 OCMulticastNode * mcPresenceNodes = NULL;
 
 OCStackResult AddClientCB(ClientCB** clientCB, OCCallbackData* cbData,
-        OCCoAPToken * token, OCDoHandle handle, OCMethod method,
-        unsigned char * requestUri, unsigned char * resourceType) {
-    ClientCB *cbNode;
-    cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
-    if (cbNode) {
-        cbNode->callBack = cbData->cb;
-        cbNode->context = cbData->context;
-        cbNode->deleteCallback = cbData->cd;
-        memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
-        cbNode->handle = handle;
-        cbNode->method = method;
-        cbNode->sequenceNumber = 0;
-        #ifdef WITH_PRESENCE
-        cbNode->presence = NULL;
-        cbNode->filterResourceType = resourceType;
-        #endif
-        cbNode->requestUri = requestUri;
-        LL_APPEND(cbList, cbNode);
+        OCCoAPToken * token, OCDoHandle *handle, OCMethod method,
+        unsigned char * requestUri, unsigned char * resourceTypeName) {
+
+    ClientCB *cbNode = NULL;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE)
+    {   // Retrieve the presence callback structure for this specific requestUri.
+        cbNode = GetClientCB(NULL, NULL, requestUri);
+    }
+    #endif // WITH_PRESENCE
+
+    if(!cbNode)// If it does not already exist, create new node.
+    {
+        cbNode = (ClientCB*) OCMalloc(sizeof(ClientCB));
+        if(!cbNode)
+        {
+            *clientCB = NULL;
+            goto exit;
+        }
+        else
+        {
+            cbNode->callBack = cbData->cb;
+            cbNode->context = cbData->context;
+            cbNode->deleteCallback = cbData->cd;
+            memcpy(&(cbNode->token), token, sizeof(OCCoAPToken));
+            cbNode->handle = *handle;
+            cbNode->method = method;
+            cbNode->sequenceNumber = 0;
+            #ifdef WITH_PRESENCE
+            cbNode->presence = NULL;
+            cbNode->filterResourceType = NULL;
+            #endif // WITH_PRESENCE
+            cbNode->requestUri = requestUri;
+            LL_APPEND(cbList, cbNode);
+            *clientCB = cbNode;
+        }
+    }
+    else
+    {
+        // Ensure that the handle the SDK hands back up to the application layer for the
+        // OCDoResource call matches the found ClientCB Node.
         *clientCB = cbNode;
-        return OC_STACK_OK;
+        OCFree(requestUri);
+        OCFree(*handle);
+        *handle = cbNode->handle;
     }
-    *clientCB = NULL;
-    return OC_STACK_NO_MEMORY;
+
+    #ifdef WITH_PRESENCE
+    if(method == OC_REST_PRESENCE && resourceTypeName)
+    {   // Amend the found or created node by adding a new resourceType to it.
+        return InsertResourceTypeFilter(cbNode, (const char *)resourceTypeName);
+    }
+    #endif
+
+    return OC_STACK_OK;
+
+    exit:
+        return OC_STACK_NO_MEMORY;
 }
 
 void DeleteClientCB(ClientCB * cbNode) {
@@ -74,9 +110,20 @@ void DeleteClientCB(ClientCB * cbNode) {
         if(cbNode->presence) {
             OCFree(cbNode->presence->timeOut);
             OCFree(cbNode->presence);
-            OCFree(cbNode->filterResourceType);
         }
-        #endif
+        if(cbNode->method == OC_REST_PRESENCE)
+        {
+            OCResourceType * pointer = cbNode->filterResourceType;
+            OCResourceType * next = NULL;
+            while(pointer)
+            {
+                next = pointer->next;
+                OCFree(pointer->resourcetypename);
+                OCFree(pointer);
+                pointer = next;
+            }
+        }
+        #endif // WITH_PRESENCE
         OCFree(cbNode);
         cbNode = NULL;
     }
@@ -113,6 +160,26 @@ ClientCB* GetClientCB(OCCoAPToken * token, OCDoHandle handle, unsigned char * re
     return NULL;
 }
 
+OCStackResult InsertResourceTypeFilter(ClientCB * cbNode, const char * resourceTypeName)
+{
+    OCResourceType * newResourceType = NULL;
+    if(cbNode && resourceTypeName)
+    {
+        // Form a new resourceType member.
+        newResourceType = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+        if(!newResourceType)
+        {
+            return OC_STACK_NO_MEMORY;
+        }
+
+        newResourceType->next = NULL;
+        newResourceType->resourcetypename = (char *) resourceTypeName;
+
+        LL_APPEND(cbNode->filterResourceType, newResourceType);
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
 
 void DeleteClientCBList() {
     ClientCB* out;
index a5a4000..2efba22 100644 (file)
@@ -22,7 +22,7 @@
 #include <string.h>
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "logger.h"
 #include "debug.h"
 #include "cJSON.h"
@@ -266,8 +266,7 @@ HandleLinkedListInterface(OCEntityHandlerRequest *ehRequest,
     jsonbufferLength = strlen((const char *)jsonbuffer);
     if(ret == OC_STACK_OK && jsonbufferLength)
     {
-        OCEntityHandlerResponse response;
-        memset(&response, 0, sizeof(OCEntityHandlerResponse));
+        OCEntityHandlerResponse response = {0};
         response.ehResult = OC_EH_OK;
         response.payload = jsonbuffer;
         response.payloadSize = jsonbufferLength + 1;
@@ -300,8 +299,7 @@ HandleBatchInterface(OCEntityHandlerRequest *ehRequest)
     jsonbufferLength = strlen((const char *)jsonbuffer);
     if(jsonbufferLength)
     {
-        OCEntityHandlerResponse response;
-        memset(&response, 0, sizeof(OCEntityHandlerResponse));
+        OCEntityHandlerResponse response = {0};
         response.ehResult = OC_EH_OK;
         response.payload = jsonbuffer;
         response.payloadSize = jsonbufferLength + 1;
index eb624ce..e8e58d4 100644 (file)
@@ -23,7 +23,7 @@
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
 #include "ocobserve.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occoap.h"
 #include "utlist.h"
 #include "debug.h"
@@ -134,7 +134,7 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
             {
                 OCEntityHandlerResponse ehResponse = {0};
                 unsigned char presenceResBuf[MAX_RESPONSE_LENGTH] = {0};
-                //we know it is the default entity handler
+                //This is effectively the implementation for the presence entity handler.
                 OC_LOG(DEBUG, TAG, PCF("This notification is for Presence"));
                 result = AddServerRequest(&request, 0, 0, 0, 1, OC_REST_GET,
                         0, OC_OBSERVE_NO_OPTION, OC_LOW_QOS,
@@ -143,7 +143,7 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                 if(result == OC_STACK_OK)
                 {
                     // we create the payload here
-                    if(resourceType)
+                    if(resourceType && resourceType->resourcetypename)
                     {
                         sprintf((char *)presenceResBuf, "%u:%u:%s",
                                 resPtr->sequenceNum, maxAge, resourceType->resourcetypename);
@@ -152,7 +152,6 @@ OCStackResult SendAllObserverNotification (OCMethod method, OCResource *resPtr,
                     {
                         sprintf((char *)presenceResBuf, "%u:%u", resPtr->sequenceNum, maxAge);
                     }
-                    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
                     ehResponse.ehResult = OC_EH_OK;
                     ehResponse.payload = presenceResBuf;
                     ehResponse.payloadSize = strlen((const char *)presenceResBuf) + 1;
@@ -185,8 +184,7 @@ OCStackResult SendListObserverNotification (OCResource * resource,
     uint8_t numSentNotification = 0;
     OCServerRequest * request = NULL;
     OCStackResult result = OC_STACK_ERROR;
-    OCEntityHandlerResponse ehResponse;
-    memset(&ehResponse, 0, sizeof(OCEntityHandlerResponse));
+    OCEntityHandlerResponse ehResponse = {0};
 
     OC_LOG(INFO, TAG, PCF("Entering SendListObserverNotification"));
     while(numIds)
@@ -286,10 +284,9 @@ OCStackResult AddObserver (const char         *resUri,
 {
     ResourceObserver *obsNode = NULL;
 
-    obsNode = (ResourceObserver *) OCMalloc(sizeof(ResourceObserver));
+    obsNode = (ResourceObserver *) OCCalloc(1, sizeof(ResourceObserver));
     if (obsNode)
     {
-        memset(obsNode, 0, sizeof(ResourceObserver));
         obsNode->observeId = obsId;
 
         obsNode->resUri = (unsigned char *)OCMalloc(strlen(resUri)+1);
index 3ee30cb..01abbc1 100644 (file)
@@ -22,7 +22,7 @@
 #include "ocstack.h"
 #include "ocstackconfig.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "ocobserve.h"
 #include "occollection.h"
 #include "occoap.h"
@@ -431,7 +431,7 @@ HandleVirtualResource (OCServerRequest *request, OCResource* resource)
         else
         {
             if(resource->resourceProperties & OC_ACTIVE){
-                SendPresenceNotification(resource->rsrcType);
+                SendPresenceNotification(NULL);
             }
         }
         #endif
index 44d3f6c..99dbe1f 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "ocstack.h"
 #include "ocserverrequest.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 
 // Module Name
 #define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
@@ -86,11 +86,9 @@ OCStackResult AddServerRequest (OCServerRequest ** request, uint16_t coapID,
 {
     OCServerRequest * serverRequest = NULL;
 
-    serverRequest = (OCServerRequest *) OCMalloc(sizeof(OCServerRequest) + reqTotalSize - 1);
+    serverRequest = (OCServerRequest *) OCCalloc(1, sizeof(OCServerRequest) + reqTotalSize - 1);
     VERIFY_NON_NULL(serverRequest);
 
-    memset(serverRequest, 0, sizeof(OCServerRequest) + reqTotalSize - 1);
-
     serverRequest->coapID = coapID;
     serverRequest->delayedResNeeded = delayedResNeeded;
     serverRequest->secured = secured;
@@ -149,9 +147,8 @@ OCStackResult AddServerResponse (OCServerResponse ** response, OCRequestHandle r
 {
     OCServerResponse * serverResponse = NULL;
 
-    serverResponse = (OCServerResponse *) OCMalloc(sizeof(OCServerResponse));
+    serverResponse = (OCServerResponse *) OCCalloc(1, sizeof(OCServerResponse));
     VERIFY_NON_NULL(serverResponse);
-    memset(serverResponse, 0, sizeof(OCServerResponse));
 
     serverResponse->payload = (unsigned char *) OCMalloc(MAX_RESPONSE_LENGTH);
     VERIFY_NON_NULL(serverResponse->payload);
@@ -255,8 +252,7 @@ void DeleteServerRequest(OCServerRequest * serverRequest)
 OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
 {
     OCStackResult result = OC_STACK_ERROR;
-    OCServerProtocolResponse protocolResponse;
-    memset(&protocolResponse, 0, sizeof(OCServerProtocolResponse));
+    OCServerProtocolResponse protocolResponse = {0};
 
     OC_LOG_V(INFO, TAG, "Inside HandleSingleResponse: %s", ehResponse->payload);
 
index 2738c96..eb0aef8 100644 (file)
@@ -24,7 +24,7 @@
 //-----------------------------------------------------------------------------
 #include "ocstack.h"
 #include "ocstackinternal.h"
-#include "ocresource.h"
+#include "ocresourcehandler.h"
 #include "occlientcb.h"
 #include "ocobserve.h"
 #include "ocrandom.h"
@@ -86,8 +86,7 @@ OCStackResult OCStackFeedBack(OCCoAPToken * token, uint8_t status)
 {
     OCStackResult result = OC_STACK_ERROR;
     ResourceObserver * observer = NULL;
-    OCEntityHandlerRequest ehRequest;
-    memset(&ehRequest, 0, sizeof(OCEntityHandlerRequest));
+    OCEntityHandlerRequest ehRequest = {0};
 
     switch(status)
     {
@@ -440,6 +439,12 @@ OCStackResult OCStop()
         return OC_STACK_ERROR;
     }
 
+    #ifdef WITH_PRESENCE
+    // Ensure that the TTL associated with ANY and ALL presence notifications originating from
+    // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
+    presenceResource.presenceTTL = 0;
+    #endif // WITH_PRESENCE
+
     // Free memory dynamically allocated for resources
     deleteAllResources();
 
@@ -532,7 +537,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     ClientCB *clientCB = NULL;
     unsigned char * requestUri = NULL;
     unsigned char * resourceType = NULL;
-    char * newURI = (char *)requiredUri;
+    char * newUri = (char *)requiredUri;
     (void) referenceUri;
 
     OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
@@ -580,7 +585,14 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 #ifdef WITH_PRESENCE
     if(method == OC_REST_PRESENCE)
     {
-        result = getResourceType(requiredUri, &resourceType, &newURI);
+        result = getResourceType(requiredUri, &resourceType, &newUri);
+        if(resourceType) {
+            OC_LOG_V(DEBUG, TAG, "Got Resource Type: %s", resourceType);
+        }
+        else
+        {
+            OC_LOG(DEBUG, TAG, "Got Resource Type is NULL.");
+        }
         if(result != OC_STACK_OK)
         {
             goto exit;
@@ -591,7 +603,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     requestUri = (unsigned char *) OCMalloc(uriLen + 1);
     if(requestUri)
     {
-        memcpy(requestUri, newURI, (uriLen + 1));
+        memcpy(requestUri, newUri, (uriLen + 1));
     }
     else
     {
@@ -610,7 +622,7 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     // with the request
     OCGenerateCoAPToken(&token);
 
-    if((result = AddClientCB(&clientCB, cbData, &token, *handle, method, requestUri, resourceType))
+    if((result = AddClientCB(&clientCB, cbData, &token, handle, method, requestUri, resourceType))
             != OC_STACK_OK)
     {
         result = OC_STACK_NO_MEMORY;
@@ -618,12 +630,12 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
     }
 
     // Make call to OCCoAP layer
-    result = OCDoCoAPResource(method, qos, &token, newURI, request, options, numOptions);
+    result = OCDoCoAPResource(method, qos, &token, newUri, request, options, numOptions);
 
 exit:
-    if(newURI != requiredUri)
+    if(newUri != requiredUri)
     {
-        OCFree(newURI);
+        OCFree(newUri);
     }
     if (result != OC_STACK_OK)
     {
@@ -954,11 +966,10 @@ OCStackResult OCCreateResource(OCResourceHandle *handle,
         }
     }
     // Create the pointer and insert it into the resource list
-    pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+    pointer = (OCResource *) OCCalloc(1, sizeof(OCResource));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResource));
     pointer->sequenceNum = OC_OFFSET_SEQUENCE_NUMBER;
 
     insertResource(pointer);
@@ -1205,11 +1216,10 @@ OCStackResult BindResourceTypeToResource(OCResource* resource,
     TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
 
     // Create the resourcetype and insert it into the resource list
-    pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+    pointer = (OCResourceType *) OCCalloc(1, sizeof(OCResourceType));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceType));
 
     // Set the resourceTypeName
     size = strlen(resourceTypeName) + 1;
@@ -1247,11 +1257,10 @@ OCStackResult BindResourceInterfaceToResource(OCResource* resource,
     TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
 
     // Create the resourceinterface and insert it into the resource list
-    pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+    pointer = (OCResourceInterface *) OCCalloc(1, sizeof(OCResourceInterface));
     if (!pointer) {
         goto exit;
     }
-    memset(pointer, 0, sizeof(OCResourceInterface));
 
     // Set the resourceinterface name
     size = strlen(resourceInterfaceName) + 1;
@@ -1737,10 +1746,18 @@ OCStackResult OCNotifyAllObservers(OCResourceHandle handle, OCQualityOfService q
     OCMethod method = OC_REST_NOMETHOD;
     uint32_t maxAge = 0;
 
+    OC_LOG(INFO, TAG, PCF("Entering OCNotifyAllObservers"));
+    #ifdef WITH_PRESENCE
+    if(handle == presenceResource.handle)
+    {
+        return OC_STACK_OK;
+    }
+    #endif // WITH_PRESENCE
     VERIFY_NON_NULL(handle, ERROR, OC_STACK_ERROR);
+
     // Verify that the resource exists
     resPtr = findResource ((OCResource *) handle);
-    if (NULL == resPtr || myStackMode == OC_CLIENT)
+    if (NULL == resPtr)
     {
         return OC_STACK_NO_RESOURCE;
     }
@@ -1920,7 +1937,7 @@ OCStackResult initResources() {
     presenceResource.presenceTTL = OC_DEFAULT_PRESENCE_TTL;
     //presenceResource.token = OCGenerateCoAPToken();
     result = OCCreateResource(&presenceResource.handle,
-            "core.presence",
+            OC_RSRVD_RESOURCE_TYPE_PRESENCE,
             "core.r",
             OC_PRESENCE_URI,
             NULL,
@@ -1982,9 +1999,22 @@ void deleteAllResources()
     while (pointer)
     {
         temp = pointer->next;
-        deleteResource(pointer);
+        #ifdef WITH_PRESENCE
+        if(pointer != (OCResource *) presenceResource.handle)
+        {
+            #endif // WITH_PRESENCE
+            deleteResource(pointer);
+            #ifdef WITH_PRESENCE
+        }
+        #endif // WITH_PRESENCE
         pointer = temp;
     }
+
+    #ifdef WITH_PRESENCE
+    // Ensure that the last resource to be deleted is the presence resource. This allows for all
+    // presence notification attributed to their deletion to be processed.
+    deleteResource((OCResource *) presenceResource.handle);
+    #endif // WITH_PRESENCE
 }
 
 /**
@@ -2004,15 +2034,27 @@ int deleteResource(OCResource *resource) {
         if (temp == resource) {
             // Invalidate all Resource Properties.
             resource->resourceProperties = (OCResourceProperty) 0;
-            OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
-
             #ifdef WITH_PRESENCE
+            if(resource != (OCResource *) presenceResource.handle)
+            {
+            #endif // WITH_PRESENCE
+                OCNotifyAllObservers((OCResourceHandle)resource, OC_HIGH_QOS);
+            #ifdef WITH_PRESENCE
+            }
+
             if(presenceResource.handle)
             {
                 ((OCResource *)presenceResource.handle)->sequenceNum = OCGetRandom();
-                SendPresenceNotification(resource->rsrcType);
+                if(resource != (OCResource *) presenceResource.handle)
+                {
+                    SendPresenceNotification(resource->rsrcType);
+                }
+                else
+                {
+                    SendPresenceNotification(NULL);
+                }
             }
-            #endif
+        #endif
 
             if (temp == headResource) {
                 headResource = temp->next;
@@ -2151,6 +2193,35 @@ OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index)
 }
 
 /**
+ * Finds a resource type in an OCResourceType link-list.
+ *
+ * @param resourceTypeList - the link-list to be searched through
+ * @param resourceTypeName - the key to search for
+ *
+ * @return
+ *      resourceType that matches the key (ie. resourceTypeName)
+ *      NULL - either an invalid parameter or this function was unable to find the key.
+ */
+OCResourceType *findResourceType(OCResourceType * resourceTypeList, const char * resourceTypeName)
+{
+    if(resourceTypeList && resourceTypeName)
+    {
+        OCResourceType * rtPointer = resourceTypeList;
+        while(resourceTypeName && rtPointer)
+        {
+            if(rtPointer->resourcetypename &&
+                    strcmp(resourceTypeName, (const char *)
+                    (rtPointer->resourcetypename)) == 0)
+            {
+                break;
+            }
+            rtPointer = rtPointer->next;
+        }
+        return rtPointer;
+    }
+    return NULL;
+}
+/**
  * Insert a resource interface into a resource's resource interface linked list.
  *
  * @param resource - resource where resource interface is to be inserted
@@ -2275,14 +2346,12 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
     {
         return OC_STACK_INVALID_PARAM;
     }
-    char * ptr = NULL;
     char * leftToken = NULL;
-    char * tempURI = (char *) OCMalloc(strlen(uri));
+    char * tempURI = (char *) OCMalloc(strlen(uri) + 1);
     if(!tempURI)
     {
         goto exit;
     }
-    ptr = tempURI;
     strcpy(tempURI, uri);
     leftToken = strtok((char *)tempURI, "?");
 
@@ -2301,7 +2370,7 @@ OCStackResult getResourceType(const char * uri, unsigned char** resourceType, ch
         leftToken = strtok(NULL, "?");
     }
 
-    *newURI = ptr;
+    *newURI = tempURI;
 
     return OC_STACK_OK;
 
index 60d5757..a37c581 100644 (file)
@@ -82,14 +82,37 @@ class ClientFridge
         OCResource::Ptr light = constructResourceObject(resource->host(),
                                 "/light", false, lightTypes, ifaces);
 
+        if(!light)
+        {
+            std::cout << "Error: Light Resource Object construction returned null\n";
+            return;
+        }
+
         std::vector<std::string> doorTypes = {"intel.fridge.door"};
 
         OCResource::Ptr leftdoor = constructResourceObject(resource->host(),
                                 "/door/left", false, doorTypes, ifaces);
+        if(!leftdoor)
+        {
+            std::cout << "Error: Left Door Resource Object construction returned null\n";
+            return;
+        }
+
         OCResource::Ptr rightdoor = constructResourceObject(resource->host(),
                                 "/door/right", false, doorTypes, ifaces);
+        if(!rightdoor)
+        {
+            std::cout << "Error: Right Door Resource Object construction returned null\n";
+            return;
+        }
+
         OCResource::Ptr randomdoor = constructResourceObject(resource->host(),
                                 "/door/random", false, doorTypes, ifaces);
+        if(!randomdoor)
+        {
+            std::cout << "Error: Random Door Resource Object construction returned null\n";
+            return;
+        }
 
         // Set header options with API version and token
         HeaderOptions headerOptions;
@@ -164,7 +187,7 @@ class ClientFridge
                 }
             case 1:
                 {
-                    bool isOn;
+                    bool isOn = false;
                     rep.getValue("on",isOn);
                     std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
                 }
@@ -172,7 +195,7 @@ class ClientFridge
             case 2:
             case 3:
                 {
-                    bool isOpen;
+                    bool isOpen = false;
                     std::string side;
                     rep.getValue("open", isOpen);
                     rep.getValue("side", side);
index e1b4e5c..ba8a09a 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <string>
 #include <cstdlib>
+#include <mutex>
+#include <condition_variable>
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -283,11 +285,15 @@ int main(int argc, char* argv[]) {
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.garage",
                     &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
 
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException& e)
     {
index d9e4959..e2a57d8 100644 (file)
@@ -25,6 +25,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -264,11 +266,14 @@ int main(int argc, char* argv[1])
         // Invoke createResource function of class light.
         myGarage.createResource();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -277,4 +282,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the OCPlatform
     // When OCPlatform destructor is invoked, internally we do Platform cleanup
+
+    return 0;
 }
index dcae88e..c97f2aa 100644 (file)
@@ -26,9 +26,6 @@ CXX         := g++
 #CXX     := clang
 OUT_DIR          := $(BUILD)
 
-DEPEND_DIR:= ../dependencies
-CEREAL_DIR:= $(DEPEND_DIR)/cereal
-
 CXX_FLAGS.debug     := -O0 -g3 -std=c++0x -Wall -pthread
 
 CXX_FLAGS.release   := -O3 -std=c++0x -Wall -pthread
@@ -40,7 +37,6 @@ CXX_INC         += -I../csdk/ocsocket/include
 CXX_INC          += -I../csdk/ocrandom/include
 CXX_INC          += -I../csdk/logger/include
 CXX_INC          += -I../csdk/libcoap
-CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a
 
index 9b69e61..17556f8 100644 (file)
@@ -42,7 +42,6 @@ CXX_INC=-I$(OCLIB)/include \
        -I../../csdk/ocsocket/include \
        -I../../csdk/ocrandom/include \
        -I../../csdk/logger/include \
-       -I../../dependencies/cereal/include
 
 BOOST_LIBS=-lboost_program_options
 #BOOST_LIBS=-L/usr/local/boost/lib/ -lboost_program_options    # for boost libraries at the specified path
index 6fd7df3..6bd79fe 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -55,8 +58,9 @@ void printUsage()
 }
 
 // Callback to presence
-void presenceHandler(OCStackResult result, const unsigned int nonce)
+void presenceHandler(OCStackResult result, const unsigned int nonce, const std::string& hostAddress)
 {
+    std::cout << "Received presence notification from : " << hostAddress << std::endl;
     std::cout << "In presenceHandler: ";
 
     switch(result)
@@ -120,7 +124,7 @@ void foundResource(std::shared_ptr<OCResource> resource)
             if(resourceURI == "/a/light")
             {
                 curResource = resource;
-                OCPlatform::OCPresenceHandle presenceHandle;
+                OCPlatform::OCPresenceHandle presenceHandle = nullptr;
 
                 if(TEST_CASE == TEST_UNICAST_PRESENCE_NORMAL)
                 {
@@ -186,7 +190,7 @@ int main(int argc, char* argv[]) {
     {
         std::cout << "Created Platform..."<<std::endl;
 
-        OCPlatform::OCPresenceHandle presenceHandle;
+        OCPlatform::OCPresenceHandle presenceHandle = nullptr;
 
         if(TEST_CASE == TEST_MULTICAST_PRESENCE_NORMAL)
         {
@@ -205,10 +209,15 @@ int main(int argc, char* argv[]) {
             OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
             std::cout<< "Finding Resource... " <<std::endl;
         }
-        while(true)
-        {
-            // some operations
-        }
+        //
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index ab75567..63d63da 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -196,11 +198,14 @@ int main()
 
         myLightResource.createResource3();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -209,4 +214,6 @@ int main()
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 60f0a4d..7e73597 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -232,10 +235,15 @@ int main(int argc, char* argv[]) {
         // Find all resources
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core", &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index 8494d31..25c7ee9 100644 (file)
@@ -24,6 +24,9 @@
 
 #include <functional>
 
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -542,7 +545,7 @@ void printUsage()
     std::cout << "2 : Create room resource with application collection entity handler.\n";
 }
 
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
 {
     printUsage();
 
@@ -579,11 +582,15 @@ int main(int argc, char* argv[1])
 
         myRoomResource.createResources();
 
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
+
     }
     catch(OCException e)
     {
@@ -592,4 +599,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 732cd4d..85c0dc1 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -370,10 +373,15 @@ int main(int argc, char* argv[]) {
         // Find all resources
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index f3363c5..e3a6f2c 100644 (file)
@@ -23,6 +23,9 @@
 #include <string>
 #include <cstdlib>
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
 #include "OCPlatform.h"
 #include "OCApi.h"
 
@@ -384,10 +387,15 @@ int main(int argc, char* argv[]) {
         OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.light", &foundResource,
                 OC::QualityOfService::LowQos);
         std::cout<< "Finding Resource... " <<std::endl;
-        while(true)
-        {
-            // some operations
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
 
     }catch(OCException& e)
     {
index 3aafe17..d3ee18b 100644 (file)
@@ -317,4 +317,6 @@ int main()
     {
         std::cout<< "Exception in main: "<<e.what()<<std::endl;
     }
+
+    return 0;
 }
index 780429a..86b1546 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -462,7 +464,7 @@ void PrintUsage()
 }
 
 
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
 {
     PrintUsage();
 
@@ -520,11 +522,15 @@ int main(int argc, char* argv[1])
 
         myLight.addType(std::string("core.brightlight"));
         myLight.addInterface(std::string("oc.mi.ll"));
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -533,4 +539,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the platform.
     // When OCPlatform::destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 70a5dfc..cf0d09a 100644 (file)
@@ -26,6 +26,8 @@
 #include <functional>
 
 #include <pthread.h>
+#include <mutex>
+#include <condition_variable>
 
 #include "OCPlatform.h"
 #include "OCApi.h"
@@ -414,7 +416,7 @@ void PrintUsage()
 }
 
 
-int main(int argc, char* argv[1])
+int main(int argc, char* argv[])
 {
     PrintUsage();
 
@@ -456,11 +458,15 @@ int main(int argc, char* argv[1])
 
         myLight.addType(std::string("core.brightlight"));
         myLight.addInterface(std::string("oc.mi.ll"));
-        // Perform app tasks
-        while(true)
-        {
-            // some tasks
-        }
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException e)
     {
@@ -469,4 +475,6 @@ int main(int argc, char* argv[1])
 
     // No explicit call to stop the platform.
     // When OCPlatform destructor is invoked, internally we do platform cleanup
+
+    return 0;
 }
index 71d09b3..ff556e2 100644 (file)
@@ -161,8 +161,8 @@ struct FooResource
 void putResourceInfo(const HeaderOptions& headerOptions,
         const OCRepresentation rep, const OCRepresentation rep2, const int eCode)
 {
-   bool m_isFoo;
-   int m_barCount;
+   bool m_isFoo = false;
+   int m_barCount = 0;
    std::cout << "In PutResourceInfo" << std::endl;
 
    std::cout <<"Clientside Put response to get was: "<<std::endl;
@@ -192,8 +192,8 @@ void getResourceInfo(std::shared_ptr<OCResource> resource, const HeaderOptions&
             const OCRepresentation rep,
             const int eCode)
 {
-    bool m_isFoo;
-    int m_barCount;
+    bool m_isFoo = false;
+    int m_barCount = 0;
     std::cout << "In getResourceInfo" << std::endl;
 
     std::cout<<"Clientside response to get was: "<<std::endl;
@@ -284,10 +284,14 @@ void client1()
     std::cout<<"result1:" << OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=core.foo",
             foundResource1)<< std::endl;
 
-    while(1)
-    {
-        // client1 related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 void client2()
@@ -298,10 +302,14 @@ void client2()
                 "coap://224.0.1.187/oc/core?rt=core.foo",
                 foundResource2)<< std::endl;
 
-    while(1)
-    {
-        // client2 related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 void server()
@@ -313,10 +321,14 @@ void server()
         return;
     }
 
-    while(1)
-    {
-        // server related operations
-    }
+    // A condition variable will free the mutex it is given, then do a non-
+    // intensive block until 'notify' is called on it.  In this case, since we
+    // don't ever call cv.notify, this should be a non-processor intensive version
+    // of while(true);
+    std::mutex blocker;
+    std::condition_variable cv;
+    std::unique_lock<std::mutex> lock(blocker);
+    cv.wait(lock);
 }
 
 int main()
@@ -354,10 +366,14 @@ int main()
         std::thread t2(client2);
         t2.detach();
 
-        while(1)
-        {
-            // server related operations
-        }
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cv.wait(lock);
     }
     catch(OCException& e)
     {
index 5a3264a..5d0d524 100644 (file)
@@ -33,7 +33,6 @@
 #define BOOST_MPL_LIMIT_LIST_SIZE 30
 #define BOOST_MPL_LIMIT_VECTOR_SIZE 30
 #include <boost/variant.hpp>
-#include <cereal/external/rapidjson/document.h>
 
 namespace OC
 {
index 95f27d0..97076c5 100644 (file)
@@ -199,7 +199,8 @@ namespace OC
     typedef std::function<OCEntityHandlerResult(
                             const std::shared_ptr<OCResourceRequest>)> EntityHandler;
 
-    typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
+    typedef std::function<void(OCStackResult, const unsigned int,
+                                const std::string&)> SubscribeCallback;
 
     typedef std::function<void(const HeaderOptions&,
                                 const OCRepresentation&, const int)> GetCallback;
index c27d0c3..fbfb7c5 100644 (file)
 #include <AttributeValue.h>
 #include <StringConstants.h>
 
-// note: is there any way to move this later so that the implementers don't need to
-// reference them?
-#include <cereal/cereal.hpp>
-#include <cereal/types/map.hpp>
-#include <cereal/types/vector.hpp>
-#include <OicJsonSerializer.hpp>// Customized Cereal serializer, required for a few functions
-#include <cereal/types/utility.hpp>
-
 #include <OCException.h>
+
+
+namespace cereal
+{
+    class access;
+}
+
 namespace OC
 {
 
@@ -195,89 +194,22 @@ namespace OC
                 private:
                     friend class cereal::access;
                     template <class Archive>
-                    void save(Archive& ar) const
-                    {
-                        if(m_types.size() > 0)
-                        {
-                            ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
-                        }
-
-                        if(m_interfaces.size()>0)
-                        {
-                            ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
-                        }
-                    }
+                    void save(Archive& ar) const;
 
                     template<class Archive>
-                    void load(Archive& ar)
-                    {
-                        optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
-                        optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
-                    }
+                    void load(Archive& ar);
 
                     std::vector<std::string>& m_types;
                     std::vector<std::string>& m_interfaces;
             };
             template<class Archive, class Val>
-            static void optional_load(Archive& ar, Val&& v)
-            {
-                try
-                {
-                    ar(v);
-                }
-                catch(cereal::Exception& e)
-                {
-                    ar.setNextName(nullptr);
-                    // Loading a key that doesn't exist results in an exception
-                    // Since "Not Found" is a valid condition for us, we swallow
-                    // this exception and the archive will not load anything
-                }
-            }
-            template<class Archive>
-            void save(Archive& ar) const
-            {
-                // printed for all interface types
-                if(!m_uri.empty())
-                {
-                    ar(cereal::make_nvp(Key::URIKEY, m_uri));
-                }
+            static void optional_load(Archive& ar, Val&& v);
 
-                if((m_interfaceType == InterfaceType::None
-                            || m_interfaceType==InterfaceType::DefaultChild
-                            || m_interfaceType==InterfaceType::LinkChild)
-                        && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
-                {
-                    // The Prop object requires that it refer to non-const vectors
-                    // so that it can alter them in the 'load' case.  In the save case
-                    // (initiated here) it will not modify the object.  So, to keep the
-                    // compiler happy, removing the 'const' context here is necessary.
-                    const std::vector<std::string>& rt(m_resourceTypes);
-                    const std::vector<std::string>& intf(m_interfaces);
-                    Prop temp(const_cast<std::vector<std::string>&>(rt),
-                            const_cast<std::vector<std::string>&>(intf));
-                    ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
-                }
-
-                // printed only for BatchChildren and DefaultParent
-                if((m_interfaceType == InterfaceType::None
-                            || m_interfaceType == InterfaceType::BatchChild
-                            || m_interfaceType == InterfaceType::DefaultParent)
-                        && m_values.size()>0)
-                {
-                    ar(cereal::make_nvp(Key::REPKEY, m_values));
-                }
-            }
+            template<class Archive>
+            void save(Archive& ar) const;
 
             template<class Archive>
-            void load(Archive& ar)
-            {
-                optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
-                {
-                    Prop temp(m_resourceTypes, m_interfaces);
-                    optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
-                }
-                optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
-            }
+            void load(Archive& ar);
 
         private:
             std::string m_uri;
@@ -290,66 +222,5 @@ namespace OC
     };
 } // namespace OC
 
-// code needed to serialize a string::Attribute value map
-namespace OC
-{
-    namespace detail
-    {
-        template<class Archive>
-        class WriteAttributeValue : public boost::static_visitor<>
-        {
-            public:
-                WriteAttributeValue(const std::string& name, Archive& ar)
-                    :m_name(name), m_archive(ar)
-                {}
-
-                template<class T>
-                void operator()(const T& value) const
-                {
-                    m_archive(cereal::make_nvp(m_name, value));
-                }
-            private:
-                std::string m_name;
-                Archive& m_archive;
-        };
-    }
-}
-
-namespace cereal
-{
-    // take no action when serializing the null type, because the 'save' below
-    // doesn't use the visitor for this type.
-    template <class Archive>
-    void serialize(Archive&, OC::NullType t)
-    {}
-
-    template<class Archive>
-    void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
-    {
-        for(const auto& kv : vals)
-        {
-            const auto& k = kv.first;
-            const auto& v = kv.second;
-
-            if(v.which() != OC::AttributeValueNullIndex)
-            {
-                OC::detail::WriteAttributeValue<Archive> writer(k,ar);
-                boost::apply_visitor(writer, v);
-            }
-            else
-            {
-                ar.setNextName(k.c_str());
-                ar.writeName();
-                ar.saveValue();
-            }
-        }
-    }
-
-    template<class Archive>
-    void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
-    {
-        ar.loadAttributeValues(vals);
-    }
-}
 
 #endif //__OCREPRESENTATION_H
index bbdd200..f611407 100644 (file)
@@ -57,6 +57,7 @@ namespace OC
                     {
                         // we swallow this exception, since it means the key
                         // doesn't exist, allowing these to be optional
+                        ar.setNextName(nullptr);
                     }
 
                     try
@@ -70,20 +71,26 @@ namespace OC
                         ar(cereal::make_nvp(OC::Key::PORTKEY, m_port));
                     }
                     catch(cereal::Exception&)
-                    {}
+                    {
+                        ar.setNextName(nullptr);
+                    }
 
                     try
                     {
                         ar(cereal::make_nvp(OC::Key::RESOURCETYPESKEY,m_resourceTypes));
                     }
                     catch(cereal::Exception&)
-                    {}
+                    {
+                        ar.setNextName(nullptr);
+                    }
                     try
                     {
                         ar(cereal::make_nvp(OC::Key::INTERFACESKEY, m_interfaces));
                     }
                     catch(cereal::Exception&)
-                    {}
+                    {
+                        ar.setNextName(nullptr);
+                    }
                 }
 
                 bool m_observable;
@@ -110,14 +117,18 @@ namespace OC
                     m_loaded=true;
                 }
                 catch(cereal::Exception&)
-                {}
+                {
+                    ar.setNextName(nullptr);
+                }
                 try
                 {
                     ar(cereal::make_nvp(OC::Key::PROPERTYKEY, m_props));
                     m_loaded=true;
                 }
                 catch(cereal::Exception&)
-                {}
+                {
+                    ar.setNextName(nullptr);
+                }
             }
 
 
@@ -180,10 +191,7 @@ namespace OC
         private:
             std::string ConvertOCAddrToString(OCSecureType sec, int secureport)
             {
-                uint8_t addr1;
-                uint8_t addr2;
-                uint8_t addr3;
-                uint8_t addr4;
+                char stringAddress[DEV_ADDR_SIZE_MAX];
                 uint16_t port;
 
                 ostringstream os;
@@ -202,7 +210,7 @@ namespace OC
                     throw ResourceInitException(false, false, false, false, false, true);
                 }
 
-                if(0== OCDevAddrToIPv4Addr(&m_address, &addr1, &addr2, &addr3, &addr4))
+                if(0== OCDevAddrToString(&m_address, stringAddress))
                 {
                     // nothing to do, successful case.
                 }
@@ -213,10 +221,7 @@ namespace OC
                     throw ResourceInitException(false, false, false, false, false, true);
                 }
 
-                os<<static_cast<int>(addr1)<<'.'
-                    <<static_cast<int>(addr2)<<'.'
-                    <<static_cast<int>(addr3)<<'.'
-                    <<static_cast<int>(addr4);
+                os<<stringAddress;
 
                 if(sec == OCSecureType::IPv4Secure && secureport>0 && secureport<=65535)
                 {
@@ -229,7 +234,7 @@ namespace OC
                 else
                 {
                     oclog() << "ConvertOCAddrToString() : Invalid Port"
-                            <<std::flush;
+                        <<std::flush;
                     throw ResourceInitException(false, false, false, false, true, false);
                 }
 
index ed07b9d..d7eb98e 100644 (file)
@@ -225,30 +225,6 @@ namespace cereal
       //! Saves a const char * to the current node
       void saveValue(char const * s)        { itsWriter.String(s);                                                       }
 
-    private:
-      // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
-      // special overloads to handle these cases.
-
-      //! 32 bit signed long saving to current node
-      template <class T> inline
-      typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
-      saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
-
-      //! non 32 bit signed long saving to current node
-      template <class T> inline
-      typename std::enable_if<sizeof(T) != sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
-      saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
-
-      //! 32 bit unsigned long saving to current node
-      template <class T> inline
-      typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
-      saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
-
-      //! non 32 bit unsigned long saving to current node
-      template <class T> inline
-      typename std::enable_if<sizeof(T) != sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
-      saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
-
     public:
 #ifdef _MSC_VER
       //! MSVC only long overload to current node
@@ -259,14 +235,22 @@ namespace cereal
       typename std::enable_if<std::is_same<T, long>::value &&
                               !std::is_same<T, std::int32_t>::value &&
                               !std::is_same<T, std::int64_t>::value, void>::type
-      saveValue( T t ){ saveLong( t ); }
+      saveValue( T t )
+      {
+          saveLong( t );
+          return t;
+      }
 
       //! Serialize an unsigned long if it would not be caught otherwise
       template <class T> inline
       typename std::enable_if<std::is_same<T, unsigned long>::value &&
                               !std::is_same<T, std::uint32_t>::value &&
                               !std::is_same<T, std::uint64_t>::value, void>::type
-      saveValue( T t ){ saveLong( t ); }
+      saveValue( T t )
+      {
+          saveLong( t );
+          return t;
+      }
 #endif // _MSC_VER
 
       //! Save exotic arithmetic as strings to current node
@@ -283,6 +267,7 @@ namespace cereal
         std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
         ss << t;
         saveValue( ss.str() );
+        return t;
       }
 
       //! Write the name of the upcoming node and prepare object/array state
index 0128006..61a6a58 100644 (file)
@@ -92,5 +92,6 @@ int main()
  basic_demo();
  c_demo();
  alternative_demo();
+ return 0;
 }
 
index 0072783..e7804c1 100644 (file)
@@ -161,6 +161,7 @@ namespace OC
         }
         else
         {
+            delete context;
             result = OC_STACK_ERROR;
         }
         return result;
@@ -272,6 +273,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
         return result;
@@ -371,6 +373,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
@@ -415,6 +418,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
@@ -471,6 +475,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             result = OC_STACK_ERROR;
         }
 
@@ -544,6 +549,7 @@ namespace OC
         }
         else
         {
+            delete ctx;
             return OC_STACK_ERROR;
         }
 
@@ -575,13 +581,30 @@ namespace OC
     }
 
     OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
-        OCClientResponse* clientResponse)
+            OCClientResponse* clientResponse)
     {
-        ClientCallbackContext::SubscribePresenceContext* context =
-            static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
-        std::thread exec(context->callback, clientResponse->result, clientResponse->sequenceNumber);
+        char stringAddress[DEV_ADDR_SIZE_MAX];
+        ostringstream os;
+        uint16_t port;
 
-        exec.detach();
+        if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 &&
+                OCDevAddrToPort(clientResponse->addr, &port) == 0)
+        {
+            os<<stringAddress<<":"<<port;
+
+            ClientCallbackContext::SubscribePresenceContext* context =
+                static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
+
+            std::thread exec(context->callback, clientResponse->result,
+                    clientResponse->sequenceNumber, os.str());
+
+            exec.detach();
+        }
+        else
+        {
+            oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() "
+                    <<"failed"<< std::flush;
+        }
         return OC_STACK_KEEP_TRANSACTION;
     }
 
@@ -609,7 +632,10 @@ namespace OC
         }
 
         if(!cLock)
+        {
+            delete ctx;
             return OC_STACK_ERROR;
+        }
 
         return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
                             OC_LOW_QOS, &cbdata, NULL, 0);
index 27741f9..c92a036 100644 (file)
@@ -120,10 +120,13 @@ void formResourceRequest(OCEntityHandlerFlag flag,
         pRequest->setRequestHandlerFlag(
                    OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
 
-        OC::ObservationInfo observationInfo;
-        observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
-        observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
-        pRequest->setObservationInfo(observationInfo);
+        if(entityHandlerRequest)
+        {
+            OC::ObservationInfo observationInfo;
+            observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
+            observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
+            pRequest->setObservationInfo(observationInfo);
+        }
     }
 }
 
index f251818..460e9ac 100644 (file)
 /// @brief  This file contains the implementation of classes and its members
 ///         related to OCRepresentation
 
+
+#include <OCRepresentation.h>
+
 #include <cereal/cereal.hpp>
 #include <cereal/types/map.hpp>
 #include <cereal/types/vector.hpp>
 #include <cereal/types/utility.hpp>
+#include <OicJsonSerializer.hpp>
 #include <algorithm>
-#include <OCRepresentation.h>
+
+// code needed to serialize a string::Attribute value map
+namespace OC
+{
+    namespace detail
+    {
+        template<class Archive>
+        class WriteAttributeValue : public boost::static_visitor<>
+        {
+            public:
+                WriteAttributeValue(const std::string& name, Archive& ar)
+                    :m_name(name), m_archive(ar)
+                {}
+
+                template<class T>
+                void operator()(const T& value) const
+                {
+                    m_archive(cereal::make_nvp(m_name, value));
+                }
+            private:
+                std::string m_name;
+                Archive& m_archive;
+        };
+    }
+}
+
+namespace cereal
+{
+    // take no action when serializing the null type, because the 'save' below
+    // doesn't use the visitor for this type.
+    template <class Archive>
+    void serialize(Archive&, OC::NullType t)
+    {}
+
+    template<class Archive>
+    void save(Archive& ar, const std::map<std::string, OC::AttributeValue>& vals)
+    {
+        for(const auto& kv : vals)
+        {
+            const auto& k = kv.first;
+            const auto& v = kv.second;
+
+            if(v.which() != OC::AttributeValueNullIndex)
+            {
+                OC::detail::WriteAttributeValue<Archive> writer(k,ar);
+                boost::apply_visitor(writer, v);
+            }
+            else
+            {
+                ar.setNextName(k.c_str());
+                ar.writeName();
+                ar.saveValue();
+            }
+        }
+    }
+
+    template<class Archive>
+    void load(Archive& ar, std::map<std::string, OC::AttributeValue>& vals)
+    {
+        ar.loadAttributeValues(vals);
+    }
+}
+
 namespace OC
 {
     typedef cereal::JSONOutputArchive OutputArchiveType;
@@ -222,6 +288,92 @@ namespace OC
     }
 }
 
+namespace OC
+{
+    template <class Archive, class Val>
+    void OCRepresentation::optional_load(Archive& ar, Val&& v)
+    {
+        try
+        {
+            ar(v);
+        }
+        catch(cereal::Exception& e)
+        {
+            ar.setNextName(nullptr);
+            // Loading a key that doesn't exist results in an exception
+            // Since "Not Found" is a valid condition for us, we swallow
+            // this exception and the archive will not load anything
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::save(Archive& ar) const
+    {
+        // printed for all interface types
+        if(!m_uri.empty())
+        {
+            ar(cereal::make_nvp(Key::URIKEY, m_uri));
+        }
+
+        if((m_interfaceType == InterfaceType::None
+                    || m_interfaceType==InterfaceType::DefaultChild
+                    || m_interfaceType==InterfaceType::LinkChild)
+                && (m_resourceTypes.size()>0 || m_interfaces.size()>0))
+        {
+            // The Prop object requires that it refer to non-const vectors
+            // so that it can alter them in the 'load' case.  In the save case
+            // (initiated here) it will not modify the object.  So, to keep the
+            // compiler happy, removing the 'const' context here is necessary.
+            const std::vector<std::string>& rt(m_resourceTypes);
+            const std::vector<std::string>& intf(m_interfaces);
+            Prop temp(const_cast<std::vector<std::string>&>(rt),
+                    const_cast<std::vector<std::string>&>(intf));
+            ar(cereal::make_nvp(Key::PROPERTYKEY, temp));
+        }
+
+        // printed only for BatchChildren and DefaultParent
+        if((m_interfaceType == InterfaceType::None
+                    || m_interfaceType == InterfaceType::BatchChild
+                    || m_interfaceType == InterfaceType::DefaultParent)
+                && m_values.size()>0)
+        {
+            ar(cereal::make_nvp(Key::REPKEY, m_values));
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::load(Archive& ar)
+    {
+        optional_load(ar, cereal::make_nvp(Key::URIKEY, m_uri));
+        {
+            Prop temp(m_resourceTypes, m_interfaces);
+            optional_load(ar, cereal::make_nvp(Key::PROPERTYKEY, temp));
+        }
+        optional_load(ar, cereal::make_nvp(Key::REPKEY, m_values));
+    }
+
+    template<class Archive>
+    void OCRepresentation::Prop::save(Archive& ar) const
+    {
+        if(m_types.size() > 0)
+        {
+            ar(cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+        }
+
+        if(m_interfaces.size()>0)
+        {
+            ar(cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+        }
+    }
+
+    template<class Archive>
+    void OCRepresentation::Prop::load(Archive& ar)
+    {
+        optional_load(ar, cereal::make_nvp(Key::RESOURCETYPESKEY, m_types));
+        optional_load(ar, cereal::make_nvp(Key::INTERFACESKEY, m_interfaces));
+    }
+}
+
 // note: the below is used to load an AttributeValue map out of JSON
 namespace OC
 {
index ae26745..5461731 100644 (file)
@@ -42,9 +42,6 @@ ifeq ($(ROOT_DIR),)
        ROOT_DIR:=$(PWD)
 endif
 
-DEPEND_DIR:=$(ROOT_DIR)/../dependencies
-CEREAL_DIR:=$(DEPEND_DIR)/cereal
-
 INC_DIRS  := -I../include/
 INC_DIRS  += -I../oc_logger/include
 INC_DIRS  += -I../csdk/stack/include
@@ -53,7 +50,6 @@ INC_DIRS  += -I../csdk/ocrandom/include
 INC_DIRS  += -I../csdk/logger/include
 INC_DIRS  += -I../csdk/libcoap
 INC_DIRS  += -I$(GTEST_DIR)/include
-INC_DIRS  += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := ../oc_logger/lib/oc_logger.a
 
index 7def475..53f0396 100644 (file)
@@ -20,14 +20,14 @@ plugins:
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE)
 
 sample-app:
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE)
-       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/fan-control/fanclient release/
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE)
+       cp -Rdp $(PROTOCOL_ROOT)plugin-manager/build/linux/libpmimpl.so $(PROTOCOL_ROOT)sample-app/linux/mqtt/
+       cp -Rdp $(PROTOCOL_ROOT)sample-app/linux/mqtt/mqttclient release/
        
 
 clean:
        cd $(PROTOCOL_ROOT)plugin-manager/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-fan/build/linux && $(MAKE) clean
        cd $(PROTOCOL_ROOT)plugins/mqtt-light/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)plugins/hue/build/linux && $(MAKE) clean
-       cd $(PROTOCOL_ROOT)sample-app/linux/fan-control && $(MAKE) clean
+       cd $(PROTOCOL_ROOT)sample-app/linux/mqtt && $(MAKE) clean
        rm -rf release
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml.hpp
new file mode 100644 (file)
index 0000000..9ddf195
--- /dev/null
@@ -0,0 +1,2601 @@
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+    #include <cstdlib>      // For std::size_t
+    #include <cassert>      // For assert
+    #include <new>          // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4). 
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+    #pragma warning(push)
+    #pragma warning(disable:4127)   // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+    
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+    //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, 
+    //! this function is called to notify user about the error.
+    //! It must be defined by the user.
+    //! <br><br>
+    //! This function cannot return. If it does, the results are undefined.
+    //! <br><br>
+    //! A very simple definition might look like that:
+    //! <pre>
+    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+    //! {
+    //!     std::cout << "Parse error: " << what << "\n";
+    //!     std::abort();
+    //! }
+    //! </pre>
+    //! \param what Human readable description of the error.
+    //! \param where Pointer to character data where error was detected.
+    void parse_error_handler(const char *what, void *where);
+}
+
+#else
+    
+#include <exception>    // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+    //! Parse error exception. 
+    //! This exception is thrown by the parser when an error occurs. 
+    //! Use what() function to get human-readable error message. 
+    //! Use where() function to get a pointer to position within source text where error was detected.
+    //! <br><br>
+    //! If throwing exceptions by the parser is undesirable, 
+    //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+    //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+    //! This function must be defined by the user.
+    //! <br><br>
+    //! This class derives from <code>std::exception</code> class.
+    class parse_error: public std::exception
+    {
+    
+    public:
+    
+        //! Constructs parse error
+        parse_error(const char *what, void *where)
+            : m_what(what)
+            , m_where(where)
+        {
+        }
+
+        //! Gets human readable description of error.
+        //! \return Pointer to null terminated description of the error.
+        virtual const char *what() const throw()
+        {
+            return m_what;
+        }
+
+        //! Gets pointer to character data where error happened.
+        //! Ch should be the same as char type of xml_document that produced the error.
+        //! \return Pointer to location within the parsed string where error occured.
+        template<class Ch>
+        Ch *where() const
+        {
+            return reinterpret_cast<Ch *>(m_where);
+        }
+
+    private:  
+
+        const char *m_what;
+        void *m_where;
+
+    };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+    // Size of static memory block of memory_pool.
+    // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+    #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+    // Size of dynamic memory block of memory_pool.
+    // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+    // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+    #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+    // Memory allocation alignment.
+    // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+    // All memory allocations for nodes, attributes and strings will be aligned to this value.
+    // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+    #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+    // Forward declarations
+    template<class Ch> class xml_node;
+    template<class Ch> class xml_attribute;
+    template<class Ch> class xml_document;
+    
+    //! Enumeration listing all node types produced by the parser.
+    //! Use xml_node::type() function to query node type.
+    enum node_type
+    {
+        node_document,      //!< A document node. Name and value are empty.
+        node_element,       //!< An element node. Name contains element name. Value contains text of first data node.
+        node_data,          //!< A data node. Name is empty. Value contains data text.
+        node_cdata,         //!< A CDATA node. Name is empty. Value contains data text.
+        node_comment,       //!< A comment node. Name is empty. Value contains comment text.
+        node_declaration,   //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+        node_doctype,       //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+        node_pi             //!< A PI node. Name contains target. Value contains instructions.
+    };
+
+    ///////////////////////////////////////////////////////////////////////
+    // Parsing flags
+
+    //! Parse flag instructing the parser to not create data nodes. 
+    //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_data_nodes = 0x1;            
+
+    //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+    //! Can be combined with other flags by use of | operator.
+    //! Note that child data nodes of element node take precendence over its value when printing. 
+    //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+    //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_element_values = 0x2;
+    
+    //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+    //! By default zero terminators are placed, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_string_terminators = 0x4;
+    
+    //! Parse flag instructing the parser to not translate entities in the source text.
+    //! By default entities are translated, modifying source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_entity_translation = 0x8;
+    
+    //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+    //! By default, UTF-8 handling is enabled.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_no_utf8 = 0x10;
+    
+    //! Parse flag instructing the parser to create XML declaration node.
+    //! By default, declaration node is not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_declaration_node = 0x20;
+    
+    //! Parse flag instructing the parser to create comments nodes.
+    //! By default, comment nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_comment_nodes = 0x40;
+    
+    //! Parse flag instructing the parser to create DOCTYPE node.
+    //! By default, doctype node is not created.
+    //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_doctype_node = 0x80;
+    
+    //! Parse flag instructing the parser to create PI nodes.
+    //! By default, PI nodes are not created.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_pi_nodes = 0x100;
+    
+    //! Parse flag instructing the parser to validate closing tag names. 
+    //! If not set, name inside closing tag is irrelevant to the parser.
+    //! By default, closing tags are not validated.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_validate_closing_tags = 0x200;
+    
+    //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+    //! By default, whitespace is not trimmed. 
+    //! This flag does not cause the parser to modify source text.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_trim_whitespace = 0x400;
+
+    //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+    //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+    //! By default, whitespace is not normalized. 
+    //! If this flag is specified, source text will be modified.
+    //! Can be combined with other flags by use of | operator.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_normalize_whitespace = 0x800;
+
+    // Compound flags
+    
+    //! Parse flags which represent default behaviour of the parser. 
+    //! This is always equal to 0, so that all other flags can be simply ored together.
+    //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+    //! This also means that meaning of each flag is a <i>negation</i> of the default setting. 
+    //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+    //! and using the flag will disable it.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_default = 0;
+    
+    //! A combination of parse flags that forbids any modifications of the source text. 
+    //! This also results in faster parsing. However, note that the following will occur:
+    //! <ul>
+    //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+    //! <li>entities will not be translated</li>
+    //! <li>whitespace will not be normalized</li>
+    //! </ul>
+    //! See xml_document::parse() function.
+    const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+    
+    //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+    
+    //! A combination of parse flags resulting in largest amount of data being extracted. 
+    //! This usually results in slowest parsing.
+    //! <br><br>
+    //! See xml_document::parse() function.
+    const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internals
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Struct that contains lookup tables for the parser
+        // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+        template<int Dummy>
+        struct lookup_tables
+        {
+            static const unsigned char lookup_whitespace[256];              // Whitespace table
+            static const unsigned char lookup_node_name[256];               // Node name table
+            static const unsigned char lookup_text[256];                    // Text table
+            static const unsigned char lookup_text_pure_no_ws[256];         // Text table
+            static const unsigned char lookup_text_pure_with_ws[256];       // Text table
+            static const unsigned char lookup_attribute_name[256];          // Attribute name table
+            static const unsigned char lookup_attribute_data_1[256];        // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_1_pure[256];   // Attribute data table with single quote
+            static const unsigned char lookup_attribute_data_2[256];        // Attribute data table with double quotes
+            static const unsigned char lookup_attribute_data_2_pure[256];   // Attribute data table with double quotes
+            static const unsigned char lookup_digits[256];                  // Digits
+            static const unsigned char lookup_upcase[256];                  // To uppercase conversion table for ASCII characters
+        };
+
+        // Find length of the string
+        template<class Ch>
+        inline std::size_t measure(const Ch *p)
+        {
+            const Ch *tmp = p;
+            while (*tmp) 
+                ++tmp;
+            return tmp - p;
+        }
+
+        // Compare strings for equality
+        template<class Ch>
+        inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+        {
+            if (size1 != size2)
+                return false;
+            if (case_sensitive)
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (*p1 != *p2)
+                        return false;
+            }
+            else
+            {
+                for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+                    if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+                        return false;
+            }
+            return true;
+        }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////
+    // Memory pool
+    
+    //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+    //! In most cases, you will not need to use this class directly. 
+    //! However, if you need to create nodes manually or modify names/values of nodes, 
+    //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. 
+    //! Not only is this faster than allocating them by using <code>new</code> operator, 
+    //! but also their lifetime will be tied to the lifetime of document, 
+    //! possibly simplyfing memory management. 
+    //! <br><br>
+    //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. 
+    //! You can also call allocate_string() function to allocate strings.
+    //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+    //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, 
+    //! or when the pool is destroyed.
+    //! <br><br>
+    //! It is also possible to create a standalone memory_pool, and use it 
+    //! to allocate nodes, whose lifetime will not be tied to any document.
+    //! <br><br>
+    //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. 
+    //! Until static memory is exhausted, no dynamic memory allocations are done.
+    //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+    //! by using global <code>new[]</code> and <code>delete[]</code> operators. 
+    //! This behaviour can be changed by setting custom allocation routines. 
+    //! Use set_allocator() function to set them.
+    //! <br><br>
+    //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+    //! This value defaults to the size of pointer on target architecture.
+    //! <br><br>
+    //! To obtain absolutely top performance from the parser,
+    //! it is important that all nodes are allocated from a single, contiguous block of memory.
+    //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+    //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> 
+    //! to obtain best wasted memory to performance compromise.
+    //! To do it, define their values before rapidxml.hpp file is included.
+    //! \param Ch Character type of created nodes. 
+    template<class Ch = char>
+    class memory_pool
+    {
+        
+    public:
+
+        //! \cond internal
+        typedef void *(alloc_func)(std::size_t);       // Type of user-defined function used to allocate memory
+        typedef void (free_func)(void *);              // Type of user-defined function used to free memory
+        //! \endcond
+        
+        //! Constructs empty pool with default allocator functions.
+        memory_pool()
+            : m_alloc_func(0)
+            , m_free_func(0)
+        {
+            init();
+        }
+
+        //! Destroys pool and frees all the memory. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Nodes allocated from the pool are no longer valid.
+        ~memory_pool()
+        {
+            clear();
+        }
+
+        //! Allocates a new node from the pool, and optionally assigns name and value to it. 
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param type Type of node to create.
+        //! \param name Name to assign to the node, or 0 to assign no name.
+        //! \param value Value to assign to the node, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated node. This pointer will never be NULL.
+        xml_node<Ch> *allocate_node(node_type type, 
+                                    const Ch *name = 0, const Ch *value = 0, 
+                                    std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+            xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+            if (name)
+            {
+                if (name_size > 0)
+                    node->name(name, name_size);
+                else
+                    node->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    node->value(value, value_size);
+                else
+                    node->value(value);
+            }
+            return node;
+        }
+
+        //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param name Name to assign to the attribute, or 0 to assign no name.
+        //! \param value Value to assign to the attribute, or 0 to assign no value.
+        //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+        //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+        //! \return Pointer to allocated attribute. This pointer will never be NULL.
+        xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, 
+                                              std::size_t name_size = 0, std::size_t value_size = 0)
+        {
+            void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+            xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+            if (name)
+            {
+                if (name_size > 0)
+                    attribute->name(name, name_size);
+                else
+                    attribute->name(name);
+            }
+            if (value)
+            {
+                if (value_size > 0)
+                    attribute->value(value, value_size);
+                else
+                    attribute->value(value);
+            }
+            return attribute;
+        }
+
+        //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+        //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+        //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+        //! will call rapidxml::parse_error_handler() function.
+        //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+        //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+        //! \return Pointer to allocated char array. This pointer will never be NULL.
+        Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+        {
+            assert(source || size);     // Either source or size (or both) must be specified
+            if (size == 0)
+                size = internal::measure(source) + 1;
+            Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+            if (source)
+                for (std::size_t i = 0; i < size; ++i)
+                    result[i] = source[i];
+            return result;
+        }
+
+        //! Clones an xml_node and its hierarchy of child nodes and attributes.
+        //! Nodes and attributes are allocated from this memory pool.
+        //! Names and values are not cloned, they are shared between the clone and the source.
+        //! Result node can be optionally specified as a second parameter, 
+        //! in which case its contents will be replaced with cloned source node.
+        //! This is useful when you want to clone entire document.
+        //! \param source Node to clone.
+        //! \param result Node to put results in, or 0 to automatically allocate result node
+        //! \return Pointer to cloned node. This pointer will never be NULL.
+        xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+        {
+            // Prepare result node
+            if (result)
+            {
+                result->remove_all_attributes();
+                result->remove_all_nodes();
+                result->type(source->type());
+            }
+            else
+                result = allocate_node(source->type());
+
+            // Clone name and value
+            result->name(source->name(), source->name_size());
+            result->value(source->value(), source->value_size());
+
+            // Clone child nodes and attributes
+            for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+                result->append_node(clone_node(child));
+            for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+                result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+            return result;
+        }
+
+        //! Clears the pool. 
+        //! This causes memory occupied by nodes allocated by the pool to be freed.
+        //! Any nodes or strings allocated from the pool will no longer be valid.
+        void clear()
+        {
+            while (m_begin != m_static_memory)
+            {
+                char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+                if (m_free_func)
+                    m_free_func(m_begin);
+                else
+                    delete[] m_begin;
+                m_begin = previous_begin;
+            }
+            init();
+        }
+
+        //! Sets or resets the user-defined memory allocation functions for the pool.
+        //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+        //! Allocation function must not return invalid pointer on failure. It should either throw,
+        //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. 
+        //! If it returns invalid pointer, results are undefined.
+        //! <br><br>
+        //! User defined allocation functions must have the following forms:
+        //! <br><code>
+        //! <br>void *allocate(std::size_t size);
+        //! <br>void free(void *pointer);
+        //! </code><br>
+        //! \param af Allocation function, or 0 to restore default function
+        //! \param ff Free function, or 0 to restore default function
+        void set_allocator(alloc_func *af, free_func *ff)
+        {
+            assert(m_begin == m_static_memory && m_ptr == align(m_begin));    // Verify that no memory is allocated yet
+            m_alloc_func = af;
+            m_free_func = ff;
+        }
+
+    private:
+
+        struct header
+        {
+            char *previous_begin;
+        };
+
+        void init()
+        {
+            m_begin = m_static_memory;
+            m_ptr = align(m_begin);
+            m_end = m_static_memory + sizeof(m_static_memory);
+        }
+        
+        char *align(char *ptr)
+        {
+            std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+            return ptr + alignment;
+        }
+        
+        char *allocate_raw(std::size_t size)
+        {
+            // Allocate
+            void *memory;   
+            if (m_alloc_func)   // Allocate memory using either user-specified allocation function or global operator new[]
+            {
+                memory = m_alloc_func(size);
+                assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+            }
+            else
+            {
+                memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+                if (!memory)            // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+                    RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+            }
+            return static_cast<char *>(memory);
+        }
+        
+        void *allocate_aligned(std::size_t size)
+        {
+            // Calculate aligned pointer
+            char *result = align(m_ptr);
+
+            // If not enough memory left in current pool, allocate a new pool
+            if (result + size > m_end)
+            {
+                // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+                std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+                if (pool_size < size)
+                    pool_size = size;
+                
+                // Allocate
+                std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size;     // 2 alignments required in worst case: one for header, one for actual allocation
+                char *raw_memory = allocate_raw(alloc_size);
+                    
+                // Setup new pool in allocated memory
+                char *pool = align(raw_memory);
+                header *new_header = reinterpret_cast<header *>(pool);
+                new_header->previous_begin = m_begin;
+                m_begin = raw_memory;
+                m_ptr = pool + sizeof(header);
+                m_end = raw_memory + alloc_size;
+
+                // Calculate aligned pointer again using new pool
+                result = align(m_ptr);
+            }
+
+            // Update pool and return aligned pointer
+            m_ptr = result + size;
+            return result;
+        }
+
+        char *m_begin;                                      // Start of raw memory making up current pool
+        char *m_ptr;                                        // First free byte in current pool
+        char *m_end;                                        // One past last available byte in current pool
+        char m_static_memory[RAPIDXML_STATIC_POOL_SIZE];    // Static raw memory
+        alloc_func *m_alloc_func;                           // Allocator function, or 0 if default is to be used
+        free_func *m_free_func;                             // Free function, or 0 if default is to be used
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML base
+
+    //! Base class for xml_node and xml_attribute implementing common functions: 
+    //! name(), name_size(), value(), value_size() and parent().
+    //! \param Ch Character type to use
+    template<class Ch = char>
+    class xml_base
+    {
+
+    public:
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        // Construct a base with empty name, value and parent
+        xml_base()
+            : m_name(0)
+            , m_value(0)
+            , m_parent(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets name of the node. 
+        //! Interpretation of name depends on type of node.
+        //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use name_size() function to determine length of the name.
+        //! \return Name of node, or empty string if node has no name.
+        Ch *name() const
+        {
+            return m_name ? m_name : nullstr();
+        }
+
+        //! Gets size of node name, not including terminator character.
+        //! This function works correctly irrespective of whether name is or is not zero terminated.
+        //! \return Size of node name, in characters.
+        std::size_t name_size() const
+        {
+            return m_name ? m_name_size : 0;
+        }
+
+        //! Gets value of node. 
+        //! Interpretation of value depends on type of node.
+        //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+        //! <br><br>
+        //! Use value_size() function to determine length of the value.
+        //! \return Value of node, or empty string if node has no value.
+        Ch *value() const
+        {
+            return m_value ? m_value : nullstr();
+        }
+
+        //! Gets size of node value, not including terminator character.
+        //! This function works correctly irrespective of whether value is or is not zero terminated.
+        //! \return Size of node value, in characters.
+        std::size_t value_size() const
+        {
+            return m_value ? m_value_size : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets name of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of name must be specified separately, because name does not have to be zero terminated.
+        //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! \param name Name of node to set. Does not have to be zero terminated.
+        //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+        void name(const Ch *name, std::size_t size)
+        {
+            m_name = const_cast<Ch *>(name);
+            m_name_size = size;
+        }
+
+        //! Sets name of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+        //! \param name Name of node to set. Must be zero terminated.
+        void name(const Ch *name)
+        {
+            this->name(name, internal::measure(name));
+        }
+
+        //! Sets value of node to a non zero-terminated string.
+        //! See \ref ownership_of_strings.
+        //! <br><br>
+        //! Note that node does not own its name or value, it only stores a pointer to it. 
+        //! It will not delete or otherwise free the pointer on destruction.
+        //! It is reponsibility of the user to properly manage lifetime of the string.
+        //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+        //! on destruction of the document the string will be automatically freed.
+        //! <br><br>
+        //! Size of value must be specified separately, because it does not have to be zero terminated.
+        //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+        //! <br><br>
+        //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+        //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+        //! \param value value of node to set. Does not have to be zero terminated.
+        //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+        void value(const Ch *value, std::size_t size)
+        {
+            m_value = const_cast<Ch *>(value);
+            m_value_size = size;
+        }
+
+        //! Sets value of node to a zero-terminated string.
+        //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+        //! \param value Vame of node to set. Must be zero terminated.
+        void value(const Ch *value)
+        {
+            this->value(value, internal::measure(value));
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets node parent.
+        //! \return Pointer to parent node, or 0 if there is no parent.
+        xml_node<Ch> *parent() const
+        {
+            return m_parent;
+        }
+
+    protected:
+
+        // Return empty string
+        static Ch *nullstr()
+        {
+            static Ch zero = Ch('\0');
+            return &zero;
+        }
+
+        Ch *m_name;                         // Name of node, or 0 if no name
+        Ch *m_value;                        // Value of node, or 0 if no value
+        std::size_t m_name_size;            // Length of node name, or undefined of no name
+        std::size_t m_value_size;           // Length of node value, or undefined if no value
+        xml_node<Ch> *m_parent;             // Pointer to parent node, or 0 if none
+
+    };
+
+    //! Class representing attribute node of XML document. 
+    //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+    //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. 
+    //! Thus, this text must persist in memory for the lifetime of attribute.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_attribute: public xml_base<Ch>
+    {
+
+        friend class xml_node<Ch>;
+    
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty attribute with the specified type. 
+        //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+        xml_attribute()
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which attribute is a child.
+        //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            if (xml_node<Ch> *node = this->parent())
+            {
+                while (node->parent())
+                    node = node->parent();
+                return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+            }
+            else
+                return 0;
+        }
+
+        //! Gets previous attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_prev_attribute : 0;
+        }
+
+        //! Gets next attribute, optionally matching attribute name. 
+        //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return this->m_parent ? m_next_attribute : 0;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_prev_attribute;        // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+        xml_attribute<Ch> *m_next_attribute;        // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+    
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML node
+
+    //! Class representing a node of XML document. 
+    //! Each node may have associated name and value strings, which are available through name() and value() functions. 
+    //! Interpretation of name and value depends on type of the node.
+    //! Type of node can be determined by using type() function.
+    //! <br><br>
+    //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. 
+    //! Thus, this text must persist in the memory for the lifetime of node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_node: public xml_base<Ch>
+    {
+
+    public:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Construction & destruction
+    
+        //! Constructs an empty node with the specified type. 
+        //! Consider using memory_pool of appropriate document to allocate nodes manually.
+        //! \param type Type of node to construct.
+        xml_node(node_type type)
+            : m_type(type)
+            , m_first_node(0)
+            , m_first_attribute(0)
+        {
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node data access
+    
+        //! Gets type of node.
+        //! \return Type of node.
+        node_type type() const
+        {
+            return m_type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Related nodes access
+    
+        //! Gets document of which node is a child.
+        //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+        xml_document<Ch> *document() const
+        {
+            xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+            while (node->parent())
+                node = node->parent();
+            return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+        }
+
+        //! Gets first child node, optionally matching node name.
+        //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_first_node;
+        }
+
+        //! Gets last child node, optionally matching node name. 
+        //! Behaviour is undefined if node has no children.
+        //! Use first_node() to test if node has children.
+        //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found child, or 0 if not found.
+        xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(m_first_node);  // Cannot query for last child if node has no children
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+                    if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+                        return child;
+                return 0;
+            }
+            else
+                return m_last_node;
+        }
+
+        //! Gets previous sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_prev_sibling;
+        }
+
+        //! Gets next sibling node, optionally matching node name. 
+        //! Behaviour is undefined if node has no parent.
+        //! Use parent() to test if node has a parent.
+        //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found sibling, or 0 if not found.
+        xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            assert(this->m_parent);     // Cannot query for siblings if node has no parent
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+                    if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+                        return sibling;
+                return 0;
+            }
+            else
+                return m_next_sibling;
+        }
+
+        //! Gets first attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute;
+        }
+
+        //! Gets last attribute of node, optionally matching attribute name.
+        //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+        //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+        //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+        //! \return Pointer to found attribute, or 0 if not found.
+        xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+        {
+            if (name)
+            {
+                if (name_size == 0)
+                    name_size = internal::measure(name);
+                for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+                    if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+                        return attribute;
+                return 0;
+            }
+            else
+                return m_first_attribute ? m_last_attribute : 0;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node modification
+    
+        //! Sets type of node.
+        //! \param type Type of node to set.
+        void type(node_type type)
+        {
+            m_type = type;
+        }
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Node manipulation
+
+        //! Prepends a new child node.
+        //! The prepended child becomes the first child, and all existing children are moved one position back.
+        //! \param child Node to prepend.
+        void prepend_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_next_sibling = m_first_node;
+                m_first_node->m_prev_sibling = child;
+            }
+            else
+            {
+                child->m_next_sibling = 0;
+                m_last_node = child;
+            }
+            m_first_node = child;
+            child->m_parent = this;
+            child->m_prev_sibling = 0;
+        }
+
+        //! Appends a new child node. 
+        //! The appended child becomes the last child.
+        //! \param child Node to append.
+        void append_node(xml_node<Ch> *child)
+        {
+            assert(child && !child->parent() && child->type() != node_document);
+            if (first_node())
+            {
+                child->m_prev_sibling = m_last_node;
+                m_last_node->m_next_sibling = child;
+            }
+            else
+            {
+                child->m_prev_sibling = 0;
+                m_first_node = child;
+            }
+            m_last_node = child;
+            child->m_parent = this;
+            child->m_next_sibling = 0;
+        }
+
+        //! Inserts a new child node at specified place inside the node. 
+        //! All children after and including the specified node are moved one position back.
+        //! \param where Place where to insert the child, or 0 to insert at the back.
+        //! \param child Node to insert.
+        void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+        {
+            assert(!where || where->parent() == this);
+            assert(child && !child->parent() && child->type() != node_document);
+            if (where == m_first_node)
+                prepend_node(child);
+            else if (where == 0)
+                append_node(child);
+            else
+            {
+                child->m_prev_sibling = where->m_prev_sibling;
+                child->m_next_sibling = where;
+                where->m_prev_sibling->m_next_sibling = child;
+                where->m_prev_sibling = child;
+                child->m_parent = this;
+            }
+        }
+
+        //! Removes first child node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_first_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_first_node;
+            m_first_node = child->m_next_sibling;
+            if (child->m_next_sibling)
+                child->m_next_sibling->m_prev_sibling = 0;
+            else
+                m_last_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes last child of the node. 
+        //! If node has no children, behaviour is undefined.
+        //! Use first_node() to test if node has children.
+        void remove_last_node()
+        {
+            assert(first_node());
+            xml_node<Ch> *child = m_last_node;
+            if (child->m_prev_sibling)
+            {
+                m_last_node = child->m_prev_sibling;
+                child->m_prev_sibling->m_next_sibling = 0;
+            }
+            else
+                m_first_node = 0;
+            child->m_parent = 0;
+        }
+
+        //! Removes specified child from the node
+        // \param where Pointer to child to be removed.
+        void remove_node(xml_node<Ch> *where)
+        {
+            assert(where && where->parent() == this);
+            assert(first_node());
+            if (where == m_first_node)
+                remove_first_node();
+            else if (where == m_last_node)
+                remove_last_node();
+            else
+            {
+                where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+                where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all child nodes (but not attributes).
+        void remove_all_nodes()
+        {
+            for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+                node->m_parent = 0;
+            m_first_node = 0;
+        }
+
+        //! Prepends a new attribute to the node.
+        //! \param attribute Attribute to prepend.
+        void prepend_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_next_attribute = m_first_attribute;
+                m_first_attribute->m_prev_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_next_attribute = 0;
+                m_last_attribute = attribute;
+            }
+            m_first_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_prev_attribute = 0;
+        }
+
+        //! Appends a new attribute to the node.
+        //! \param attribute Attribute to append.
+        void append_attribute(xml_attribute<Ch> *attribute)
+        {
+            assert(attribute && !attribute->parent());
+            if (first_attribute())
+            {
+                attribute->m_prev_attribute = m_last_attribute;
+                m_last_attribute->m_next_attribute = attribute;
+            }
+            else
+            {
+                attribute->m_prev_attribute = 0;
+                m_first_attribute = attribute;
+            }
+            m_last_attribute = attribute;
+            attribute->m_parent = this;
+            attribute->m_next_attribute = 0;
+        }
+
+        //! Inserts a new attribute at specified place inside the node. 
+        //! All attributes after and including the specified attribute are moved one position back.
+        //! \param where Place where to insert the attribute, or 0 to insert at the back.
+        //! \param attribute Attribute to insert.
+        void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+        {
+            assert(!where || where->parent() == this);
+            assert(attribute && !attribute->parent());
+            if (where == m_first_attribute)
+                prepend_attribute(attribute);
+            else if (where == 0)
+                append_attribute(attribute);
+            else
+            {
+                attribute->m_prev_attribute = where->m_prev_attribute;
+                attribute->m_next_attribute = where;
+                where->m_prev_attribute->m_next_attribute = attribute;
+                where->m_prev_attribute = attribute;
+                attribute->m_parent = this;
+            }
+        }
+
+        //! Removes first attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_first_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_first_attribute;
+            if (attribute->m_next_attribute)
+            {
+                attribute->m_next_attribute->m_prev_attribute = 0;
+            }
+            else
+                m_last_attribute = 0;
+            attribute->m_parent = 0;
+            m_first_attribute = attribute->m_next_attribute;
+        }
+
+        //! Removes last attribute of the node. 
+        //! If node has no attributes, behaviour is undefined.
+        //! Use first_attribute() to test if node has attributes.
+        void remove_last_attribute()
+        {
+            assert(first_attribute());
+            xml_attribute<Ch> *attribute = m_last_attribute;
+            if (attribute->m_prev_attribute)
+            {
+                attribute->m_prev_attribute->m_next_attribute = 0;
+                m_last_attribute = attribute->m_prev_attribute;
+            }
+            else
+                m_first_attribute = 0;
+            attribute->m_parent = 0;
+        }
+
+        //! Removes specified attribute from node.
+        //! \param where Pointer to attribute to be removed.
+        void remove_attribute(xml_attribute<Ch> *where)
+        {
+            assert(first_attribute() && where->parent() == this);
+            if (where == m_first_attribute)
+                remove_first_attribute();
+            else if (where == m_last_attribute)
+                remove_last_attribute();
+            else
+            {
+                where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+                where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+                where->m_parent = 0;
+            }
+        }
+
+        //! Removes all attributes of node.
+        void remove_all_attributes()
+        {
+            for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+                attribute->m_parent = 0;
+            m_first_attribute = 0;
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////////
+        // Restrictions
+
+        // No copying
+        xml_node(const xml_node &);
+        void operator =(const xml_node &);
+    
+        ///////////////////////////////////////////////////////////////////////////
+        // Data members
+    
+        // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+        // This is required for maximum performance, as it allows the parser to omit initialization of 
+        // unneded/redundant values.
+        //
+        // The rules are as follows:
+        // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+        // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+        // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+        node_type m_type;                       // Type of node; always valid
+        xml_node<Ch> *m_first_node;             // Pointer to first child node, or 0 if none; always valid
+        xml_node<Ch> *m_last_node;              // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+        xml_attribute<Ch> *m_first_attribute;   // Pointer to first attribute of node, or 0 if none; always valid
+        xml_attribute<Ch> *m_last_attribute;    // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+        xml_node<Ch> *m_prev_sibling;           // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+        xml_node<Ch> *m_next_sibling;           // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    // XML document
+    
+    //! This class represents root of the DOM hierarchy. 
+    //! It is also an xml_node and a memory_pool through public inheritance.
+    //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+    //! parse() function allocates memory for nodes and attributes by using functions of xml_document, 
+    //! which are inherited from memory_pool.
+    //! To access root node of the document, use the document itself, as if it was an xml_node.
+    //! \param Ch Character type to use.
+    template<class Ch = char>
+    class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+    {
+    
+    public:
+
+        //! Constructs empty XML document
+        xml_document()
+            : xml_node<Ch>(node_document)
+        {
+        }
+
+        //! Parses zero-terminated XML string according to given flags.
+        //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+        //! The string must persist for the lifetime of the document.
+        //! In case of error, rapidxml::parse_error exception will be thrown.
+        //! <br><br>
+        //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+        //! Make sure that data is zero-terminated.
+        //! <br><br>
+        //! Document can be parsed into multiple times. 
+        //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+        //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+        template<int Flags>
+        void parse(Ch *text)
+        {
+            assert(text);
+            
+            // Remove current contents
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            
+            // Parse BOM, if any
+            parse_bom<Flags>(text);
+            
+            // Parse children
+            while (1)
+            {
+                // Skip whitespace before node
+                skip<whitespace_pred, Flags>(text);
+                if (*text == 0)
+                    break;
+
+                // Parse and append new child
+                if (*text == Ch('<'))
+                {
+                    ++text;     // Skip '<'
+                    if (xml_node<Ch> *node = parse_node<Flags>(text))
+                        this->append_node(node);
+                }
+                else
+                    RAPIDXML_PARSE_ERROR("expected <", text);
+            }
+
+        }
+
+        //! Clears the document by deleting all nodes and clearing the memory pool.
+        //! All nodes owned by document pool are destroyed.
+        void clear()
+        {
+            this->remove_all_nodes();
+            this->remove_all_attributes();
+            memory_pool<Ch>::clear();
+        }
+        
+    private:
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal character utility functions
+        
+        // Detect whitespace character
+        struct whitespace_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect node name character
+        struct node_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute name character
+        struct attribute_name_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA)
+        struct text_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_no_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect text character (PCDATA) that does not require processing
+        struct text_pure_with_ws_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Detect attribute value character
+        template<Ch Quote>
+        struct attribute_value_pure_pred
+        {
+            static unsigned char test(Ch ch)
+            {
+                if (Quote == Ch('\''))
+                    return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+                if (Quote == Ch('\"'))
+                    return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+                return 0;       // Should never be executed, to avoid warnings on Comeau
+            }
+        };
+
+        // Insert coded character, using UTF8 or 8-bit ASCII
+        template<int Flags>
+        static void insert_coded_character(Ch *&text, unsigned long code)
+        {
+            if (Flags & parse_no_utf8)
+            {
+                // Insert 8-bit ASCII character
+                // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+                text[0] = static_cast<unsigned char>(code);
+                text += 1;
+            }
+            else
+            {
+                // Insert UTF8 sequence
+                if (code < 0x80)    // 1 byte sequence
+                {
+                       text[0] = static_cast<unsigned char>(code);
+                    text += 1;
+                }
+                else if (code < 0x800)  // 2 byte sequence
+                {
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xC0);
+                    text += 2;
+                }
+                   else if (code < 0x10000)    // 3 byte sequence
+                {
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xE0);
+                    text += 3;
+                }
+                   else if (code < 0x110000)   // 4 byte sequence
+                {
+                       text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+                       text[0] = static_cast<unsigned char>(code | 0xF0);
+                    text += 4;
+                }
+                else    // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+                {
+                    RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+                }
+            }
+        }
+
+        // Skip characters until predicate evaluates to true
+        template<class StopPred, int Flags>
+        static void skip(Ch *&text)
+        {
+            Ch *tmp = text;
+            while (StopPred::test(*tmp))
+                ++tmp;
+            text = tmp;
+        }
+
+        // Skip characters until predicate evaluates to true while doing the following:
+        // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+        // - condensing whitespace sequences to single space character
+        template<class StopPred, class StopPredPure, int Flags>
+        static Ch *skip_and_expand_character_refs(Ch *&text)
+        {
+            // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+            if (Flags & parse_no_entity_translation && 
+                !(Flags & parse_normalize_whitespace) &&
+                !(Flags & parse_trim_whitespace))
+            {
+                skip<StopPred, Flags>(text);
+                return text;
+            }
+            
+            // Use simple skip until first modification is detected
+            skip<StopPredPure, Flags>(text);
+
+            // Use translation skip
+            Ch *src = text;
+            Ch *dest = src;
+            while (StopPred::test(*src))
+            {
+                // If entity translation is enabled    
+                if (!(Flags & parse_no_entity_translation))
+                {
+                    // Test if replacement is needed
+                    if (src[0] == Ch('&'))
+                    {
+                        switch (src[1])
+                        {
+
+                        // &amp; &apos;
+                        case Ch('a'): 
+                            if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+                            {
+                                *dest = Ch('&');
+                                ++dest;
+                                src += 5;
+                                continue;
+                            }
+                            if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('\'');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &quot;
+                        case Ch('q'): 
+                            if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+                            {
+                                *dest = Ch('"');
+                                ++dest;
+                                src += 6;
+                                continue;
+                            }
+                            break;
+
+                        // &gt;
+                        case Ch('g'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('>');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &lt;
+                        case Ch('l'): 
+                            if (src[2] == Ch('t') && src[3] == Ch(';'))
+                            {
+                                *dest = Ch('<');
+                                ++dest;
+                                src += 4;
+                                continue;
+                            }
+                            break;
+
+                        // &#...; - assumes ASCII
+                        case Ch('#'): 
+                            if (src[2] == Ch('x'))
+                            {
+                                unsigned long code = 0;
+                                src += 3;   // Skip &#x
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 16 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            else
+                            {
+                                unsigned long code = 0;
+                                src += 2;   // Skip &#
+                                while (1)
+                                {
+                                    unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+                                    if (digit == 0xFF)
+                                        break;
+                                    code = code * 10 + digit;
+                                    ++src;
+                                }
+                                insert_coded_character<Flags>(dest, code);    // Put character in output
+                            }
+                            if (*src == Ch(';'))
+                                ++src;
+                            else
+                                RAPIDXML_PARSE_ERROR("expected ;", src);
+                            continue;
+
+                        // Something else
+                        default:
+                            // Ignore, just copy '&' verbatim
+                            break;
+
+                        }
+                    }
+                }
+                
+                // If whitespace condensing is enabled
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Test if condensing is needed                 
+                    if (whitespace_pred::test(*src))
+                    {
+                        *dest = Ch(' '); ++dest;    // Put single space in dest
+                        ++src;                      // Skip first whitespace char
+                        // Skip remaining whitespace chars
+                        while (whitespace_pred::test(*src))
+                            ++src;
+                        continue;
+                    }
+                }
+
+                // No replacement, only copy character
+                *dest++ = *src++;
+
+            }
+
+            // Return new end
+            text = src;
+            return dest;
+
+        }
+
+        ///////////////////////////////////////////////////////////////////////
+        // Internal parsing functions
+        
+        // Parse BOM, if any
+        template<int Flags>
+        void parse_bom(Ch *&text)
+        {
+            // UTF-8?
+            if (static_cast<unsigned char>(text[0]) == 0xEF && 
+                static_cast<unsigned char>(text[1]) == 0xBB && 
+                static_cast<unsigned char>(text[2]) == 0xBF)
+            {
+                text += 3;      // Skup utf-8 bom
+            }
+        }
+
+        // Parse XML declaration (<?xml...)
+        template<int Flags>
+        xml_node<Ch> *parse_xml_declaration(Ch *&text)
+        {
+            // If parsing of declaration is disabled
+            if (!(Flags & parse_declaration_node))
+            {
+                // Skip until end of declaration
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+
+            // Create declaration
+            xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+            // Skip whitespace before attributes or ?>
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse declaration attributes
+            parse_node_attributes<Flags>(text, declaration);
+            
+            // Skip ?>
+            if (text[0] != Ch('?') || text[1] != Ch('>'))
+                RAPIDXML_PARSE_ERROR("expected ?>", text);
+            text += 2;
+            
+            return declaration;
+        }
+
+        // Parse XML comment (<!--...)
+        template<int Flags>
+        xml_node<Ch> *parse_comment(Ch *&text)
+        {
+            // If parsing of comments is disabled
+            if (!(Flags & parse_comment_nodes))
+            {
+                // Skip until end of comment
+                while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;     // Skip '-->'
+                return 0;      // Do not produce comment node
+            }
+
+            // Remember value start
+            Ch *value = text;
+
+            // Skip until end of comment
+            while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create comment node
+            xml_node<Ch> *comment = this->allocate_node(node_comment);
+            comment->value(value, text - value);
+            
+            // Place zero terminator after comment value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+            
+            text += 3;     // Skip '-->'
+            return comment;
+        }
+
+        // Parse DOCTYPE
+        template<int Flags>
+        xml_node<Ch> *parse_doctype(Ch *&text)
+        {
+            // Remember value start
+            Ch *value = text;
+
+            // Skip to >
+            while (*text != Ch('>'))
+            {
+                // Determine character type
+                switch (*text)
+                {
+                
+                // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+                // This works for all W3C test files except for 2 most wicked
+                case Ch('['):
+                {
+                    ++text;     // Skip '['
+                    int depth = 1;
+                    while (depth > 0)
+                    {
+                        switch (*text)
+                        {
+                            case Ch('['): ++depth; break;
+                            case Ch(']'): --depth; break;
+                            case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                                                       default: break;
+                        }
+                        ++text;
+                    }
+                    break;
+                }
+                
+                // Error on end of text
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                
+                // Other character, skip it
+                default:
+                    ++text;
+
+                }
+            }
+            
+            // If DOCTYPE nodes enabled
+            if (Flags & parse_doctype_node)
+            {
+                // Create a new doctype node
+                xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+                doctype->value(value, text - value);
+                
+                // Place zero terminator after value
+                if (!(Flags & parse_no_string_terminators))
+                    *text = Ch('\0');
+
+                text += 1;      // skip '>'
+                return doctype;
+            }
+            else
+            {
+                text += 1;      // skip '>'
+                return 0;
+            }
+
+        }
+
+        // Parse PI
+        template<int Flags>
+        xml_node<Ch> *parse_pi(Ch *&text)
+        {
+            // If creation of PI nodes is enabled
+            if (Flags & parse_pi_nodes)
+            {
+                // Create pi node
+                xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+                // Extract PI target name
+                Ch *name = text;
+                skip<node_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected PI target", text);
+                pi->name(name, text - name);
+                
+                // Skip whitespace between pi target and pi
+                skip<whitespace_pred, Flags>(text);
+
+                // Remember start of pi
+                Ch *value = text;
+                
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+
+                // Set pi value (verbatim, no entity expansion or whitespace normalization)
+                pi->value(value, text - value);     
+                
+                // Place zero terminator after name and value
+                if (!(Flags & parse_no_string_terminators))
+                {
+                    pi->name()[pi->name_size()] = Ch('\0');
+                    pi->value()[pi->value_size()] = Ch('\0');
+                }
+                
+                text += 2;                          // Skip '?>'
+                return pi;
+            }
+            else
+            {
+                // Skip to '?>'
+                while (text[0] != Ch('?') || text[1] != Ch('>'))
+                {
+                    if (*text == Ch('\0'))
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 2;    // Skip '?>'
+                return 0;
+            }
+        }
+
+        // Parse and append data
+        // Return character that ends data.
+        // This is necessary because this character might have been overwritten by a terminating 0
+        template<int Flags>
+        Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+        {
+            // Backup to contents start if whitespace trimming is disabled
+            if (!(Flags & parse_trim_whitespace))
+                text = contents_start;     
+            
+            // Skip until end of data
+            Ch *value = text, *end;
+            if (Flags & parse_normalize_whitespace)
+                end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);   
+            else
+                end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+            // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+            if (Flags & parse_trim_whitespace)
+            {
+                if (Flags & parse_normalize_whitespace)
+                {
+                    // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+                    if (*(end - 1) == Ch(' '))
+                        --end;
+                }
+                else
+                {
+                    // Backup until non-whitespace character is found
+                    while (whitespace_pred::test(*(end - 1)))
+                        --end;
+                }
+            }
+            
+            // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+            // Create new data node
+            if (!(Flags & parse_no_data_nodes))
+            {
+                xml_node<Ch> *data = this->allocate_node(node_data);
+                data->value(value, end - value);
+                node->append_node(data);
+            }
+
+            // Add data to parent node if no data exists yet
+            if (!(Flags & parse_no_element_values)) 
+                if (*node->value() == Ch('\0'))
+                    node->value(value, end - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+            {
+                Ch ch = *text;
+                *end = Ch('\0');
+                return ch;      // Return character that ends data; this is required because zero terminator overwritten it
+            }
+
+            // Return character that ends data
+            return *text;
+        }
+
+        // Parse CDATA
+        template<int Flags>
+        xml_node<Ch> *parse_cdata(Ch *&text)
+        {
+            // If CDATA is disabled
+            if (Flags & parse_no_data_nodes)
+            {
+                // Skip until end of cdata
+                while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+                {
+                    if (!text[0])
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                text += 3;      // Skip ]]>
+                return 0;       // Do not produce CDATA node
+            }
+
+            // Skip until end of cdata
+            Ch *value = text;
+            while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+            {
+                if (!text[0])
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                ++text;
+            }
+
+            // Create new cdata node
+            xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+            cdata->value(value, text - value);
+
+            // Place zero terminator after value
+            if (!(Flags & parse_no_string_terminators))
+                *text = Ch('\0');
+
+            text += 3;      // Skip ]]>
+            return cdata;
+        }
+        
+        // Parse element node
+        template<int Flags>
+        xml_node<Ch> *parse_element(Ch *&text)
+        {
+            // Create element node
+            xml_node<Ch> *element = this->allocate_node(node_element);
+
+            // Extract element name
+            Ch *name = text;
+            skip<node_name_pred, Flags>(text);
+            if (text == name)
+                RAPIDXML_PARSE_ERROR("expected element name", text);
+            element->name(name, text - name);
+            
+            // Skip whitespace between element name and attributes or >
+            skip<whitespace_pred, Flags>(text);
+
+            // Parse attributes, if any
+            parse_node_attributes<Flags>(text, element);
+
+            // Determine ending type
+            if (*text == Ch('>'))
+            {
+                ++text;
+                parse_node_contents<Flags>(text, element);
+            }
+            else if (*text == Ch('/'))
+            {
+                ++text;
+                if (*text != Ch('>'))
+                    RAPIDXML_PARSE_ERROR("expected >", text);
+                ++text;
+            }
+            else
+                RAPIDXML_PARSE_ERROR("expected >", text);
+
+            // Place zero terminator after name
+            if (!(Flags & parse_no_string_terminators))
+                element->name()[element->name_size()] = Ch('\0');
+
+            // Return parsed element
+            return element;
+        }
+
+        // Determine node type, and parse it
+        template<int Flags>
+        xml_node<Ch> *parse_node(Ch *&text)
+        {
+            // Parse proper node type
+            switch (text[0])
+            {
+
+            // <...
+            default: 
+                // Parse and append element node
+                return parse_element<Flags>(text);
+
+            // <?...
+            case Ch('?'): 
+                ++text;     // Skip ?
+                if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+                    (text[1] == Ch('m') || text[1] == Ch('M')) && 
+                    (text[2] == Ch('l') || text[2] == Ch('L')) &&
+                    whitespace_pred::test(text[3]))
+                {
+                    // '<?xml ' - xml declaration
+                    text += 4;      // Skip 'xml '
+                    return parse_xml_declaration<Flags>(text);
+                }
+                else
+                {
+                    // Parse PI
+                    return parse_pi<Flags>(text);
+                }
+            
+            // <!...
+            case Ch('!'): 
+
+                // Parse proper subset of <! node
+                switch (text[1])    
+                {
+                
+                // <!-
+                case Ch('-'):
+                    if (text[2] == Ch('-'))
+                    {
+                        // '<!--' - xml comment
+                        text += 3;     // Skip '!--'
+                        return parse_comment<Flags>(text);
+                    }
+                    break;
+
+                // <![
+                case Ch('['):
+                    if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') && 
+                        text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+                    {
+                        // '<![CDATA[' - cdata
+                        text += 8;     // Skip '![CDATA['
+                        return parse_cdata<Flags>(text);
+                    }
+                    break;
+
+                // <!D
+                case Ch('D'):
+                    if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') && 
+                        text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') && 
+                        whitespace_pred::test(text[8]))
+                    {
+                        // '<!DOCTYPE ' - doctype
+                        text += 9;      // skip '!DOCTYPE '
+                        return parse_doctype<Flags>(text);
+                    }
+                                       break;
+                               
+                               default:
+                                       break;
+
+                }   // switch
+
+                // Attempt to skip other, unrecognized node types starting with <!
+                ++text;     // Skip !
+                while (*text != Ch('>'))
+                {
+                    if (*text == 0)
+                        RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+                    ++text;
+                }
+                ++text;     // Skip '>'
+                return 0;   // No node recognized
+
+            }
+        }
+
+        // Parse contents of the node - children, data etc.
+        template<int Flags>
+        void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all children and text
+            while (1)
+            {
+                // Skip whitespace between > and node contents
+                Ch *contents_start = text;      // Store start of node contents before whitespace is skipped
+                skip<whitespace_pred, Flags>(text);
+                Ch next_char = *text;
+
+            // After data nodes, instead of continuing the loop, control jumps here.
+            // This is because zero termination inside parse_and_append_data() function
+            // would wreak havoc with the above code.
+            // Also, skipping whitespace after data nodes is unnecessary.
+            after_data_node:    
+                
+                // Determine what comes next: node closing, child node, data node, or 0?
+                switch (next_char)
+                {
+                
+                // Node closing or child node
+                case Ch('<'):
+                    if (text[1] == Ch('/'))
+                    {
+                        // Node closing
+                        text += 2;      // Skip '</'
+                        if (Flags & parse_validate_closing_tags)
+                        {
+                            // Skip and validate closing tag name
+                            Ch *closing_name = text;
+                            skip<node_name_pred, Flags>(text);
+                            if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+                                RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+                        }
+                        else
+                        {
+                            // No validation, just skip name
+                            skip<node_name_pred, Flags>(text);
+                        }
+                        // Skip remaining whitespace after node name
+                        skip<whitespace_pred, Flags>(text);
+                        if (*text != Ch('>'))
+                            RAPIDXML_PARSE_ERROR("expected >", text);
+                        ++text;     // Skip '>'
+                        return;     // Node closed, finished parsing contents
+                    }
+                    else
+                    {
+                        // Child node
+                        ++text;     // Skip '<'
+                        if (xml_node<Ch> *child = parse_node<Flags>(text))
+                            node->append_node(child);
+                    }
+                    break;
+
+                // End of data - error
+                case Ch('\0'):
+                    RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+
+                // Data node
+                default:
+                    next_char = parse_and_append_data<Flags>(node, text, contents_start);
+                    goto after_data_node;   // Bypass regular processing after data nodes
+
+                }
+            }
+        }
+        
+        // Parse XML attributes of the node
+        template<int Flags>
+        void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+        {
+            // For all attributes 
+            while (attribute_name_pred::test(*text))
+            {
+                // Extract attribute name
+                Ch *name = text;
+                ++text;     // Skip first character of attribute name
+                skip<attribute_name_pred, Flags>(text);
+                if (text == name)
+                    RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+                // Create new attribute
+                xml_attribute<Ch> *attribute = this->allocate_attribute();
+                attribute->name(name, text - name);
+                node->append_attribute(attribute);
+
+                // Skip whitespace after attribute name
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip =
+                if (*text != Ch('='))
+                    RAPIDXML_PARSE_ERROR("expected =", text);
+                ++text;
+
+                // Add terminating zero after name
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->name()[attribute->name_size()] = 0;
+
+                // Skip whitespace after =
+                skip<whitespace_pred, Flags>(text);
+
+                // Skip quote and remember if it was ' or "
+                Ch quote = *text;
+                if (quote != Ch('\'') && quote != Ch('"'))
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;
+
+                // Extract attribute value and expand char refs in it
+                Ch *value = text, *end;
+                const int AttFlags = Flags & ~parse_normalize_whitespace;   // No whitespace normalization in attributes
+                if (quote == Ch('\''))
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+                else
+                    end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+                
+                // Set attribute value
+                attribute->value(value, end - value);
+                
+                // Make sure that end quote is present
+                if (*text != quote)
+                    RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+                ++text;     // Skip quote
+
+                // Add terminating zero after value
+                if (!(Flags & parse_no_string_terminators))
+                    attribute->value()[attribute->value_size()] = 0;
+
+                // Skip whitespace after attribute value
+                skip<whitespace_pred, Flags>(text);
+            }
+        }
+
+    };
+
+    //! \cond internal
+    namespace internal
+    {
+
+        // Whitespace (space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,  // 0
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 1
+             1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 2
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 3
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 4
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 5
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 6
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 7
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 8
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // 9
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // A
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // B
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // C
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // D
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  // E
+             0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0   // F
+        };
+
+        // Node name (anything but space \n \r \t / > ? \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_node_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) (anything but < \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled 
+        // (anything but < \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+        // (anything but < \0 & space \n \r \t)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote (anything but ' \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with single quote that does not require processing (anything but ' \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote (anything but " \0)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Attribute data with double quote that does not require processing (anything but " \0 &)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+             0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 0
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 1
+             1,  1,  0,  1,  1,  1,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 2
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 3
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 4
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 5
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 6
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 7
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 8
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // 9
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // A
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // B
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // C
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // D
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  // E
+             1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   // F
+        };
+
+        // Digits (dec and hex, 255 denotes end of numeric character reference)
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_digits[256] = 
+        {
+          // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 0
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 1
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 2
+             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,255,255,255,255,255,255,  // 3
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 4
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 5
+           255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255,  // 6
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 7
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 8
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // 9
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // A
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // B
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // C
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // D
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,  // E
+           255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255   // F
+        };
+    
+        // Upper case conversion
+        template<int Dummy>
+        const unsigned char lookup_tables<Dummy>::lookup_upcase[256] = 
+        {
+          // 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A   B   C   D   E   F
+           0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,   // 0
+           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,   // 1
+           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,   // 2
+           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,   // 3
+           64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 4
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,   // 5
+           96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,   // 6
+           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127,  // 7
+           128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,  // 8
+           144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,  // 9
+           160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,  // A
+           176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,  // B
+           192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,  // C
+           208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,  // D
+           224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,  // E
+           240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255   // F
+        };
+    }
+    //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+    #pragma warning(pop)
+#endif
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_iterators.hpp
new file mode 100644 (file)
index 0000000..52ebc29
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
+#define RAPIDXML_ITERATORS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_iterators.hpp This file contains rapidxml iterators
+
+#include "rapidxml.hpp"
+
+namespace rapidxml
+{
+
+    //! Iterator of child nodes of xml_node
+    template<class Ch>
+    class node_iterator
+    {
+    
+    public:
+
+        typedef typename xml_node<Ch> value_type;
+        typedef typename xml_node<Ch> &reference;
+        typedef typename xml_node<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        node_iterator()
+            : m_node(0)
+        {
+        }
+
+        node_iterator(xml_node<Ch> *node)
+            : m_node(node->first_node())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_node);
+            return *m_node;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_node);
+            return m_node;
+        }
+
+        node_iterator& operator++()
+        {
+            assert(m_node);
+            m_node = m_node->next_sibling();
+            return *this;
+        }
+
+        node_iterator operator++(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        node_iterator& operator--()
+        {
+            assert(m_node && m_node->previous_sibling());
+            m_node = m_node->previous_sibling();
+            return *this;
+        }
+
+        node_iterator operator--(int)
+        {
+            node_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const node_iterator<Ch> &rhs)
+        {
+            return m_node == rhs.m_node;
+        }
+
+        bool operator !=(const node_iterator<Ch> &rhs)
+        {
+            return m_node != rhs.m_node;
+        }
+
+    private:
+
+        xml_node<Ch> *m_node;
+
+    };
+
+    //! Iterator of child attributes of xml_node
+    template<class Ch>
+    class attribute_iterator
+    {
+    
+    public:
+
+        typedef typename xml_attribute<Ch> value_type;
+        typedef typename xml_attribute<Ch> &reference;
+        typedef typename xml_attribute<Ch> *pointer;
+        typedef std::ptrdiff_t difference_type;
+        typedef std::bidirectional_iterator_tag iterator_category;
+        
+        attribute_iterator()
+            : m_attribute(0)
+        {
+        }
+
+        attribute_iterator(xml_node<Ch> *node)
+            : m_attribute(node->first_attribute())
+        {
+        }
+        
+        reference operator *() const
+        {
+            assert(m_attribute);
+            return *m_attribute;
+        }
+
+        pointer operator->() const
+        {
+            assert(m_attribute);
+            return m_attribute;
+        }
+
+        attribute_iterator& operator++()
+        {
+            assert(m_attribute);
+            m_attribute = m_attribute->next_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator++(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        attribute_iterator& operator--()
+        {
+            assert(m_attribute && m_attribute->previous_attribute());
+            m_attribute = m_attribute->previous_attribute();
+            return *this;
+        }
+
+        attribute_iterator operator--(int)
+        {
+            attribute_iterator tmp = *this;
+            ++this;
+            return tmp;
+        }
+
+        bool operator ==(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute == rhs.m_attribute;
+        }
+
+        bool operator !=(const attribute_iterator<Ch> &rhs)
+        {
+            return m_attribute != rhs.m_attribute;
+        }
+
+    private:
+
+        xml_attribute<Ch> *m_attribute;
+
+    };
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_print.hpp
new file mode 100644 (file)
index 0000000..f929b3c
--- /dev/null
@@ -0,0 +1,422 @@
+#ifndef RAPIDXML_PRINT_HPP_INCLUDED
+#define RAPIDXML_PRINT_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_print.hpp This file contains rapidxml printer implementation
+
+#include "rapidxml.hpp"
+
+// Only include streams if not disabled
+#ifndef RAPIDXML_NO_STREAMS
+    #include <ostream>
+    #include <iterator>
+#endif
+
+namespace rapidxml
+{
+
+    ///////////////////////////////////////////////////////////////////////
+    // Printing flags
+
+    const int print_no_indenting = 0x1;   //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
+
+    ///////////////////////////////////////////////////////////////////////
+    // Internal
+
+    //! \cond internal
+    namespace internal
+    {
+        
+        ///////////////////////////////////////////////////////////////////////////
+        // Internal character operations
+    
+        // Copy characters from given range to given output iterator
+        template<class OutIt, class Ch>
+        inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
+        {
+            while (begin != end)
+                *out++ = *begin++;
+            return out;
+        }
+        
+        // Copy characters from given range to given output iterator and expand
+        // characters into references (&lt; &gt; &apos; &quot; &amp;)
+        template<class OutIt, class Ch>
+        inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
+        {
+            while (begin != end)
+            {
+                if (*begin == noexpand)
+                {
+                    *out++ = *begin;    // No expansion, copy character
+                }
+                else
+                {
+                    switch (*begin)
+                    {
+                    case Ch('<'):
+                        *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('>'): 
+                        *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('\''): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
+                        break;
+                    case Ch('"'): 
+                        *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
+                        break;
+                    case Ch('&'): 
+                        *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); 
+                        break;
+                    default:
+                        *out++ = *begin;    // No expansion, copy character
+                    }
+                }
+                ++begin;    // Step to next character
+            }
+            return out;
+        }
+
+        // Fill given output iterator with repetitions of the same character
+        template<class OutIt, class Ch>
+        inline OutIt fill_chars(OutIt out, int n, Ch ch)
+        {
+            for (int i = 0; i < n; ++i)
+                *out++ = ch;
+            return out;
+        }
+
+        // Find character
+        template<class Ch, Ch ch>
+        inline bool find_char(const Ch *begin, const Ch *end)
+        {
+            while (begin != end)
+                if (*begin++ == ch)
+                    return true;
+            return false;
+        }
+
+        template<class OutIt, class Ch>
+        inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
+
+        // Print children of the node                               
+        template<class OutIt, class Ch>
+        inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
+                out = print_node(out, child, flags, indent);
+            return out;
+        }
+
+        // Print attributes of the node
+        template<class OutIt, class Ch>
+        inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
+        {
+            for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
+            {
+                if (attribute->name() && attribute->value())
+                {
+                    // Print attribute name
+                    *out = Ch(' '), ++out;
+                    out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
+                    *out = Ch('='), ++out;
+                    // Print attribute value using appropriate quote type
+                    if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
+                    {
+                        *out = Ch('\''), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
+                        *out = Ch('\''), ++out;
+                    }
+                    else
+                    {
+                        *out = Ch('"'), ++out;
+                        out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
+                        *out = Ch('"'), ++out;
+                    }
+                }
+            }
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_data);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+            return out;
+        }
+
+        // Print data node
+        template<class OutIt, class Ch>
+        inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_cdata);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'); ++out;
+            *out = Ch('!'); ++out;
+            *out = Ch('['); ++out;
+            *out = Ch('C'); ++out;
+            *out = Ch('D'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('T'); ++out;
+            *out = Ch('A'); ++out;
+            *out = Ch('['); ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch(']'); ++out;
+            *out = Ch(']'); ++out;
+            *out = Ch('>'); ++out;
+            return out;
+        }
+
+        // Print element node
+        template<class OutIt, class Ch>
+        inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_element);
+
+            // Print element name and attributes, if any
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            out = print_attributes(out, node, flags);
+            
+            // If node is childless
+            if (node->value_size() == 0 && !node->first_node())
+            {
+                // Print childless node tag ending
+                *out = Ch('/'), ++out;
+                *out = Ch('>'), ++out;
+            }
+            else
+            {
+                // Print normal node tag ending
+                *out = Ch('>'), ++out;
+
+                // Test if node contains a single data node only (and no other nodes)
+                xml_node<Ch> *child = node->first_node();
+                if (!child)
+                {
+                    // If node has no children, only print its value without indenting
+                    out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
+                }
+                else if (child->next_sibling() == 0 && child->type() == node_data)
+                {
+                    // If node has a sole data child, only print its value without indenting
+                    out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
+                }
+                else
+                {
+                    // Print all children with full indenting
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+                    out = print_children(out, node, flags, indent + 1);
+                    if (!(flags & print_no_indenting))
+                        out = fill_chars(out, indent, Ch('\t'));
+                }
+
+                // Print node end
+                *out = Ch('<'), ++out;
+                *out = Ch('/'), ++out;
+                out = copy_chars(node->name(), node->name() + node->name_size(), out);
+                *out = Ch('>'), ++out;
+            }
+            return out;
+        }
+
+        // Print declaration node
+        template<class OutIt, class Ch>
+        inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            // Print declaration start
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            *out = Ch('x'), ++out;
+            *out = Ch('m'), ++out;
+            *out = Ch('l'), ++out;
+
+            // Print attributes
+            out = print_attributes(out, node, flags);
+            
+            // Print declaration end
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            
+            return out;
+        }
+
+        // Print comment node
+        template<class OutIt, class Ch>
+        inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_comment);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('-'), ++out;
+            *out = Ch('-'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print doctype node
+        template<class OutIt, class Ch>
+        inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_doctype);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('!'), ++out;
+            *out = Ch('D'), ++out;
+            *out = Ch('O'), ++out;
+            *out = Ch('C'), ++out;
+            *out = Ch('T'), ++out;
+            *out = Ch('Y'), ++out;
+            *out = Ch('P'), ++out;
+            *out = Ch('E'), ++out;
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('>'), ++out;
+            return out;
+        }
+
+        // Print pi node
+        template<class OutIt, class Ch>
+        inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+        {
+            assert(node->type() == node_pi);
+            if (!(flags & print_no_indenting))
+                out = fill_chars(out, indent, Ch('\t'));
+            *out = Ch('<'), ++out;
+            *out = Ch('?'), ++out;
+            out = copy_chars(node->name(), node->name() + node->name_size(), out);
+            *out = Ch(' '), ++out;
+            out = copy_chars(node->value(), node->value() + node->value_size(), out);
+            *out = Ch('?'), ++out;
+            *out = Ch('>'), ++out;
+            return out;
+        }
+        ///////////////////////////////////////////////////////////////////////////
+                // Internal printing operations
+
+                // Print node
+                template<class OutIt, class Ch>
+                inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
+                {
+                    // Print proper node type
+                    switch (node->type())
+                    {
+
+                    // Document
+                    case node_document:
+                        out = print_children(out, node, flags, indent);
+                        break;
+
+                    // Element
+                    case node_element:
+                        out = print_element_node(out, node, flags, indent);
+                        break;
+
+                    // Data
+                    case node_data:
+                        out = print_data_node(out, node, flags, indent);
+                        break;
+
+                    // CDATA
+                    case node_cdata:
+                        out = print_cdata_node(out, node, flags, indent);
+                        break;
+
+                    // Declaration
+                    case node_declaration:
+                        out = print_declaration_node(out, node, flags, indent);
+                        break;
+
+                    // Comment
+                    case node_comment:
+                        out = print_comment_node(out, node, flags, indent);
+                        break;
+
+                    // Doctype
+                    case node_doctype:
+                        out = print_doctype_node(out, node, flags, indent);
+                        break;
+
+                    // Pi
+                    case node_pi:
+                        out = print_pi_node(out, node, flags, indent);
+                        break;
+
+                        // Unknown
+                    default:
+                        assert(0);
+                        break;
+                    }
+
+                    // If indenting not disabled, add line break after node
+                    if (!(flags & print_no_indenting))
+                        *out = Ch('\n'), ++out;
+
+                    // Return modified iterator
+                    return out;
+                }
+    }
+    //! \endcond
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Printing
+
+    //! Prints XML to given output iterator.
+    //! \param out Output iterator to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output iterator pointing to position immediately after last character of printed text.
+    template<class OutIt, class Ch> 
+    inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
+    {
+        return internal::print_node(out, &node, flags, 0);
+    }
+
+#ifndef RAPIDXML_NO_STREAMS
+
+    //! Prints XML to given output stream.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed. Pass xml_document to print entire document.
+    //! \param flags Flags controlling how XML is printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
+    {
+        print(std::ostream_iterator<Ch>(out), node, flags);
+        return out;
+    }
+
+    //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
+    //! \param out Output stream to print to.
+    //! \param node Node to be printed.
+    //! \return Output stream.
+    template<class Ch> 
+    inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
+    {
+        return print(out, node);
+    }
+
+#endif
+
+}
+
+#endif
diff --git a/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp b/service/protocol-plugin/lib/rapidxml/rapidxml_utils.hpp
new file mode 100644 (file)
index 0000000..37c2953
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef RAPIDXML_UTILS_HPP_INCLUDED
+#define RAPIDXML_UTILS_HPP_INCLUDED
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
+//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <fstream>
+#include <stdexcept>
+
+namespace rapidxml
+{
+
+    //! Represents data loaded from a file
+    template<class Ch = char>
+    class file
+    {
+        
+    public:
+        
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor.
+        //! \param filename Filename to load.
+        file(const char *filename)
+        {
+            using namespace std;
+
+            // Open stream
+            basic_ifstream<Ch> stream(filename, ios::binary);
+            if (!stream)
+                throw runtime_error(string("cannot open file ") + filename);
+            stream.unsetf(ios::skipws);
+            
+            // Determine stream size
+            stream.seekg(0, ios::end);
+            size_t size = stream.tellg();
+            stream.seekg(0);   
+            
+            // Load data and add terminating 0
+            m_data.resize(size + 1);
+            stream.read(&m_data.front(), static_cast<streamsize>(size));
+            m_data[size] = 0;
+        }
+
+        //! Loads file into the memory. Data will be automatically destroyed by the destructor
+        //! \param stream Stream to load from
+        file(std::basic_istream<Ch> &stream)
+        {
+            using namespace std;
+
+            // Load data and add terminating 0
+            stream.unsetf(ios::skipws);
+            m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
+            if (stream.fail() || stream.bad())
+                throw runtime_error("error reading stream");
+            m_data.push_back(0);
+        }
+        
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        Ch *data()
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data.
+        //! \return Pointer to data of file.
+        const Ch *data() const
+        {
+            return &m_data.front();
+        }
+
+        //! Gets file data size.
+        //! \return Size of file data, in characters.
+        std::size_t size() const
+        {
+            return m_data.size();
+        }
+
+    private:
+
+        std::vector<Ch> m_data;   // File data
+
+    };
+
+    //! Counts children of node. Time complexity is O(n).
+    //! \return Number of children of node
+    template<class Ch>
+    inline std::size_t count_children(xml_node<Ch> *node)
+    {
+        xml_node<Ch> *child = node->first_node();
+        std::size_t count = 0;
+        while (child)
+        {
+            ++count;
+            child = child->next_sibling();
+        }
+        return count;
+    }
+
+    //! Counts attributes of node. Time complexity is O(n).
+    //! \return Number of attributes of node
+    template<class Ch>
+    inline std::size_t count_attributes(xml_node<Ch> *node)
+    {
+        xml_attribute<Ch> *attr = node->first_attribute();
+        std::size_t count = 0;
+        while (attr)
+        {
+            ++count;
+            attr = attr->next_attribute();
+        }
+        return count;
+    }
+
+}
+
+#endif
index f6187f4..453451f 100644 (file)
@@ -1,12 +1,13 @@
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall
-
-CPLUFF_DIR = ../../../lib/cpluff/libcpluff
+LIB = ../../../lib
+CPLUFF_DIR = $(LIB)/cpluff/libcpluff
 
 SRC = ../../src/
 
 CXX_INC    = -I. -I$(CPLUFF_DIR)
+CXX_INC += -I$(LIB)/rapidxml 
 
 LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
 CXX_LIBS = $(CPLUFF_DIR)/.libs/libcpluff.a 
@@ -22,8 +23,8 @@ PluginManager.o : $(SRC)PluginManager.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManager.cpp 
 
 
-libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CPLUFF_DIR)/.libs/libcpluff.a 
-       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o $(CXX_LIBS) $(LINK_LIB)  
+libpmimpl.so:PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CPLUFF_DIR)/.libs/libcpluff.a 
+       $(CXX) -shared -o libpmimpl.so PluginManagerImpl.o Plugin.o CpluffAdapter.o FelixAdapter.o Config.o $(CXX_LIBS) $(LINK_LIB)  
 
 PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(CXX_FLAGS) -Wsign-compare $(SRC)PluginManagerImpl.cpp
@@ -31,6 +32,9 @@ PluginManagerImpl.o : $(SRC)PluginManagerImpl.cpp
 Plugin.o : $(SRC)Plugin.cpp
        $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Plugin.cpp
 
+Config.o : $(SRC)Config.cpp
+       $(CXX) $(CXX_INC)  -fPIC  -c $(SRC)Config.cpp
+
 CpluffAdapter.o  : $(SRC)CpluffAdapter.cpp
        $(CXX) $(CXX_INC) -c $(CXX_FLAGS) -Wsign-compare $(SRC)CpluffAdapter.cpp
 
diff --git a/service/protocol-plugin/plugin-manager/src/Config.cpp b/service/protocol-plugin/plugin-manager/src/Config.cpp
new file mode 100644 (file)
index 0000000..528c7dd
--- /dev/null
@@ -0,0 +1,157 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.cpp
+
+/// @brief
+
+
+#include "Config.h"
+
+
+using namespace OIC;
+using namespace rapidxml;
+using namespace std;
+
+Config *Config::s_configinstance = NULL;
+
+Config::Config()
+{
+    if (loadConfigFile("./pluginmanager.xml") != PM_S_OK)
+    {
+        fprintf(stderr, "PM Configuration file is not exist current Folder.\n" );
+        exit(EXIT_FAILURE);
+    }
+}
+
+Config::~Config(void)
+{
+    s_configinstance->deleteinstance();
+    s_configinstance = NULL;
+}
+
+PMRESULT Config::loadConfigFile(const std::string configfilepath)
+{
+    // Read the xml file
+    std::ifstream xmlFile(configfilepath.c_str());
+    xml_document<> doc;
+    //into a vector
+    std::vector<char> buffer((istreambuf_iterator<char>(xmlFile)), istreambuf_iterator<char>());
+    buffer.push_back('\0');
+
+    // Parse the buffer using the xml file parsing library into doc
+    parsing(buffer, &doc);
+
+    // Find our root node
+    xml_node<> *root_node = doc.first_node("pluginManager");
+    xml_node<> *pluginInfo = root_node->first_node("pluginInfo");
+
+    getXmlData(pluginInfo, "pluginPath");
+    getXmlData(pluginInfo, "maxMEM");
+    getXmlData(pluginInfo, "version");
+    getXmlData(pluginInfo, "name");
+
+    return PM_S_OK;
+}
+
+PMRESULT Config::parsing(std::vector<char> buffer, xml_document<> *doc)
+{
+    // Parse the buffer using the xml file parsing library into doc
+    try
+    {
+        doc->parse<0>(&buffer[0]);
+    }
+    catch (rapidxml::parse_error err)
+    {
+        //print errors to screen
+        fprintf(stderr, "PM Configuration file parsing error \n");
+        exit(EXIT_FAILURE); //then exit
+    }
+    return PM_S_OK;
+}
+
+PMRESULT Config::getXmlData(xml_node<> *pluginInfo, std::string key)
+{
+    xml_attribute<> *iAttr = NULL;
+    std::string value  = "";
+    if (iAttr = pluginInfo->first_attribute(key.c_str()))
+    {
+        value = iAttr->value();
+        setValue(key, value);
+        return PM_S_OK;
+    }
+    else
+    {
+        return PM_S_FALSE;
+    }
+}
+
+void Config::setValue(const std::string key, const std::string value)
+{
+    m_configurationMap.insert( std::pair<std::string, std::string>(key, value));
+}
+
+std::string  Config::getValue(const std::string key)
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find(key.c_str());
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getVersion()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("version");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
+
+std::string  Config::getPluginPath()
+{
+    std::map<std::string, std::string>::iterator m_iterator;
+
+    m_iterator = m_configurationMap.find("pluginPath");
+
+    if (m_iterator != m_configurationMap.end())
+    {
+        return m_iterator->second;
+    }
+    else
+    {
+        return "";
+    }
+}
\ No newline at end of file
diff --git a/service/protocol-plugin/plugin-manager/src/Config.h b/service/protocol-plugin/plugin-manager/src/Config.h
new file mode 100644 (file)
index 0000000..33f7f39
--- /dev/null
@@ -0,0 +1,122 @@
+//******************************************************************
+//
+// Copyright 2014 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file Config.h
+
+/// @brief
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+#include <map>
+#include <string>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rapidxml.hpp"
+#include <fstream>
+#include <vector>
+
+using namespace rapidxml;
+
+namespace OIC
+{
+
+    enum PMRESULT
+    {
+        PM_S_OK
+        , PM_S_FALSE
+        , PM_E_POINTER
+        , PM_E_OUTOFMEMORY
+        , PM_E_FAIL
+        , PM_E_NOINTERFACE
+        , PM_E_NOTIMPL
+    };
+    /**
+    * @brief    Configuration class
+    *
+    *
+    */
+    class Config
+    {
+        public:
+            /**
+            * A function to register pluins in the path.
+            * This function will load plugins in plugin manager table.
+            *
+            * @param path plugin file path to be registered.
+            * @return int, 1 is success, 0 is fail.
+            *
+            * NOTE:
+            *
+            */
+            /**
+            *
+            * new Singleton pattern instance.
+            *
+            * @return config pointer Address.
+            */
+            static Config *Getinstance()
+            {
+                if (NULL == s_configinstance)
+                {
+                    s_configinstance = new Config();
+                }
+
+                return s_configinstance;
+            }
+            std::string  getPluginPath();
+            std::string  getVersion();
+            std::string  getValue(const std::string key);
+
+        private:
+            static Config *s_configinstance;
+            typedef std::map<std::string, std::string> configmap;
+            configmap m_configurationMap;
+            /**
+            * Constructor for Config.
+            * During construction time, configuration file  will be loaded.
+            *
+            */
+            Config();
+
+            /**
+            * Virtual destructor
+            */
+            virtual ~Config(void);
+
+            /**
+            * delete Singleton pattern instance.
+            */
+            static void deleteinstance()
+            {
+                if (NULL != s_configinstance)
+                {
+                    delete s_configinstance;
+                    s_configinstance = NULL;
+                }
+            }
+            void setValue(const std::string key, const std::string value);
+            PMRESULT loadConfigFile(const std::string configfilepath);
+            PMRESULT parsing(std::vector<char> buffer, xml_document<> *doc);
+            PMRESULT getXmlData(  xml_node<> *pluginInfo, std::string key);
+    };
+}
+
+#endif
\ No newline at end of file
index b3d60e4..addc2a7 100644 (file)
@@ -34,14 +34,27 @@ CpluffAdapter::CpluffAdapter()
     m_context = cp_create_context(&m_status);
     m_cp_plugins = nullptr;
     m_plugin = nullptr;
-    registerAllPlugin("../../../plugins");
+
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 CpluffAdapter::~CpluffAdapter(void)
 {
     cp_release_info(m_context, m_cp_plugins);
-    m_thread_g.interrupt_all();
-    m_thread_g.join_all();
+    //Auto plugin detection is disabled
+    //m_thread_g.interrupt_all();
+    //m_thread_g.join_all();
     s_pinstance->deleteinstance();
     s_pinstance = nullptr;
 }
@@ -57,7 +70,12 @@ int CpluffAdapter::installPlugin(const std::string path)
     }
     else if ((m_status = cp_install_plugin(m_context, m_plugin)) != 0)
     {
-        printf("cp_install_plugin failed\n");
+        if (m_status == CP_ERR_CONFLICT)
+        {
+            printf("Plugin is already installed or conflicts symbol.\n");
+        }
+        printf("cp_install_plugin failed : %d \n" , m_status);
+
         return false;
     }
 
@@ -70,8 +88,7 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
     File_list file_list;
     getFileList(file_list, path);
     File_list::iterator itr;
-    int flag = FALSE;
-
+    int flag = TRUE;
     for (itr = file_list.begin(); itr != file_list.end(); itr++)
     {
         if (itr->second == true)
@@ -91,9 +108,10 @@ int CpluffAdapter::findPluginRecursive(const std::string path)
                 }
             }
             std::string filename = filepath.substr(0, count );
-            //char *temp_char = const_cast<char *>(filename.c_str());
-            flag = installPlugin(filename);
-            //printf("plugin file path %s \n", plugin->plugin_path);
+            if (!installPlugin(filename))
+            {
+                printf("installPlugin failed path : %s \n", filename.c_str());
+            }
         }
     }
 
@@ -110,7 +128,7 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
     }
     else
     {
-        printPluginList(m_cp_plugins);
+        printPluginList();
     }
 
     for (int i = 0 ; m_cp_plugins[i] != nullptr; i++)
@@ -176,7 +194,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
         }
         if (plugin_compare_flag)
         {
-            m_plugins.push_back(*plugin);
+            //Auto plugin detection is disabled
+            /*
             try
             {
                 boost::thread *t = new boost::thread(boost::bind(&CpluffAdapter::observePluginPath,
@@ -188,6 +207,8 @@ int CpluffAdapter::loadPluginInfoToManager(const std::string path)
             {
                 printf("thread throw exception\n");
             }
+            */
+            m_plugins.push_back(*plugin);
             delete(plugin);
         }
         //printf("plugin size = %d\n",m_plugins.size());
@@ -208,11 +229,10 @@ int CpluffAdapter::registerPlugin(const std::string path)
     }
 
     //non recursive
-
-    flag = installPlugin(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (installPlugin(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -227,11 +247,10 @@ int CpluffAdapter::registerAllPlugin(const std::string path)
     }
 
     //recursive
-
-    flag = findPluginRecursive(path);
-
-    flag = loadPluginInfoToManager(path);
-
+    if (findPluginRecursive(path))
+    {
+        flag = loadPluginInfoToManager(path);
+    }
     return flag;
 }
 
@@ -403,7 +422,7 @@ const char *CpluffAdapter::state_to_string(int state)
     }
 }
 
-void CpluffAdapter::printPluginList(cp_plugin_info_t **plugins)
+void CpluffAdapter::printPluginList()
 {
     const char format[] = "  %-30s %-15s %-15s %-20s\n";
     printf("\n====== Plugins List ======\n");
@@ -491,7 +510,8 @@ bool CpluffAdapter::isStarted(Plugin *plugin)
     }
     return FALSE;
 }
-
+//Auto plugin detection is disabled
+/*
 void CpluffAdapter::observePluginPath(void *str)
 {
     //printf("start observePluginPath\n");
@@ -568,7 +588,7 @@ void CpluffAdapter::observePluginPath(void *str)
     ( void ) close( fd );
     //printf("observePluginPath end\n");
 }
-
+*/
 const std::string CpluffAdapter::getState(const std::string plugID)
 {
     return state_to_string(cp_get_plugin_state(m_context, plugID.c_str()));
index ec565d3..e0b934f 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -160,6 +161,13 @@ namespace OIC
             */
             const std::string getState(const std::string plugID);
 
+            /**
+            * print whole plugin info.
+            *
+            * @param cpluff plugins
+            */
+            void printPluginList();
+
 
             /**
             *
@@ -181,15 +189,14 @@ namespace OIC
 
         private:
 
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             cp_context_t *m_context;
             cp_status_t m_status;
             cp_plugin_info_t **m_cp_plugins;
             cp_plugin_info_t *m_plugin;
-            boost::thread m_file_detect_thread;
-            boost::thread_group m_thread_g;
-            std::string m_path;
+            //boost::thread_group m_thread_g;
             static CpluffAdapter *s_pinstance;
 
             /**
@@ -222,7 +229,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
 
             /**
@@ -243,13 +250,6 @@ namespace OIC
             bool getFileList(File_list &list, const std::string strDir);
 
             /**
-            * print whole plugin info.
-            *
-            * @param cpluff plugins
-            */
-            void printPluginList(cp_plugin_info_t **plugins);
-
-            /**
             * install plugin using c-pluff.
             *
             * @param Root path.
index 0247e74..50a92e2 100644 (file)
@@ -30,7 +30,18 @@ FelixAdapter *FelixAdapter::s_pinstance;
 
 FelixAdapter::FelixAdapter()
 {
-
+    config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path is not exist\n");
+        pluginpath = "";
+    }
+    registerAllPlugin(pluginpath);
 }
 
 FelixAdapter::~FelixAdapter(void)
@@ -113,12 +124,12 @@ bool FelixAdapter::isStarted(Plugin *plugin)
 {
     return FALSE;
 }
-
+/*
 void FelixAdapter::observePluginPath(void *str)
 {
 
 }
-
+*/
 const std::string FelixAdapter::getState(const std::string plugID)
 {
     return "";
index 3842184..7c6398c 100644 (file)
@@ -38,6 +38,7 @@
 #include <internal.h>
 
 #include "Plugin.h"
+#include "Config.h"
 
 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
 #define BUF_LEN     (int)( 1024 * ( EVENT_SIZE + 16 ) )
@@ -180,7 +181,7 @@ namespace OIC
 
 
         private:
-
+            Config *config;
             typedef std::map<std::string, bool> File_list;
             std::vector<Plugin> m_plugins;
             boost::thread m_file_detect_thread;
@@ -224,7 +225,7 @@ namespace OIC
             * @param plugin file path.
             * @return void
             */
-            void observePluginPath(void *);
+            //void observePluginPath(void *);
 
             /**
             * Get whole "SO" file list.
index d77f68f..7ef312c 100644 (file)
@@ -136,16 +136,6 @@ namespace OIC
             return false;
         }
     }
-
-    std::vector<std::string> Plugin::getSupportedType(void)
-    {
-        return m_supportedType;
-    }
-
-    void Plugin::addSupportedType(const std::string rscType)
-    {
-        m_supportedType.push_back(rscType);
-    }
 }
 
 
index bd823d8..5b1e3a6 100644 (file)
@@ -141,22 +141,6 @@ namespace OIC
             */
             bool operator==(Plugin &plugin);
 
-            /**
-            * Get supported resourc type
-            *
-            *
-            * @return vector of surported resource type
-            */
-            std::vector<std::string> getSupportedType(void);
-            /**
-            * Add supported resource type for a plugin
-            *
-            * @param resource type string
-            * @return void
-            *
-            */
-            void addSupportedType(const std::string rscType);
-
         private:
             std::map<std::string, AttributeValue> m_attributeMap;
             std::vector<std::string> m_supportedType;
index 7c158ca..c3abdb8 100644 (file)
@@ -56,18 +56,17 @@ int PluginManager::stopPlugins(const std::string key, const std::string value)
     return pluginManagerImpl->stopPlugins(key, value);
 }
 
-int PluginManager::startPlugins(Plugin *const plugin)
+int PluginManager::rescanPlugin()
 {
-    printf("PluginManager::startPlugins\n");
-    return pluginManagerImpl->startPlugins(plugin);
+    return pluginManagerImpl->rescanPlugin();
 }
 
-int PluginManager::stopPlugins(Plugin *const plugin)
+std::vector<Plugin> PluginManager::getPlugins(void)
 {
-    return pluginManagerImpl->stopPlugins(plugin);
+    return pluginManagerImpl->getAllPlugins();
 }
 
-std::vector<Plugin> PluginManager::getPlugins(void)
+std::string PluginManager::getState(const std::string plugID)
 {
-    return pluginManagerImpl->getAllPlugins();
+    return pluginManagerImpl->getState(plugID);
 }
\ No newline at end of file
index 41a631e..2ae8b73 100644 (file)
@@ -68,23 +68,13 @@ namespace OIC
             int stopPlugins(const std::string key, const std::string value);
 
             /**
-            * Start plugin
-            * This function will load dynamic plugin library on memory and call start function of plugin to be initialized.
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
             *
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            int startPlugins(Plugin *const plugin);
-
-
-            /**
-            * Stop Plugin.
-            * This function will call stop function of plugin and unload dynamic plugin library from memory.
-            *
-            * @param Plugin
-            * @return int, 1 is success, 0 is fail.
-            */
-            int stopPlugins(Plugin *const plugin);
+            int rescanPlugin();
 
             /**
             * Get Plugin list.
@@ -95,6 +85,14 @@ namespace OIC
             */
             std::vector<Plugin> getPlugins(void);
 
+            /**
+            * Get Plugin state.
+            *
+            * @param Plugin ID
+            * @return Plugin state.
+            */
+            std::string getState(const std::string plugID);
+
         private:
             PluginManagerImpl *pluginManagerImpl;
             void (*destroy)(PluginManagerImpl *);
index d501786..2795e83 100644 (file)
@@ -110,6 +110,23 @@ int PluginManagerImpl::unregisterAllPlugin()
     return flag;
 }
 
+int PluginManagerImpl::rescanPlugin()
+{
+    Config *config = Config::Getinstance();
+    std::string pluginpath = config->getPluginPath();
+    if (pluginpath != "")
+    {
+        printf("Current path is %s\n", pluginpath.c_str());
+    }
+    else
+    {
+        fprintf(stderr, "Pluing path does not exist\n");
+        pluginpath = "";
+    }
+    int result = registerAllPlugin(pluginpath);
+    return result;
+}
+
 
 std::vector<Plugin> &PluginManagerImpl::getAllPlugins(void)
 {
index f42236a..3beb8e8 100644 (file)
@@ -120,7 +120,7 @@ namespace OIC
             * @param Plugin ID
             * @return Plugin state.
             */
-            std::string getState(const std::string plugID);
+            virtual std::string getState(const std::string plugID);
 
             /**
             * Start  plugins by resource type
@@ -145,7 +145,7 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int startPlugins(Plugin *const plugin);
+            int startPlugins(Plugin *const plugin);
 
 
             /**
@@ -155,7 +155,16 @@ namespace OIC
             * @param Plugin
             * @return int, 1 is success, 0 is fail.
             */
-            virtual int stopPlugins(Plugin *const plugin);
+            int stopPlugins(Plugin *const plugin);
+
+            /**
+            * Rescan Plugin.
+            * This function will call rescan function of plugins in the configuration folder
+            *
+            * @param Plugin
+            * @return int, 1 is success, 0 is fail.
+            */
+            virtual int rescanPlugin();
 
             /**
             * get all plugins which currently registered.
index bf4db27..9f258f1 100644 (file)
@@ -1,5 +1,3 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
@@ -8,6 +6,9 @@ LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,6 +18,8 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
 CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
index 544679a..12111e0 100644 (file)
@@ -45,23 +45,22 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeFanRepresentation (void *param);
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'fanResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
-// void entityHandler(std::shared_ptr<OCResourceRequest> request,
-//                    std::shared_ptr<OCResourceResponse> response);
-
 /// This class represents a single resource named 'fanResource'. This resource has
 /// two simple properties named 'state' and 'power'
 typedef struct plugin_data_t plugin_data_t;
@@ -114,7 +113,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -136,7 +135,7 @@ class FanResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&FanResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -251,13 +250,10 @@ class FanResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -272,40 +268,52 @@ class FanResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request === Handle by FanServer\n";
+                    cout << "\t\trequestFlag : Request   ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the fanResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -314,26 +322,19 @@ class FanResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -370,6 +371,7 @@ class FanResource
                         pthread_create (&threadId, NULL, ChangeFanRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -377,7 +379,7 @@ class FanResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -436,34 +438,36 @@ void *ChangeFanRepresentation (void *param)
     return NULL;
 }
 
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    FanResource *fanPtr = (FanResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(fanPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
 
 //int start_fanserver(void*)                // 1
 void *start_fanserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_fanserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myFanResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class fan.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myFanResource.createResource();
-        //myFanResource.addType(std::string("core.fan"));
-        //myFanResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 9b2aca2..026b3a9 100644 (file)
@@ -1,5 +1,3 @@
-include ../../../../config.mk
-
 CXX = g++
 
 CXX_FLAGS = -std=c++0x -Wall -pthread
@@ -8,6 +6,9 @@ LIB_DIR = ../../../../../../resource
 
 SRC_DIR = ../../src
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -17,6 +18,8 @@ CXX_INC += -I$(LIB_DIR)/csdk/logger/include/
 CXX_INC += -I$(BOOST_DIR) 
 CXX_INC += -I../../lib 
 CXX_INC += -I../../../../lib/cpluff/libcpluff
+CXX_INC          += -I../csdk/libcoap
+CXX_INC   += -I$(CEREAL_DIR)/include
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
 CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../../lib/cpluff/libcpluff/.libs/libcpluff.a
index 93bad63..9f30718 100644 (file)
@@ -43,18 +43,19 @@ struct tm *tblock;           // Define a structure for time block
 
 int gObservation = 0;
 void *ChangeLightRepresentation (void *param);
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
 // Specifies where to notify all observers or list of observers
-// 0 - notifies all observers
-// 1 - notifies list of observers
-int isListOfObservers = 0;
-
-// Forward declaring the entityHandler
-
-/// This class represents a single resource named 'lightResource'. This resource has
-/// two simple properties named 'state' and 'power'
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
 
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
 
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
 
 // Forward declaring the entityHandler
 // void entityHandler(std::shared_ptr<OCResourceRequest> request,
@@ -112,7 +113,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             // This will internally create and register the resource.
             OCStackResult result = OCPlatform::registerResource(
@@ -134,7 +135,7 @@ class LightResource
             // OCResourceProperty is defined ocstack.h
             uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
-            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1, PH::_2);
+            EntityHandler cb = std::bind(&LightResource::entityHandler, this, PH::_1);
 
             OCResourceHandle resHandle;
 
@@ -249,13 +250,10 @@ class LightResource
     private:
         // This is just a sample implementation of entity handler.
         // Entity handler can be implemented in several ways by the manufacturer
-        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request,
-                                            std::shared_ptr<OCResourceResponse> response)
+        OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
         {
-            OCEntityHandlerResult result = OC_EH_OK;
-
             cout << "\tIn Server CPP entity handler:\n";
-
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
             if (request)
             {
                 // Get the request type and request flag
@@ -270,40 +268,52 @@ class LightResource
                 }
                 if (requestFlag & RequestHandlerFlag::RequestFlag)
                 {
-                    cout << "\t\trequestFlag : Request ===  Handle by LightServer\n";
+                    cout << "\t\trequestFlag : Request ===  Handle by FanServer\n";
+                    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+                    pResponse->setRequestHandle(request->getRequestHandle());
+                    pResponse->setResourceHandle(request->getResourceHandle());
 
                     // If the request type is GET
                     if (requestType == "GET")
                     {
                         cout << "\t\t\trequestType : GET\n";
-
-                        if (response)
+                        if (isSlowResponse) // Slow response case
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            static int startedThread = 0;
+                            if (!startedThread)
+                            {
+                                std::thread t(handleSlowResponse, (void *)this, request);
+                                startedThread = 1;
+                                t.detach();
+                            }
+                            ehResult = OC_EH_SLOW;
+                        }
+                        else // normal response case.
+                        {
+                            pResponse->setErrorCode(200);
+                            pResponse->setResponseResult(OC_EH_OK);
+                            pResponse->setResourceRepresentation(get());
+                            if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                            {
+                                ehResult = OC_EH_OK;
+                            }
                         }
                     }
                     else if (requestType == "PUT")
                     {
                         cout << "\t\t\trequestType : PUT\n";
-
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to PUT request
-
                         // Update the lightResource
                         put(rep);
-
-                        if (response)
+                        pResponse->setErrorCode(200);
+                        pResponse->setResponseResult(OC_EH_OK);
+                        pResponse->setResourceRepresentation(get());
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(get());
+                            ehResult = OC_EH_OK;
                         }
-
                     }
                     else if (requestType == "POST")
                     {
@@ -312,26 +322,19 @@ class LightResource
                         OCRepresentation rep = request->getResourceRepresentation();
 
                         // Do related operations related to POST request
-
                         OCRepresentation rep_post = post(rep);
-
-                        if (response)
+                        pResponse->setResourceRepresentation(rep_post);
+                        pResponse->setErrorCode(200);
+                        if (rep_post.hasAttribute("createduri"))
                         {
-                            // TODO Error Code
-                            response->setErrorCode(200);
-
-                            response->setResourceRepresentation(rep_post);
-
-                            if (rep_post.hasAttribute("createduri"))
-                            {
-                                result = OC_EH_RESOURCE_CREATED;
-
-                                response->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
-                            }
-
+                            pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                            pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
                         }
 
-                        // POST request operations
+                        if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
                     }
                     else if (requestType == "DELETE")
                     {
@@ -368,6 +371,7 @@ class LightResource
                         pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
                         startedThread = 1;
                     }
+                    ehResult = OC_EH_OK;
                 }
             }
             else
@@ -375,7 +379,7 @@ class LightResource
                 std::cout << "Request invalid" << std::endl;
             }
 
-            return result;
+            return ehResult;
         }
 };
 
@@ -434,36 +438,36 @@ void *ChangeLightRepresentation (void *param)
     return NULL;
 }
 
-
+void *handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    LightResource *lightPtr = (LightResource *) param;
+    // Induce a case for slow response by using sleep
+    std::cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(lightPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
 
 
 //int start_lightserver(void*)                // 1
 void *start_lightserver(void *d)      // 2
 {
-    /*PlatformConfig cfg;
-    cfg.ipAddress = "192.168.2.5";
-    cfg.port = 56832;
-    cfg.mode = ModeType::Server;
-    cfg.serviceType = ServiceType::InProc;*/
-    // PlatformConfig cfg
-    // {
-    //     OC::ServiceType::InProc,
-    //     OC::ModeType::Server,
-    //     "192.168.2.5",
-    //     56832,
-    //     OC::QualityOfService::NonConfirmable
-    // };
-
-    // Create PlatformConfig object
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-
     // Create PlatformConfig object
     PlatformConfig cfg
     {
         OC::ServiceType::InProc,
-        OC::ModeType::Server,
+        OC::ModeType::Both,
         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
         0,         // Uses randomly available port
         OC::QualityOfService::LowQos
@@ -487,18 +491,9 @@ void *start_lightserver(void *d)      // 2
             printf("Mosquitto is working\n");
         }
 
-        //plugin_data_t *data = (plugin_data_t *)d;
-        //OCPlatform *platform = (OCPlatform*)data->str;
-        //myLightResource.m_platform = (OCPlatform*)data->str;
-        //OCPlatform platform(cfg);
-        // Invoke createResource function of class light.
-
-        //mosquitto_connect(myMosquitto, "192.168.2.5", 1883, 60);
         mosquitto_connect(myMosquitto, "127.0.0.1", 1883, 60);
         printf("Mosquitto Connection is done\n");
         myLightResource.createResource();
-        //myLightResource.addType(std::string("core.light"));
-        //myLightResource.addInterface(std::string("oc.mi.ll"));
         // Get time of day
         timer = time(NULL);
         // Converts date/time to a structure
index 935bc7e..351756b 100644 (file)
@@ -1,20 +1,75 @@
 
+This guide will help you setup your developing environment for Protocol plug-in Manager and Protocol plug-ins in Ubuntu. 
+
+1. Preparings
+Before starting, following tools should be installed. 
+
+Automake
+Automake is a tool for automatically generating Makefile.in files compiliant with the GNU Coding Standards. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+$ sudo apt-get install automake
+
+Libtool
+GNU libtool is a generic library support script. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install libtool
+
+gettext
+GNU `gettext' utilities are a set of tools that provides a framework to help other GNU packages produce multi-lingual messages. This tool is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install gettext
+
+Expat
+Expat is a stream-oriented XML parser library. This library is used for compiling C-Pluff open source which used in Plug-in Manager.
+       $ sudo apt-get install expat
+
+Building and Using Protocol Plug-in Manager
+
+Once the source code is downloaded into a specific folder, oic in this context, you may follow the steps to build and execute Protocol Plug-in Manager.
+The path for Protocol Plugin is as following;
+
+~/oic/oic-resource/service/protocol-plugin $_
+
+The Protocol Plug-in directory includes following sub directories;
+
+/plugin-manager        Directory for Plug-in Manager
+/plugins       Directory for Reference Plugins  
+/lib           Directory for Common Library
+/sample-app    Directory for Iotivity Sample Application
+/doc           Directory for Developers Document
+/build         Directory for Building and Binary Release
+
+
+2. Compiling C-Pluff library 
+Before building Protocol-Plugin Manager, C-Pluff library should be compiled as follows.
+
+~/oic/oic-service/protocol-plugin/lib/cpluff$ aclocal
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoconf
+~/oic/oic-service/protocol-plugin/lib/cpluff$ autoheader
+~/oic/oic-service/protocol-plugin/lib/cpluff$ automake
+~/oic/oic-service/protocol-plugin/lib/cpluff$ ./configure
+~/oic/oic-service/protocol-plugin/lib/cpluff$ make
+
+3. Run make
+By running make in the protocol-plugin path, protocol-plugin manager, all plugins and sample applications will be created. 
+NOTE: To build plugins in 64-bit Ubuntu Linux, OCLib.a and libcoap.a library should be re-compiled with ?fPIC option.
+~/oic/oic-service/protocol-plugin/build/linux$make
+
+
+4. Using Plugins 
 This version of protocol plug-in source code has following functionality.
 
-1. provides plug-in manager which can register, unregister, start and stop plug-in library.
-2. provides plug-in library which can communicate with MQTT protocol FAN.
-3. provides OIC Sample Client which can turn on/off FAN.
+1) provides plug-in manager which can start and stop plug-in library.
+2) provides plug-in library which can communicate with MQTT protocol Fan and Light.
+3) provides OIC Sample Client which can get info about Fan and Light with configuration file(pluginmanager.xml).
 
 So, to test a plug-in, follow below steps.
 
-1. Locate shared plug-in library and XML file in a specific folder.
-2. Register the plug-in with directory path input from plug-in manager sample.
-3. Start the plug-in from plug-in manager sample.
-4. Run OIC sample client.
-
-If you have any questions about protocol plug-in component, please contact with following addresses.
+1) Locate shared plug-in library and XML file in a specific folder.
+2) Register the plug-in with directory path input from plug-in manager sample.
+3) Start the plug-in from plug-in manager sample.
+4) Run OIC sample client.
+   ex)service/protocol-plugin/sample-app/linux/mqtt$./mqttclient
+  (mqtt broker is already installed in the local system.)
 
-kc7576.park@samsung.com
-heesung84.kim@samsung.com
-junho13.lee@samsung.com
-yh_.joo@samsung.com
\ No newline at end of file
@@ -4,6 +4,9 @@ CXX_FLAGS = -std=c++0x -Wall -pthread
 
 LIB_DIR = ../../../../../resource
 
+DEPEND_DIR:= $(LIB_DIR)/dependencies
+CEREAL_DIR:= $(DEPEND_DIR)/cereal
+
 CXX_INC := -I$(LIB_DIR)/include/ 
 CXX_INC += -I$(LIB_DIR)/oc_logger/include/ 
 CXX_INC += -I$(LIB_DIR)/csdk/stack/include/ 
@@ -14,22 +17,24 @@ CXX_INC += -I$(BOOST_DIR)
 CXX_INC += -I../../lib
 CXX_INC += -I../../../lib/cpluff/libcpluff
 CXX_INC += -I../../../plugin-manager/src
+CXX_INC   += -I$(CEREAL_DIR)/include
+CXX_INC += -I../../../lib/rapidxml 
 
 LIB_OC_LOGGER := $(LIB_DIR)/oc_logger/lib/oc_logger.a
 CXX_LIBS  := $(LIB_DIR)/release/obj/liboc.a $(LIB_DIR)/csdk/linux/release/liboctbstack.a $(LIB_OC_LOGGER) ../../../build/linux/release/libppm.a ../../../lib/cpluff/libcpluff/.libs/libcpluff.a
 LINK_LIB = -lboost_system -ldl -lexpat -lboost_thread 
 
-.PHONY: fanclient
+.PHONY: mqttclient
 
 all: .PHONY
 
-fanclient: fanclient.o
-       $(CXX) $(CXX_FLAGS) -o fanclient fanclient.o $(CXX_LIBS) $(LINK_LIB)
+mqttclient: mqttclient.o
+       $(CXX) $(CXX_FLAGS) -o mqttclient mqttclient.o $(CXX_LIBS) $(LINK_LIB)
 
-fanclient.o: fanclient.cpp
-       $(CXX) $(CXX_FLAGS) -c fanclient.cpp $(CXX_INC)
+mqttclient.o: mqttclient.cpp
+       $(CXX) $(CXX_FLAGS) -c mqttclient.cpp $(CXX_INC)
 
        
 clean:
        rm -f *.o
-       rm -f fanclient 
+       rm -f mqttclient
@@ -32,7 +32,8 @@
 using namespace OC;
 using namespace OIC;
 
-std::shared_ptr<OCResource> curResource;
+std::shared_ptr<OCResource> curFanResource;
+std::shared_ptr<OCResource> curLightResource;
 static ObserveType OBSERVE_TYPE_TO_USE = ObserveType::Observe;
 
 time_t timer;                // Define the timer
@@ -78,7 +79,7 @@ void onObserve(const HeaderOptions headerOptions, const OCRepresentation &rep,
         if (observe_count() > 30)
         {
             std::cout << "Cancelling Observe..." << std::endl;
-            OCStackResult result = curResource->cancelObserve();
+            OCStackResult result = curFanResource->cancelObserve();
 
             std::cout << "Cancel result: " << result << std::endl;
             sleep(10);
@@ -120,7 +121,7 @@ void onPost2(const HeaderOptions &headerOptions, const OCRepresentation &rep, co
         else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)
             std::cout << endl << "ObserveAll is used." << endl << endl;
 
-        curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
+        //curFanResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), &onObserve);
 
     }
     else
@@ -162,7 +163,7 @@ void onPost(const HeaderOptions &headerOptions, const OCRepresentation &rep, con
         rep2.setValue("state", myfan.m_state);
         rep2.setValue("power", myfan.m_power);
 
-        curResource->post(rep2, QueryParamsMap(), &onPost2);
+        curFanResource->post(rep2, QueryParamsMap(), &onPost2);
     }
     else
     {
@@ -206,7 +207,7 @@ void onPut(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        postFanRepresentation(curResource);
+        postFanRepresentation(curFanResource);
     }
     else
     {
@@ -251,7 +252,7 @@ void onGet(const HeaderOptions &headerOptions, const OCRepresentation &rep, cons
         std::cout << "\tpower: " << myfan.m_power << std::endl;
         std::cout << "\tname: " << myfan.m_name << std::endl;
 
-        putFanRepresentation(curResource);
+        putFanRepresentation(curFanResource);
     }
     else
     {
@@ -288,7 +289,7 @@ void getLightRepresentation(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceFan(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curFanResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -325,7 +326,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/fan")
             {
-                curResource = resource;
+                curFanResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getFanRepresentation(resource);
             }
@@ -346,7 +347,7 @@ void foundResourceFan(std::shared_ptr<OCResource> resource)
 // Callback to found resources
 void foundResourceLight(std::shared_ptr<OCResource> resource)
 {
-    if (curResource)
+    if (curLightResource)
     {
         std::cout << "Found another resource, ignoring" << std::endl;
     }
@@ -383,7 +384,7 @@ void foundResourceLight(std::shared_ptr<OCResource> resource)
 
             if (resourceURI == "/a/light")
             {
-                curResource = resource;
+                curLightResource = resource;
                 // Call a local function which will internally invoke get API on the resource pointer
                 getLightRepresentation(resource);
             }
@@ -425,7 +426,9 @@ void client1()
     std::cout << "Finding Fan Resource... time : " << asctime(tblock) << std::endl;
     while (1)
     {
-        // client1 related operations
+        std::cout << "Get Fan Resource....." << std::endl;
+        sleep(5);
+        getFanRepresentation(curFanResource);
     }
 }
 
@@ -449,7 +452,9 @@ void client2()
 
     while (1)
     {
-        // client2 related operations
+        std::cout << "Get Light Resource....." << std::endl;
+        sleep(5);
+        getLightRepresentation(curLightResource);
     }
 }
 
@@ -457,6 +462,11 @@ void client2()
 
 int main(int argc, char *argv[])
 {
+    std::string name;
+    std::string key = "Name";
+    std::string  state = "";
+    std::string  id = "";
+
     if (argc == 1)
     {
         OBSERVE_TYPE_TO_USE = ObserveType::Observe;
@@ -494,41 +504,83 @@ int main(int argc, char *argv[])
 
         std::cout << "Created Platform..." << std::endl;
 
-
         PluginManager *m_pm = new PluginManager();
 
+        std::cout << "==== 1st TEST CASE ===" << std::endl;
         std::cout << "======================" << std::endl;
-
         std::cout << "start light Plugin by Resource Type"  << std::endl;
+
         m_pm->startPlugins("ResourceType", "oic.light");
 
         sleep(2);
 
+        std::cout << "\n==== 2nd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "get Plugin List" << std::endl;
+        std::cout << "Get Plugin List\n" << std::endl;
         std::vector<Plugin> user_plugin;
+
         user_plugin = m_pm->getPlugins();
+
         for (unsigned int i = 0; i < user_plugin.size(); i++)
         {
-            printf("value Name = %s\n", user_plugin[i].getName().c_str());
-            printf("value ID = %s\n", user_plugin[i].getID().c_str());
+            std::cout << "value Name = " << user_plugin[i].getName() << std::endl;
+            std::cout << "value ID = " << user_plugin[i].getID() << std::endl;
+            id =  user_plugin[i].getID();
         }
-
+        std::cout << "\n===== 3rd TEST CASE =====" << std::endl;
         std::cout << "======================" << std::endl;
-        std::cout << "start Fan Plugin by Name" << std::endl;
-        m_pm->startPlugins("Name", "mqtt-fan");
+        std::cout << "Start Fan Plugin by Name\n" << std::endl;
+
+        name = user_plugin[0].getName().c_str();
+        m_pm->startPlugins(key, name);
+
+        sleep(5);
+
+        std::cout << "\n====== 4th TEST CASE ======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Get Plugin Status\n" << std::endl;
+
+        state = m_pm->getState(id);
 
+        std::cout << "last plugin status :  " << state << std::endl;
+        std::cout << "sleep 15 seconds please add new plugin in the plugin folder  " << std::endl;
 
+        sleep(15);
+
+        std::cout << "\n====  5th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Rescan Plugins.........\n" << std::endl;
+
+        m_pm->rescanPlugin();
+
+        std::cout << "\n====  6th TEST CASE  ====" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << "Try to start new resource type.........\n" << std::endl;
+        std::cout << "start oic.test resource" <<  std::endl;
+
+        sleep(5);
+
+        int flag = m_pm->startPlugins("ResourceType", "oic.test");
+
+        if (!flag)
+            std::cout << "There are no resouce type. Start plugin failed" << std::endl;
         // Start each client in a seperate thread
-//        std::thread t1(client1);
-//        t1.detach();
 
-///*
-//        sleep(5);
+        sleep(10);
+
+        std::cout << "\n====== 7th TEST CASE =======" << std::endl;
+        std::cout << "========================" << std::endl;
+        std::cout << " start client to find resource" << std::endl;
+
+        std::thread t1(client1);
+        t1.detach();
+
+        sleep(5);
+
         // Start each client in a seperate thread
-//        std::thread t2(client2);
-//        t2.detach();
-//*/
+        std::thread t2(client2);
+        t2.detach();
+
         while (true)
         {
             // some operations
diff --git a/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml b/service/protocol-plugin/sample-app/linux/mqtt/pluginmanager.xml
new file mode 100644 (file)
index 0000000..c90bb9f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pluginManager>
+    <pluginInfo        
+        pluginPath="../../../plugins"        
+        maxMEM="64M"
+        maxPlugin=""
+        version="1.0"
+        name="pluginmanager">
+    </pluginInfo>
+    <specailpluginInfo>
+    </specailpluginInfo>
+</pluginManager>
index cd76579..323937b 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../build/linux/root_path.inc
 -include ../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -6,12 +6,14 @@ SRC_PATH=../../src
 INC_PATH=../../include
 RST_NAME=release
 
+GAR=ar
+
 # Insert your project name.
-TARGET=SDKlib
+TARGET=${SSM_LIB}
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I../../ -I${INC_PATH}/ -I${FD_SSMCORE}/include -I${FD_SSMCORE}/src -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 CXX_LIB= 
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -30,7 +32,7 @@ pre_job:
        @echo " "
 
 ${TARGET}: ${OBJLIST}
-       @cp -Rdp ./*.o ./${RST_NAME}/ 
+       ${GAR} -r ./${RST_NAME}/$@  ./*.o
        @cp -Rdp ${INC_PATH}/*.h ./${RST_NAME}/
        @echo " " 
 
index 1ee47bd..36d6d57 100644 (file)
@@ -168,7 +168,6 @@ class SSMClient
 {
     private:
         SSMReturn m_retResponse;
-        OCPlatform *m_pPlatform;
         CSemaphore m_sem;
         /**
          * @brief SoftSensorManager Resource.
@@ -233,11 +232,16 @@ class SSMClient
 
         // friend option. for callback from SSMResource
         void onFoundResource(std::shared_ptr< OCResource > resource);
-        void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onRegisterQuery(const OCRepresentation &rep, const int eCode);
-        void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
-        void onObserve(const OCRepresentation &rep, const int &eCode);
+        void onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                 const int eCode);
+        void onReleaseQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                  const int eCode);
+        void onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                             const int eCode);
+        void onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                               const int eCode);
+        void onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep, const int &eCode,
+                       const int &sequenceNumber);
 };
 
 #endif /* RESOURCECLIENT_H_ */
diff --git a/service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp b/service/soft-sensor-manager/SDK/src/InprocSSMCore.cpp
new file mode 100644 (file)
index 0000000..358f807
--- /dev/null
@@ -0,0 +1,121 @@
+#include "SSMInterface.h"
+#include "SSMInterface/SSMCore.h"
+#include "Common/PlatformLayer.h"
+
+class SSMCoreEventReceiver : public IQueryEngineEvent
+{
+    public:
+        SSMCoreEventReceiver()
+        {
+        }
+
+        SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult)
+        {
+            SSMRESULT res = SSM_E_FAIL;
+
+            m_mtxListener.lock();
+
+            if (m_mapListener.find(cqid) == m_mapListener.end())
+            {
+                SSM_CLEANUP_ASSERT(res);
+            }
+
+            m_mapListener[cqid]->onQueryEngineEvent(cqid, pResult);
+
+            res = SSM_S_OK;
+
+CLEANUP:
+            m_mtxListener.unlock();
+            return res;
+        }
+
+        void lockListener()
+        {
+            m_mtxListener.lock();
+        }
+
+        void unlockListener()
+        {
+            m_mtxListener.unlock();
+        }
+
+        void addListener(IN int cqid, IN IQueryEngineEvent *pEngineEvent)
+        {
+            m_mapListener[cqid] = pEngineEvent;
+        }
+
+        void removeListener(IN int cqid)
+        {
+            m_mapListener.erase(cqid);
+        }
+
+    private:
+        CSimpleMutex                        m_mtxListener;
+        std::map<int, IQueryEngineEvent *>   m_mapListener;
+};
+
+IQueryEngine                        *g_pQueryEngineInstance = NULL;
+SSMCoreEventReceiver                *g_pEventReceiver = NULL;
+
+SSMInterface::SSMInterface()
+{
+    std::string xmlDescription = "<SSMCore>"
+                                 "<Device>"
+                                 "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
+                                 "<Name>MyPC</Name>"
+                                 "<Type>PC</Type>"
+                                 "</Device>"
+                                 "</SSMCore>";
+
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver = new SSMCoreEventReceiver();
+    SSM_CLEANUP_NULL_ASSERT(g_pEventReceiver);
+    SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
+    SSM_CLEANUP_ASSERT(StartSSMCore());
+    SSM_CLEANUP_ASSERT(CreateQueryEngine(&g_pQueryEngineInstance));
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->registerQueryEvent(g_pEventReceiver));
+CLEANUP:
+    ;
+}
+
+SSMInterface::~SSMInterface()
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->unregisterQueryEvent(g_pEventReceiver));
+    ReleaseQueryEngine(g_pQueryEngineInstance);
+    g_pQueryEngineInstance = NULL;
+    SSM_CLEANUP_ASSERT(StopSSMCore());
+    SSM_CLEANUP_ASSERT(TerminateSSMCore());
+
+CLEANUP:
+    SAFE_DELETE(g_pEventReceiver);
+}
+
+SSMRESULT SSMInterface::registerQuery(IN std::string queryString, IN IQueryEngineEvent *listener,
+                                      IN int &cqid)
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver->lockListener();
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->executeContextQuery(queryString, &cqid));
+    g_pEventReceiver->addListener(cqid, listener);
+
+CLEANUP:
+    g_pEventReceiver->unlockListener();
+    return res;
+}
+
+SSMRESULT SSMInterface::unregisterQuery(IN int cqid)
+{
+    SSMRESULT res = SSM_E_FAIL;
+
+    g_pEventReceiver->lockListener();
+    SSM_CLEANUP_ASSERT(g_pQueryEngineInstance->killContextQuery(cqid));
+    g_pEventReceiver->removeListener(cqid);
+
+CLEANUP:
+    g_pEventReceiver->unlockListener();
+    return res;
+}
\ No newline at end of file
index 174456c..4f0b574 100644 (file)
@@ -29,17 +29,11 @@ const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
 
 #define SSM_RESOURCE_TYPE       = "core.SoftSensorManager"
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               5683
-#define COAP_MODE               ModeType::Client
-#define COAP_SRVTYPE            ServiceType::InProc
-
 #define COAP_SERVER_ADDR        "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
 
 SSMClient::SSMClient()
 {
     m_sem.create(100000);
-    m_pPlatform = NULL;
     m_appListener = NULL;
     m_retResponse = SSM_ERROR;
     _findResource();
@@ -49,34 +43,30 @@ SSMClient::SSMClient()
 SSMClient::~SSMClient()
 {
     _releaseQueryEngine(m_queryEngineId);
-    if (m_pPlatform)
-    {
-        delete m_pPlatform;
-        m_pPlatform = NULL;
-    }
 }
 
 void SSMClient::_findResource()
 {
     // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+                       "0.0.0.0", 0, OC::QualityOfService::LowQos);
 
     // Create a OCPlatform instance.
     // Note: Platform creation is synchronous call.
     try
     {
-        m_pPlatform = new OCPlatform(cfg);
+        OCPlatform::Configure(cfg);
 
         // Find all resources
         OCStackResult result;
-        if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
-                                                std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
+        if ((result = OCPlatform::findResource("", COAP_SERVER_ADDR,
+                                               std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
             != OC_STACK_OK)
         {
-            delete m_pPlatform;
-            m_pPlatform = NULL;
+            std::cout << "Faile to Find Resource... " << std::endl;
             return;
         }
+        std::cout << "Find Resource... " << std::endl;
 
         m_sem.wait();
 
@@ -91,20 +81,13 @@ void SSMClient::_createQueryEngine(void)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("CreateQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("CreateQueryEngine"));
 
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
     {
         return;
     }
@@ -116,25 +99,14 @@ void SSMClient::_releaseQueryEngine(std::string queryEngineId)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("ReleaseQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("ReleaseQueryEngine"));
+    rep.setValue("queryEngineId", queryEngineId);
 
     m_SSMResource->put(rep, queryParamsMap,
                        std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
-                                 std::placeholders::_2));
+                                 std::placeholders::_2, std::placeholders::_3));
 
     m_sem.wait();
 }
@@ -144,39 +116,25 @@ SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues contextQueryValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("ExecuteContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
 
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    contextQueryValue.push_back(queryString);
-
-    requestAttributeMap["contextQuery"] = contextQueryValue;
+    rep.setValue("command", std::string("ExecuteContextQuery"));
+    rep.setValue("queryEngineId", m_queryEngineId);
+    rep.setValue("contextQuery", queryString);
 
     m_appListener = listener;
 
-    rep.setAttributeMap(requestAttributeMap);
-
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
         return SSM_ERROR_NETWORK;
 
     m_sem.wait();
 
     if (m_retResponse == SSM_SUCCESS)
     {
-        cqid = m_responseAttributeMap["CQID"].back();
+        cqid = m_responseAttributeMap["CQID"];
     }
 
     return m_retResponse;
@@ -186,30 +144,15 @@ SSMReturn SSMClient::unregisterQuery(std::string cqid)
 {
     OCRepresentation rep;
 
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues cqidValue;
-
     QueryParamsMap queryParamsMap;
 
-    commandValue.push_back("KillContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    cqidValue.push_back(cqid);
-
-    requestAttributeMap["CQID"] = cqidValue;
-
-    rep.setAttributeMap(requestAttributeMap);
+    rep.setValue("command", std::string("KillContextQuery"));
+    rep.setValue("queryEngineId", m_queryEngineId);
+    rep.setValue("CQID", cqid);
 
     if (m_SSMResource->put(rep, queryParamsMap,
                            std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
+                                     std::placeholders::_2, std::placeholders::_3)) != OC_STACK_OK)
         return SSM_ERROR_NETWORK;
 
     m_sem.wait();
@@ -246,7 +189,8 @@ void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
     m_sem.release();
 }
 
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onCreateQueryEngine(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                    const int eCode)
 {
     if (eCode != 0)
     {
@@ -254,15 +198,14 @@ void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode
         goto CLEANUP;
     }
 
-    m_responseAttributeMap = rep.getAttributeMap();
-    m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
-    m_responseAttributeMap["queryEngineId"].pop_back();
+    m_queryEngineId = rep.getValue<std::string>("queryEngineId");
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onRegisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                const int eCode)
 {
     QueryParamsMap queryParamsMap;
 
@@ -281,14 +224,16 @@ void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
     }
 
     m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
-                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
+                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1,
+                                     std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
 
     m_retResponse = SSM_SUCCESS;
 
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
+void SSMClient::onUnregisterQuery(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                                  const int eCode)
 {
     if (eCode != 0)
     {
@@ -309,7 +254,8 @@ void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
+void SSMClient::onReleaseQueryEngine(const HeaderOptions &headerOptions,
+                                     const OCRepresentation &rep, const int eCode)
 {
     if (eCode != 0)
     {
@@ -324,7 +270,8 @@ void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCod
 CLEANUP: m_sem.release();
 }
 
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
+void SSMClient::onObserve(const HeaderOptions &headerOptions, const OCRepresentation &rep,
+                          const int &eCode, const int &sequenceNumber)
 {
     SSMReturn ret = SSM_SUCCESS;
 
index dbec597..f6a3f19 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../build/linux/root_path.inc
 -include ../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -7,13 +7,13 @@ INC_PATH=../../include
 RST_NAME=release
 
 # Insert your project name.
-TARGET=SSMCoreUbuntu
+TARGET=${SSMCORE_LIB}
 EXCLUDE_LIST=SSMCore_JNI.cpp
 
 # C++ type Compile Flag define.
 CXX=g++
-CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -DMODEL_DIRECTORY=${MODEL_DIR} -DHIGH_LOCATION=${HIGH_LOCATION} -ldl
-CXX_INC=-I../../ -I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST} -I${SRC_PATH} -I${SRC_PATH}/Common -I${SRC_PATH}/QueryProcessor -I${SRC_PATH}/SensorProcessor -I${SRC_PATH}/SSMInterface
+CXX_FLAGS=-std=c++0x -Wall -pthread -DLINUX -ldl
+CXX_INC=-I${INC_PATH}/ -I${SRC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 CXX_LIB=-L""
 
 CXX_SRCPATH=${wildcard ${SRC_PATH}/**/*.cpp}
@@ -34,8 +34,8 @@ GCC_OBJLIST=${GCC_USESRCS:.c=.o}
 
 # Linker FLAGS define.
 LD_FLAGS=-std=c++0x -Wall -DLINUX
-GAR=ar
-LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} -lpthread -ldl 
+GAR=ar
+# LD_LIB=${IOT_RELEASE}/${IOT_LIB} ${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} ${IOT_LOG_DIR}/lib/${IOT_LOG_LIB} -lpthread -ldl 
 
 
 # Force metatargets to build:
@@ -51,8 +51,8 @@ pre_job:
        @echo "${MODEL_DIR}"
        
 ${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
-       $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}             
-       ${GAR} -r ./${RST_NAME}/$@  ./*.o
+       # $(CXX) $(LD_FLAGS) -o ./${RST_NAME}/$@ $^ ${LD_LIB}           
+       ${GAR} -r ./${RST_NAME}/$@  ./*.o
        @echo " "
 
 %.o : ${SRC_PATH}/**/%.c 
@@ -70,6 +70,7 @@ ${TARGET}: ${GCC_OBJLIST} ${CXX_OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
+       cp -Rdp ${INC_PATH}/SSMInterface.h ${OUTPUTS_DIR}/
        cp -Rdp ${SRC_PATH}/SSMInterface/SSMModelDefinition.h ${OUTPUTS_DIR}/
        @echo "---------------- SSMCore Build Successful. ---------------"
        @echo "Enter to ${RST_NAME} folder."
diff --git a/service/soft-sensor-manager/SSMCore/include/SSMInterface.h b/service/soft-sensor-manager/SSMCore/include/SSMInterface.h
new file mode 100644 (file)
index 0000000..b126130
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef _SSMInterface_H_
+#define _SSMInterface_H_
+
+#include <string>
+#include <vector>
+
+enum SSMRESULT
+{
+    SSM_S_OK
+    , SSM_S_FALSE
+    , SSM_E_POINTER
+    , SSM_E_OUTOFMEMORY
+    , SSM_E_FAIL
+    , SSM_E_NOINTERFACE
+    , SSM_E_NOTIMPL
+};
+
+/**
+* @class    IModelData
+* @brief    IModelData Interface
+*            This class represents context model data package
+*
+* @see
+*/
+class IModelData
+{
+    public:
+        /**
+        * @fn     getDataId
+        * @brief Get affected DataId. ContextModel has plenty of data so \n
+        *         returned data is matched from given condition
+        *
+        * @param None
+        *
+        * @return int
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual int getDataId() = 0;
+
+        /**
+        * @fn     GetPropertyCount
+        * @brief ContextModel has at least one property that contains data \n
+        *         property is described from its specification.
+        *
+        * @param None
+        *
+        * @return int
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual int getPropertyCount() = 0;
+
+        /**
+        * @fn     getPropertyName
+        * @brief Retrieve propertyName
+        *
+        * @param [in] int propertyIndex - index of property to read
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyName(int propertyIndex) = 0;
+
+        /**
+        * @fn     getPropertyValue
+        * @brief Retrieve propertyValue
+        *
+        * @param [in] int propertyIndex - index of property to read
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyValue(int propertyIndex) = 0;
+
+        /**
+        * @fn     getPropertyValueByName
+        * @brief Retrieve propertyValue using given name
+        *
+        * @param [in] std::string propertyName - property name looking for
+        *
+        * @return std::string
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual std::string getPropertyValueByName(std::string propertyName) = 0;
+    protected:
+        virtual ~IModelData() {};
+};
+
+/**
+* @class    IDataReader
+* @brief    IDataReader Interface
+*            This class represents context model data package's reader
+*
+* @see
+*/
+class IDataReader
+{
+    public:
+        /**
+        * @fn     getAffectedModels
+        * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
+        *
+        * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getAffectedModels(std::vector<std::string> *pAffectedModels) = 0;
+
+        /**
+        * @fn     getModelDataCount
+        * @brief Get affected data count. There are multiple data can exist from given condition.
+        *
+        * @param [in] std::string modelName - affected ContextModel name
+        *
+        * @param [out] int *pDataCount - affected dataId count
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getModelDataCount(std::string modelName, int *pDataCount) = 0;
+
+        /**
+        * @fn     getModelData
+        * @brief Get actual Context Model data
+        *
+        * @param [in] std::string modelName - affected ContextModel name
+        *
+        *
+        * @param [in] int dataIndex - affected dataId index
+        *
+        *
+        * @param [out] IModelData **ppModelData - affected ContextModel data reader
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT getModelData(std::string modelName, int dataIndex, IModelData **ppModelData) = 0;
+    protected:
+        virtual ~IDataReader() {};
+};
+
+/**
+* @class    IQueryEngineEvent
+* @brief    IQueryEngineEvent Interface
+*            This class represents Query Engine's event that contains results
+*
+* @see
+*/
+class IQueryEngineEvent
+{
+    public:
+        /**
+        * @fn     onQueryEngineEvent
+        * @brief Transmit result of SSMCore to Application layer
+        *
+        * @param [in] int cqid - entered ContextQuery ID
+        *
+        * @param [in] IDataReader *pResult - result of SSMCore
+        *
+        * @return SSMRESULT
+        * @warning
+        * @exception
+        * @see
+        */
+        virtual SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult) = 0;
+    protected:
+        virtual ~IQueryEngineEvent() {};
+};
+
+class SSMInterface
+{
+    public:
+        SSMInterface();
+        ~SSMInterface();
+
+        SSMRESULT registerQuery(std::string queryString, IQueryEngineEvent *listener, int &cqid);
+        SSMRESULT unregisterQuery(int cqid);
+};
+#endif
\ No newline at end of file
index dd9fe3e..e0db5b2 100644 (file)
@@ -113,21 +113,21 @@ class IContextRepository : public IBase
                 ;
 
         /**
-        * @fn           setCurrentDeviceInfo
-        * @brief        set device information
+        * @fn           initRepository
+        * @brief        initialize repository using given info
         *
         * @param        [in] std::string name - Device name
         * @param        [in] std::string type - Device Type
         * @param        [in] std::string pathSoftSensors - SoftSensors Repository path
         * @param        [in] std::string pathDescription - SoftSensors Description path
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        virtual void setCurrentDeviceInfo(IN std::string name, IN std::string type,
-                                          IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
+        virtual SSMRESULT initRepository(IN std::string name, IN std::string type,
+                                         IN std::string pathSoftSensors, IN std::string pathDescription) = 0;
 
         virtual SSMRESULT registerResourceFinderEvent(IN IResourceEvent *pResourceEvent) = 0;
         virtual SSMRESULT startResourceFinder() = 0;
@@ -1123,16 +1123,15 @@ class IContextExecutor : public IBase
                                        IEvent *pEvent) = 0;
 };
 
-static const OID OID_IResponseReactor = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
+static const OID OID_ISensingEngine = { 0x3140a3dc, 0xf912, 0x4d88, { 0x97, 0x3c, 0x86, 0xe8, 0x35, 0x69, 0xa7, 0xf8 } };
 /**
- * @class    IResponseReactor
- * @brief    Interface for implement of reactor pattern
- *           Delegate requested context to context executor layer.
+ * @class    ISensingEngine
+ * @brief    Class for implementing main abstration of SensorProcessor
  *
  *
  * @see
  */
-class IResponseReactor : public IBase
+class ISensingEngine : public IBase
     , public IEvent
 {
     public:
@@ -1149,7 +1148,8 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void registerContext(TypeofEvent callType, ISSMResource *pSSMResouce, IEvent *pEvent) = 0;
+        virtual SSMRESULT registerContext(TypeofEvent callType, ISSMResource *pSSMResouce,
+                                          IEvent *pEvent) = 0;
 
         /**
         * @fn     unregisterContext
@@ -1164,8 +1164,8 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
-                                       IEvent *pEvent) = 0;
+        virtual SSMRESULT unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+                                            IEvent *pEvent) = 0;
 
         /**
         * @fn    getList
@@ -1178,7 +1178,7 @@ class IResponseReactor : public IBase
         * @exception
         * @see
         */
-        virtual void getList(std::vector<ISSMResource *> *pList) = 0;
+        virtual SSMRESULT getList(std::vector<ISSMResource *> *pList) = 0;
 };
 
 class IResourceFinderEvent
@@ -1199,13 +1199,6 @@ class IResourceFinder : public IBase
         virtual SSMRESULT stopObserveResource(IN ISSMResource *pSensor) = 0;
 };
 
-static const OID OID_IResourceConnectivity = { 0x8e42b098, 0x9aa5, 0x43f3, { 0x84, 0xa, 0x21, 0x44, 0xc9, 0x4c, 0xc7, 0x99 } };
-class IResourceConnectivity : public IBase
-{
-    public:
-        virtual void *getPlatform() = 0;
-};
-
 /**
 * @class    ISoftSensorManager
 * @brief    ISoftSensorManager Interface
index bb86402..4a8e050 100644 (file)
@@ -1,3 +1,22 @@
+/******************************************************************
+*
+* Copyright 2014 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
 #include "ThreadManager.h"
 
 CSimpleMutex::CSimpleMutex()
index bab1e7c..58d2df4 100644 (file)
@@ -36,7 +36,7 @@ SSMRESULT CPropagationEngine::finalConstruct()
 
     SSM_CLEANUP_ASSERT(m_pContextRepository->registerResourceFinderEvent(this));
 
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
+    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
 
     SSM_CLEANUP_ASSERT(initializeEngine());
 
@@ -148,7 +148,7 @@ SSMRESULT CPropagationEngine::addResourceFromGetList()
     std::vector<ISSMResource *>      contextModelList;
     std::stringstream               sstream;
 
-    m_pResponseReactor->getList(&contextModelList);
+    m_pSensingEngine->getList(&contextModelList);
     for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
          itor != contextModelList.end(); ++itor)
     {
@@ -288,12 +288,12 @@ CLEANUP:
     return res;
 }
 
-SSMRESULT CPropagationEngine::installResponseReactor(IN IResponseReactor *pResponseReactor)
+SSMRESULT CPropagationEngine::installCurrentSensors()
 {
     SSMRESULT res = SSM_E_FAIL;
     std::vector<ISSMResource *>      contextModelList;
 
-    pResponseReactor->getList(&contextModelList);
+    m_pSensingEngine->getList(&contextModelList);
 
     for (std::vector<ISSMResource *>::iterator itor = contextModelList.begin();
          itor != contextModelList.end(); ++itor)
@@ -449,7 +449,7 @@ SSMRESULT CPropagationEngine::initializeEngine()
 
     SSM_CLEANUP_ASSERT(updateDeviceInfo(&ssmResource, NULL));
 
-    SSM_CLEANUP_ASSERT(installResponseReactor(m_pResponseReactor));
+    SSM_CLEANUP_ASSERT(installCurrentSensors());
 
 CLEANUP:
     SAFE_RELEASE(pRootModel);
@@ -525,11 +525,11 @@ SSMRESULT CPropagationEngine::onModelStatusChange(IN IContextModel::Status newSt
     {
         case IContextModel::STATUS_ACTIVATE:
             pModel->addRef();
-            m_pResponseReactor->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->registerContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
             break;
 
         case IContextModel::STATUS_DEACTIVATE:
-            m_pResponseReactor->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->unregisterContext(SSM_REPEAT, pSSMResource, (CContextModel *)pModel);
             //pModel->CleanUpModelData();
             pModel->release();
             break;
@@ -537,7 +537,7 @@ SSMRESULT CPropagationEngine::onModelStatusChange(IN IContextModel::Status newSt
         case IContextModel::STATUS_START_READ_VALUE:
             //Model must be released from OnEvent callType
             pModel->addRef();
-            m_pResponseReactor->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
+            m_pSensingEngine->registerContext(SSM_ONCE, pSSMResource, (CContextModel *)pModel);
             break;
 
         case IContextModel::STATUS_STOP_READ_VALUE:
index 45eca05..0b59a69 100644 (file)
@@ -56,7 +56,7 @@ class CPropagationEngine :
         CSimpleMutex                                m_mtxContextModelList;
         CSimpleMutex                                m_mtxLookUpList;
 
-        CObjectPtr<IResponseReactor>                m_pResponseReactor;
+        CObjectPtr<ISensingEngine>                  m_pSensingEngine;
 
         CObjectPtr<IContextModel>                   m_pDeviceModel;
 
@@ -75,9 +75,9 @@ class CPropagationEngine :
         SSMRESULT addResourceFromGetList();
 
         //TODO: Install Context model from SSMResource
-        SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
+        SSMRESULT installCurrentSensors();
 
-        SSMRESULT installResponseReactor(IN IResponseReactor *pResponseReactor);
+        SSMRESULT installContextModelFromISSMResource(IN ISSMResource *pSSMResource);
 
         SSMRESULT installContextModel(IN IContextModel *pParentModel,
                                       IN IContextModel::ConstructionType constructionType,
index f109cfb..1217284 100644 (file)
@@ -20,9 +20,7 @@
 #ifndef _SSMCore_H_
 #define _SSMCore_H_
 
-#include <string>
-#include <vector>
-
+#include "SSMInterface.h"
 #include "SSMModelDefinition.h"
 
 #define IN
 */
 #define INTERFACE_DECLSPEC
 
-enum SSMRESULT
-{
-    SSM_S_OK
-    , SSM_S_FALSE
-    , SSM_E_POINTER
-    , SSM_E_OUTOFMEMORY
-    , SSM_E_FAIL
-    , SSM_E_NOINTERFACE
-    , SSM_E_NOTIMPL
-};
-
-/**
-* @class    IModelData
-* @brief    IModelData Interface
-*            This class represents context model data package
-*
-* @see
-*/
-class IModelData
-{
-    public:
-        /**
-        * @fn     getDataId
-        * @brief Get affected DataId. ContextModel has plenty of data so \n
-        *         returned data is matched from given condition
-        *
-        * @param None
-        *
-        * @return int
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual int getDataId() = 0;
-
-        /**
-        * @fn     GetPropertyCount
-        * @brief ContextModel has at least one property that contains data \n
-        *         property is described from its specification.
-        *
-        * @param None
-        *
-        * @return int
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual int getPropertyCount() = 0;
-
-        /**
-        * @fn     getPropertyName
-        * @brief Retrieve propertyName
-        *
-        * @param [in] int propertyIndex - index of property to read
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyName(IN int propertyIndex) = 0;
-
-        /**
-        * @fn     getPropertyValue
-        * @brief Retrieve propertyValue
-        *
-        * @param [in] int propertyIndex - index of property to read
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyValue(IN int propertyIndex) = 0;
-
-        /**
-        * @fn     getPropertyValueByName
-        * @brief Retrieve propertyValue using given name
-        *
-        * @param [in] std::string propertyName - property name looking for
-        *
-        * @return std::string
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual std::string getPropertyValueByName(IN std::string propertyName) = 0;
-    protected:
-        virtual ~IModelData() {};
-};
-
-/**
-* @class    IDataReader
-* @brief    IDataReader Interface
-*            This class represents context model data package's reader
-*
-* @see
-*/
-class IDataReader
-{
-    public:
-        /**
-        * @fn     getAffectedModels
-        * @brief Get affected ContextModels. The CQL can specify multiple ContextModels for retrieving data.
-        *
-        * @param [out] std::vector<std::string> *pAffectedModels - affected ContextModel list
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getAffectedModels(OUT std::vector<std::string> *pAffectedModels) = 0;
-
-        /**
-        * @fn     getModelDataCount
-        * @brief Get affected data count. There are multiple data can exist from given condition.
-        *
-        * @param [in] std::string modelName - affected ContextModel name
-        *
-        * @param [out] int *pDataCount - affected dataId count
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getModelDataCount(IN std::string modelName, OUT int *pDataCount) = 0;
-
-        /**
-        * @fn     getModelData
-        * @brief Get actual Context Model data
-        *
-        * @param [in] std::string modelName - affected ContextModel name
-        *
-        *
-        * @param [in] int dataIndex - affected dataId index
-        *
-        *
-        * @param [out] IModelData **ppModelData - affected ContextModel data reader
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT getModelData(IN std::string modelName, IN int dataIndex,
-                                       OUT IModelData **ppModelData) = 0;
-    protected:
-        virtual ~IDataReader() {};
-};
-
-/**
-* @class    IQueryEngineEvent
-* @brief    IQueryEngineEvent Interface
-*            This class represents Query Engine's event that contains results
-*
-* @see
-*/
-class IQueryEngineEvent
-{
-    public:
-        /**
-        * @fn     onQueryEngineEvent
-        * @brief Transmit result of SSMCore to Application layer
-        *
-        * @param [in] int cqid - entered ContextQuery ID
-        *
-        * @param [in] IDataReader *pResult - result of SSMCore
-        *
-        * @return SSMRESULT
-        * @warning
-        * @exception
-        * @see
-        */
-        virtual SSMRESULT onQueryEngineEvent(IN int cqid, IN IDataReader *pResult) = 0;
-    protected:
-        virtual ~IQueryEngineEvent() {};
-};
-
 /**
 * @class    IQueryEngine
 * @brief    IQueryEngine Interface
index 23aabed..9dbb031 100644 (file)
@@ -17,6 +17,7 @@
 * limitations under the License.
 *
 ******************************************************************/
+#include "SSMCore.h"
 #include "SSMInterface/SSMCore_JNI.h"
 #include "Common/PlatformLayer.h"
 
index 51a13db..19dd122 100644 (file)
@@ -51,18 +51,18 @@ class CQueryEngineEvent: public IQueryEngineEvent
             std::stringstream sstream;
 
             // QueryEngine Id
-            queryEventResult["queryEngineId"].push_back(m_queryEngineId);
+            queryEventResult["queryEngineId"] = m_queryEngineId;
 
             // CQID
             sstream << cqid;
-            queryEventResult["CQID"].push_back(sstream.str());
+            queryEventResult["CQID"] = sstream.str();
             sstream.str("");
 
             pResult->getAffectedModels(&affectedModels);
 
             // Affected Model Count
             sstream << affectedModels.size();
-            queryEventResult["modelCount"].push_back(sstream.str());
+            queryEventResult["modelCount"] = sstream.str();
             sstream.str("");
 
             //TODO: we assume that contains only one model at time
@@ -71,14 +71,14 @@ class CQueryEngineEvent: public IQueryEngineEvent
             {
                 // Model Name
                 sstream << (*itor);
-                queryEventResult["modelName"].push_back(sstream.str());
+                queryEventResult["modelName"] = sstream.str();
                 sstream.str("");
 
                 pResult->getModelDataCount(*itor, &dataCount);
 
                 // Data Count
                 sstream << dataCount;
-                queryEventResult["dataCount"].push_back(sstream.str());
+                queryEventResult["dataCount"] = sstream.str();
                 sstream.str("");
 
                 //FixME: we have to support multiple data count
@@ -88,26 +88,28 @@ class CQueryEngineEvent: public IQueryEngineEvent
 
                     // Data Id
                     sstream << pModelData->getDataId();
-                    queryEventResult["dataId"].push_back(sstream.str());
+                    queryEventResult["dataId"] = sstream.str();
                     sstream.str("");
 
                     // Property Count
                     sstream << pModelData->getPropertyCount();
-                    queryEventResult["propertyCount"].push_back(sstream.str());
+                    queryEventResult["propertyCount"] = sstream.str();
                     sstream.str("");
 
                     for (int j = 0; j < pModelData->getPropertyCount(); j++)
                     {
                         // Property Name & Value
                         sstream << pModelData->getPropertyValue(j).c_str();
-                        queryEventResult[pModelData->getPropertyName(j).c_str()].push_back(sstream.str());
+                        queryEventResult[pModelData->getPropertyName(j).c_str()] = sstream.str();
                         sstream.str("");
                     }
                 }
             }
 
             g_vecQueryEventResults.push_back(queryEventResult);
-            OCPlatform::notifyObservers(m_hSSMResource);
+
+            //TODO: need to modify for notifying proper clients
+            OCPlatform::notifyAllObservers(m_hSSMResource);
 
             return SSM_S_OK;
         }
@@ -115,7 +117,6 @@ class CQueryEngineEvent: public IQueryEngineEvent
 
 SSMResourceServer::SSMResourceServer()
 {
-    m_pPlatform = NULL;
     m_hSSMResource = NULL;
 }
 
@@ -126,16 +127,10 @@ SSMResourceServer::~SSMResourceServer()
 int SSMResourceServer::initializeManager(std::string &xmlDescription)
 {
     SSMRESULT res = SSM_E_FAIL;
-    CObjectPtr < IResourceConnectivity > pResourceConnectivity;
 
     SSM_CLEANUP_ASSERT(InitializeSSMCore(xmlDescription));
     SSM_CLEANUP_ASSERT(StartSSMCore());
 
-    SSM_CLEANUP_ASSERT(
-        CreateGlobalInstance(OID_IResourceConnectivity, (IBase **) &pResourceConnectivity));
-
-    m_pPlatform = (OC::OCPlatform *) pResourceConnectivity->getPlatform();
-
     if (createResource() != 0)
     {
         SSM_CLEANUP_ASSERT (SSM_E_FAIL);
@@ -165,15 +160,14 @@ CLEANUP:
 int SSMResourceServer::createResource()
 {
     std::string resourceURI = "/service/SoftSensorManager"; // URI of the resource
-    std::string resourceTypeName =
-        "core.SoftSensorManager"; // resource type name. In this case, it is light
+    std::string resourceTypeName = "core.SoftSensorManager"; // resource type name.
     std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
 
     // OCResourceProperty is defined ocstack.h
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = m_pPlatform->registerResource(m_hSSMResource, resourceURI,
+    OCStackResult result = OCPlatform::registerResource(m_hSSMResource, resourceURI,
                            resourceTypeName, resourceInterface,
                            std::bind(&SSMResourceServer::entityHandler, this, std::placeholders::_1,
                                      std::placeholders::_2), resourceProperty);
@@ -186,8 +180,8 @@ int SSMResourceServer::createResource()
     return 0;
 }
 
-void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
-                                      std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > request,
+        std::shared_ptr< OCResourceResponse > response)
 {
     SSMRESULT res = SSM_E_FAIL;
 
@@ -195,14 +189,17 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
+            cout << "\t\trequestFlag : Request\n";
+
             // If the request type is GET
             if (requestType == "GET")
             {
@@ -237,7 +234,7 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
                 AttributeMap responseAttributeMap;
 
                 // Process query params and do required operations ..
-                if (requestAttributeMap["command"].back() == "CreateQueryEngine")
+                if (requestAttributeMap["command"] == "CreateQueryEngine")
                 {
                     CQueryEngineEvent *queryEngineEvent = NULL;
 
@@ -245,7 +242,7 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("CreateQueryEngine failed");
+                        responseAttributeMap["error"] = "CreateQueryEngine failed";
                         goto CLEANUP;
                     }
 
@@ -256,8 +253,8 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (queryEngineEvent == NULL)
                     {
-                        responseAttributeMap["error"].push_back(
-                            "QueryEngineEvent create failed");
+                        responseAttributeMap["error"] =
+                            "QueryEngineEvent create failed";
                         goto CLEANUP;
                     }
 
@@ -265,49 +262,49 @@ void SSMResourceServer::entityHandler(std::shared_ptr< OCResourceRequest > reque
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("RegisterQueryEvent failed");
+                        responseAttributeMap["error"] = "RegisterQueryEvent failed";
                         goto CLEANUP;
                     }
 
-                    responseAttributeMap["queryEngineId"].push_back(sstream.str());
+                    responseAttributeMap["queryEngineId"] = sstream.str();
                 }
-                else if (requestAttributeMap["command"].back() == "ReleaseQueryEngine")
+                else if (requestAttributeMap["command"] == "ReleaseQueryEngine")
                 {
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       requestAttributeMap["queryEngineId"]);
 
                     ReleaseQueryEngine(pQueryEngine);
                 }
-                else if (requestAttributeMap["command"].back() == "ExecuteContextQuery")
+                else if (requestAttributeMap["command"] == "ExecuteContextQuery")
                 {
                     int CQID = 0;
 
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       requestAttributeMap["queryEngineId"]);
 
                     res = pQueryEngine->executeContextQuery(
-                              requestAttributeMap["contextQuery"].back(), &CQID);
+                              requestAttributeMap["contextQuery"], &CQID);
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("ExecuteContextQuery failed");
+                        responseAttributeMap["error"] = "ExecuteContextQuery failed";
                         goto CLEANUP;
                     }
 
                     sstream << CQID;
 
-                    responseAttributeMap["CQID"].push_back(sstream.str());
+                    responseAttributeMap["CQID"] = sstream.str();
                 }
-                else if (requestAttributeMap["command"].back() == "KillContextQuery")
+                else if (requestAttributeMap["command"] == "KillContextQuery")
                 {
-                    pQueryEngine = (IQueryEngine *) stoi(
-                                       requestAttributeMap["queryEngineId"].back());
+                    pQueryEngine = (IQueryEngine *) std::stoi(
+                                       requestAttributeMap["queryEngineId"]);
 
-                    res = pQueryEngine->killContextQuery(stoi(requestAttributeMap["CQID"].back()));
+                    res = pQueryEngine->killContextQuery(std::stoi(requestAttributeMap["CQID"]));
 
                     if (res != SSM_S_OK)
                     {
-                        responseAttributeMap["error"].push_back("KillContextQuery failed");
+                        responseAttributeMap["error"] = "KillContextQuery failed";
                         goto CLEANUP;
                     }
                 }
@@ -330,12 +327,12 @@ CLEANUP:
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             // perform observe related operations on the resource.
         }
     }
-    else
-    {
-    }
+
+    return OC_EH_OK;
 }
@@ -34,11 +34,10 @@ class SSMResourceServer
         int initializeManager(std::string &xmlDescription);
         int terminateManager();
 
-        void entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
-                           std::shared_ptr< OC::OCResourceResponse > response);
+        OCEntityHandlerResult entityHandler(std::shared_ptr< OC::OCResourceRequest > request,
+                                            std::shared_ptr< OC::OCResourceResponse > response);
 
     private:
-        OC::OCPlatform *m_pPlatform;
         OCResourceHandle m_hSSMResource;
         int createResource();
 };
index 5eed956..0d0149e 100644 (file)
 #include "QueryProcessor/ConditionedModel.h"
 #include "QueryProcessor/EvaluationEngine.h"
 #include "QueryProcessor/PropagationEngine.h"
-#include "SensorProcessor/ResponseReactor.h"
+#include "SensorProcessor/SensingEngine.h"
 #include "SensorProcessor/ContextExecutor.h"
 #include "SensorProcessor/ContextDataReader.h"
 #include "SensorProcessor/ResourceFinder.h"
-#include "SensorProcessor/ResourceConnectivity.h"
 
 inline bool operator<( const OID &lhs, const OID &rhs )
 {
@@ -121,8 +120,9 @@ SSMRESULT CSoftSensorManager::initializeCore(IN std::string xmlDescription)
     }
 
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IContextRepository, (IBase **)&m_pContextRepository));
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResponseReactor, (IBase **)&m_pResponseReactor));
-    m_pContextRepository->setCurrentDeviceInfo(name, type, pathSoftSensors, pathDescription);
+    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ISensingEngine, (IBase **)&m_pSensingEngine));
+    SSM_CLEANUP_ASSERT(m_pContextRepository->initRepository(name, type, pathSoftSensors,
+                       pathDescription));
 
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IPropagationEngine, (IBase **)&m_pPropagationEngine));
 
@@ -173,7 +173,7 @@ unsigned long CSoftSensorManager::releaseQueryEngine(IN IQueryEngine *pQueryEngi
 
 SSMRESULT CSoftSensorManager::getInstalledModelList(OUT std::vector<ISSMResource *> *pList)
 {
-    m_pResponseReactor->getList(pList);
+    m_pSensingEngine->getList(pList);
 
     return SSM_S_OK;
 }
@@ -238,18 +238,11 @@ SSMRESULT CreateGlobalInstance(IN const OID &objectID, OUT IBase **ppvObject)
             SSM_CLEANUP_ASSERT(CreateInstance(OID_IContextDataReader, ppvObject));
         }
     }
-    else if (IsEqualOID(OID_IResponseReactor, objectID))
+    else if (IsEqualOID(OID_ISensingEngine, objectID))
     {
-        if (g_globalInstance->find(OID_IResponseReactor) == g_globalInstance->end())
+        if (g_globalInstance->find(OID_ISensingEngine) == g_globalInstance->end())
         {
-            SSM_CLEANUP_ASSERT(CreateInstance(OID_IResponseReactor, ppvObject));
-        }
-    }
-    else if (IsEqualOID(OID_IResourceConnectivity, objectID))
-    {
-        if (g_globalInstance->find(OID_IResourceConnectivity) == g_globalInstance->end())
-        {
-            SSM_CLEANUP_ASSERT(CreateInstance(OID_IResourceConnectivity, ppvObject));
+            SSM_CLEANUP_ASSERT(CreateInstance(OID_ISensingEngine, ppvObject));
         }
     }
     else
@@ -313,9 +306,9 @@ SSMRESULT CreateInstance(IN const OID &objectID, OUT IBase **ppObject)
     {
         SSM_CLEANUP_ASSERT(CreateNewObject<CContextRepository>(objectID, ppObject));
     }
-    else if (IsEqualOID(OID_IResponseReactor, objectID))
+    else if (IsEqualOID(OID_ISensingEngine, objectID))
     {
-        SSM_CLEANUP_ASSERT(CreateNewObject<CResponseReactor>(objectID, ppObject));
+        SSM_CLEANUP_ASSERT(CreateNewObject<CSensingEngine>(objectID, ppObject));
     }
     else if (IsEqualOID(OID_IContextExecutor, objectID))
     {
@@ -353,10 +346,6 @@ SSMRESULT CreateInstance(IN const OID &objectID, OUT IBase **ppObject)
     {
         SSM_CLEANUP_ASSERT(CreateNewObject<CContextDataReader>(objectID, ppObject));
     }
-    else if (IsEqualOID(OID_IResourceConnectivity, objectID))
-    {
-        SSM_CLEANUP_ASSERT(CreateNewObject<CResourceConnectivity>(objectID, ppObject));
-    }
 
 CLEANUP:
     return res;
index 1718097..8baa123 100644 (file)
@@ -44,7 +44,7 @@ class CSoftSensorManager :
     private:
         CObjectPtr<IContextRepository>      m_pContextRepository;
         CObjectPtr<IPropagationEngine>      m_pPropagationEngine;
-        CObjectPtr<IResponseReactor>        m_pResponseReactor;
+        CObjectPtr<ISensingEngine>          m_pSensingEngine;
 
     public:
         SSMRESULT finalConstruct();
diff --git a/service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp b/service/soft-sensor-manager/SSMCore/src/SSMResourceServerLauncher.cpp
deleted file mode 100644 (file)
index bf96c57..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-
-/*
- * SSMResourceServerLauncher.cpp
- */
-#include "SSMResourceServer.h"
-
-string xmlDescription = "<SSMCore>"
-                        "<Device>"
-                        "<UDN>abcde123-31f8-11b4-a222-08002b34c003</UDN>"
-                        "<Name>MyPC</Name>"
-                        "<Type>PC</Type>"
-                        "</Device>"
-                        "</SSMCore>";
-
-using namespace std;
-
-int main(int argc, char *argv[])
-{
-    int inputKey = 0;
-
-    try
-    {
-        SSMResourceServer ssmResourceServer;
-
-        cout << "Initializing Resource Server" << endl;
-
-        if (ssmResourceServer.initializeManager(xmlDescription) != 0)
-        {
-            cout << "SSM Resource Server init failed" << endl;
-            return -1;
-        }
-
-        cout << "SSM Resource Server is working, press anykey to terminate" << endl;
-
-        cin >> inputKey;
-
-        cout << "SSM Resource Server is terminating" << endl;
-
-        if (ssmResourceServer.terminateManager() != 0)
-        {
-            cout << "SSM Resource Server terminate failed" << endl;
-        }
-    }
-    catch (std::exception e)
-    {
-        cout << e.what() << endl;
-    }
-
-    cout << "bye bye" << endl;
-}
index 9f26e55..2fbcd84 100644 (file)
@@ -75,22 +75,6 @@ void CContextExecutor::getDataFromDatabase(std::string modelName, int startIndex
     m_pContextDataReader->getContextData(modelName, startIndex, count, data, pLastIndex);
 }
 
-std::string CContextExecutor::checkError(std::vector<ContextData> data)
-{
-    std::string errorMsg = "OK";
-
-    for (unsigned int i = 0 ; i < data.size() ; ++i)
-    {
-        if (data[i].outputProperty[0].find("error") != data[i].outputProperty[0].end())
-        {
-            errorMsg = data[i].outputProperty[0].find("error")->second ;
-            break;
-        }
-    }
-
-    return errorMsg;
-}
-
 void CContextExecutor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
                                        IEvent *pEvent)
 {
@@ -242,10 +226,12 @@ std::map<std::string, std::vector<ContextData> >  CContextExecutor::getPreparedC
     std::string primitiveSensor)
 {
     //check m_relatedSoftSensor / apply timestamp
-    std::map<std::string, std::vector<ContextData> > returnData;
 
     SSMRESULT ret = SSM_E_FAIL;
 
+    std::map<std::string, std::vector<ContextData> >    returnData;
+    std::vector<ContextData>                            contextDataList;
+
     for (unsigned int i = 0; i < m_relatedSoftSensor[primitiveSensor].size(); ++i)
     {
         std::string softSensorName = m_relatedSoftSensor[primitiveSensor][i];
@@ -253,24 +239,26 @@ std::map<std::string, std::vector<ContextData> >  CContextExecutor::getPreparedC
         {
             ret = SSM_S_OK;
             std::vector<std::string> inputList = m_registeredResources[softSensorName]->inputList;
-            std::vector<ContextData> contextDataList;
             for (unsigned int j = 0; j < inputList.size(); j++) //check all "inputlist" arrived or not
             {
                 if (m_storedPrimitiveSensorData.find(inputList[j]) == m_storedPrimitiveSensorData.end())
                 {
+                    //Still we have partial data
                     ret = SSM_E_FAIL;
                     break;
                 }
                 else
                 {
-                    std::vector<ContextData> primitiveSensorData = m_storedPrimitiveSensorData[inputList[j]];
-                    for (unsigned k = 0; k < primitiveSensorData.size(); k++)
+                    //Copy all properties of current primitiveSensor data to outputs
+                    for (std::vector<ContextData>::iterator itor = m_storedPrimitiveSensorData[inputList[j]].begin();
+                         itor != m_storedPrimitiveSensorData[inputList[j]].end(); ++itor)
                     {
-                        contextDataList.push_back(primitiveSensorData[k]);
+                        contextDataList.push_back(*itor);
                     }
                 }
             }
 
+            //We have all inputs
             if (ret == SSM_S_OK)
             {
                 returnData.insert(std::make_pair(softSensorName, contextDataList));
@@ -296,27 +284,14 @@ int CContextExecutor::onEvent(std::string type, TypeofEvent callType,
         //find soft sensor
         std::map<std::string, std::vector<ContextData> > readyContextList = getPreparedContextList(type);
 
-        if (readyContextList.size() > 0)
+        //Run SoftSensor!  readyContextList has all data for run
+        std::map<std::string, std::vector<ContextData> >::iterator iter;
+        for (iter = readyContextList.begin(); iter != readyContextList.end(); ++iter)
         {
-            //Run SoftSensor!  readyContextList has all data for run
-            std::map<std::string, std::vector<ContextData> >::iterator iter = readyContextList.begin();
-            for (; iter != readyContextList.end(); ++iter)
-            {
-                std::string softSensorName = iter->first;
-                std::vector<ContextData> inputData = iter->second;
-                std::string errorMsg = checkError(inputData);
+            std::string softSensorName = iter->first;
+            std::vector<ContextData> inputData = iter->second;
 
-                if (!errorMsg.compare("OK"))
-                {
-                    runLogic(inputData, softSensorName);
-                }
-                else
-                {
-                    inputData.clear();
-                    inputData.push_back(makeErrorContextData(softSensorName, errorMsg));
-                    addOutput(inputData);
-                }
-            }
+            runLogic(inputData, softSensorName);
         }
     }
     else //This data is primitive
@@ -421,18 +396,4 @@ void CContextExecutor::runLogic(std::vector<ContextData> inputData, std::string
         m_ctxEventList[softSensor]->onCtxEvent(SPF_START, inputData);
     }
     m_mtxLibraryIO.unlock();
-}
-
-ContextData CContextExecutor::makeErrorContextData(std::string rootName, std::string errMsg)
-{
-    std::map<std::string, std::string> errorMap;
-    ContextData errorContextData;
-
-    errorMap.insert(std::make_pair("error", errMsg));
-    errorMap.insert(std::make_pair("available", "false"));
-    errorContextData.rootName = rootName;
-    errorContextData.outputPropertyCount = 2;
-    errorContextData.outputProperty.push_back(errorMap);
-
-    return errorContextData;
 }
\ No newline at end of file
index c8f88a9..6b3a6c9 100644 (file)
@@ -214,9 +214,6 @@ class CContextExecutor :
         std::map<std::string, std::vector<ContextData> >  getPreparedContextList(
             IN std::string primitiveSensor);
         void runLogic(IN std::vector<ContextData> inputData, IN std::string softSensor);
-        ContextData makeErrorContextData(IN std::string rootName, IN std::string errMsg);
-        std::string checkError(IN std::vector<ContextData> data);
-
 };
 
 #endif
index f6c6423..ce571d6 100644 (file)
@@ -65,23 +65,43 @@ void CContextRepository::finalRelease()
 {
 }
 
-void CContextRepository::setCurrentDeviceInfo(IN std::string name, IN std::string type,
+SSMRESULT CContextRepository::initRepository(IN std::string name, IN std::string type,
         IN std::string pathSoftSensors, IN std::string pathDescription)
 {
-    //TODO: Someone need to provides a way to generate permanent uuid function
-    /*
-    m_currentDeviceInfo.friendlyName = name;
-    //m_currentDeviceInfo.ID="2fac1234-31f8-11b4-a222-08002b34c003";
-    m_currentDeviceInfo.ID = udn;
-    m_currentDeviceInfo.IPAddress = "127.0.0.1";
-    m_currentDeviceInfo.tp = tp;
-    //m_currentDeviceInfo.type = SSM_DEVICE_MOBILE;
-    m_currentDeviceInfo.type = td;
-    */
+    SSMRESULT res = SSM_E_FAIL;
+
+    std::vector<DictionaryData> dict;
+
     m_name = name;
     m_type = type;
-    m_pathSoftSensors = pathSoftSensors;
-    m_pathSoftSensorsDescription = pathDescription;
+
+    if (pathSoftSensors.length() == 0)
+    {
+        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
+        m_pathSoftSensors.append("/");
+    }
+    else
+    {
+        m_pathSoftSensors = pathSoftSensors;
+    }
+
+    if (pathDescription.length() == 0)
+    {
+        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensorsDescription));
+        m_pathSoftSensorsDescription.append("/");
+        m_pathSoftSensorsDescription.append(DEFAULT_PATH_SOFT_SENSORS);
+    }
+    else
+    {
+        m_pathSoftSensorsDescription = pathDescription;
+    }
+
+
+    SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
+    SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, &m_lstSoftSensor));
+
+CLEANUP:
+    return res;
 }
 
 SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
@@ -118,7 +138,7 @@ SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
             keyStr = subItem->name();  // key
             valueStr = subItem->value();   // value
 
-            if (!keyStr.compare("root_name"))
+            if (!keyStr.compare("name"))
             {
                 dictionaryData.rootName = trim_both(valueStr);
             }
@@ -131,58 +151,29 @@ SSMRESULT CContextRepository::loadXMLFromString(char *xmlData,
                 keyStr = subItem2->name();  // key
                 valueStr = subItem2->value();   // value
 
-                if (!keyStr.compare("attribute_property_count"))
-                {
-                    dictionaryData.attributePropertyCount = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("output_property_count"))
-                {
-                    dictionaryData.outputPropertyCount  = trim_both(valueStr);
-                }
-                if (!keyStr.compare("inputs_count"))
-                {
-                    dictionaryData.inputCount = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("app_inputs_count"))
-                {
-                    dictionaryData.appInputCount  = trim_both(valueStr);
-                }
-                else if (!keyStr.compare("app_input"))
-                {
-                    dictionaryData.appInputs.push_back(trim_both(valueStr));
-                }
-                else if (!keyStr.compare("input"))
+                if (!keyStr.compare("input"))
                 {
                     dictionaryData.inputs.push_back(trim_both(valueStr));
                 }
                 ////std::cout<<name << " :: " << subItem2->value() <<std::endl<<std::endl;
                 for (subItem3 = subItem2->first_node(); subItem3 ; subItem3 = subItem3->next_sibling())
                 {
-
                     std::string newKeyStr = subItem3->name();  // key
                     valueStr = subItem3->value();   // value
 
-                    if (!keyStr.compare("attribute_property") || !keyStr.compare("output_property") )
-                    {
-                        propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)))    ;
-                    }
-                    else if (!keyStr.compare("enter_condition"))
+                    if (!keyStr.compare("attribute") || !keyStr.compare("output") )
                     {
-                        enterconditionVector.push_back(trim_both(valueStr));
+                        propertyMap.insert(std::make_pair(trim_both(newKeyStr), trim_both(valueStr)));
                     }
                 }
-                if (!keyStr.compare("attribute_property"))
+                if (!keyStr.compare("attribute"))
                 {
                     dictionaryData.attributeProperty.push_back(propertyMap);
                 }
-                else if (!keyStr.compare("output_property"))
+                else if (!keyStr.compare("output"))
                 {
                     dictionaryData.outputProperty.push_back(propertyMap);
                 }
-                else if (!keyStr.compare("enter_condition"))
-                {
-                    dictionaryData.enterConditions.push_back(enterconditionVector);
-                }
             }
         }
         //for accurate data.
@@ -208,22 +199,6 @@ SSMRESULT CContextRepository::loadXMLFromFile(std::string descriptionFilePath,
     SSMRESULT res = SSM_E_FAIL;
     std::basic_ifstream< char > xmlFile(descriptionFilePath.c_str());
 
-    if (descriptionFilePath.length() > 0 && xmlFile.fail())
-    {
-        //error while opening given path, return error
-        SSM_CLEANUP_ASSERT(SSM_E_FAIL);
-    }
-
-    if (descriptionFilePath.length() == 0)
-    {
-        //No given path, try to open local Path
-        std::string path;
-        SSM_CLEANUP_ASSERT(GetCurrentPath(&path));
-        path.append("/");
-        path.append(DEFAULT_PATH_SOFT_SENSORS);
-        xmlFile.open(path);
-    }
-
     //path loaded
     if (!xmlFile.fail())
     {
@@ -250,23 +225,20 @@ CLEANUP:
 
 SSMRESULT CContextRepository::getSoftSensorList(OUT std::vector<ISSMResource *> *pSoftSensorList)
 {
-    SSMRESULT res = SSM_E_FAIL;
-    std::vector<DictionaryData> dict;
-
-    SSM_CLEANUP_ASSERT(loadXMLFromFile(m_pathSoftSensorsDescription.c_str(), &dict));
-
-    SSM_CLEANUP_ASSERT(makeSSMResourceListForDictionaryData(dict, pSoftSensorList));
+    for (size_t i = 0; i < m_lstSoftSensor.size(); i++)
+    {
+        pSoftSensorList->push_back(m_lstSoftSensor.at(i));
+    }
 
-CLEANUP:
-    return res;
+    return SSM_S_OK;
 }
 
 SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResource *>
         *pPrimitiveSensorList)
 {
-    for (size_t i = 0; i < m_lstSensor.size(); i++)
+    for (size_t i = 0; i < m_lstPrimitiveSensor.size(); i++)
     {
-        pPrimitiveSensorList->push_back(m_lstSensor.at(i));
+        pPrimitiveSensorList->push_back(m_lstPrimitiveSensor.at(i));
     }
 
     return SSM_S_OK;
@@ -274,7 +246,7 @@ SSMRESULT CContextRepository::getPrimitiveSensorList(OUT std::vector<ISSMResourc
 
 SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
 {
-    m_lstSensor.push_back(pSensor);
+    m_lstPrimitiveSensor.push_back(pSensor);
 
     for (size_t i = 0; i < m_resourceEvents.size(); i++)
     {
@@ -287,11 +259,11 @@ SSMRESULT CContextRepository::onResourceFound(IN ISSMResource *pSensor)
 SSMRESULT CContextRepository::onResourceLost(IN ISSMResource *pSensor)
 {
     std::vector<ISSMResource *>::iterator    itor;
-    itor = std::find(m_lstSensor.begin(), m_lstSensor.end(), pSensor);
+    itor = std::find(m_lstPrimitiveSensor.begin(), m_lstPrimitiveSensor.end(), pSensor);
 
-    if (itor != m_lstSensor.end())
+    if (itor != m_lstPrimitiveSensor.end())
     {
-        m_lstSensor.erase(itor);
+        m_lstPrimitiveSensor.erase(itor);
         return SSM_S_OK;
     }
 
@@ -349,13 +321,6 @@ SSMRESULT CContextRepository::loadSoftSensor(std::string softSensorName, ICtxDel
     typedef void(*InitContext)(IN ICtxDelegate *);
     InitContext InitializeContextFunction = NULL;
 
-    if (m_pathSoftSensors.length() == 0)
-    {
-        SSM_CLEANUP_ASSERT(GetCurrentPath(&m_pathSoftSensors));
-    }
-
-    m_pathSoftSensors.append("/");
-
     // load dll(so)
     res = SSM_E_FAIL;
     for (unsigned int i = 1; i <= SSM_MODEL_RETRY; ++i)
@@ -372,8 +337,7 @@ SSMRESULT CContextRepository::loadSoftSensor(std::string softSensorName, ICtxDel
         {
             InitializeContextFunction = (InitContext)GetProcAddress(hModule, "InitializeContext");
         }
-#else
-        //sstream << "/data/data/com.example.javaproject/lib/lib" << modelName <<".so" << std::ends;
+#elif defined(LINUX)
         sstream << m_pathSoftSensors << "lib" << softSensorName.c_str() << ".so" << std::ends;
 
         void *hModule = NULL;
@@ -386,8 +350,10 @@ SSMRESULT CContextRepository::loadSoftSensor(std::string softSensorName, ICtxDel
 #endif
         if (hModule == NULL)
         {
-            InitializeContextFunction = NULL;
-            continue;
+            //load library failed. raise error
+            SSM_CLEANUP_ASSERT(SSM_E_FAIL);
+            //InitializeContextFunction = NULL;
+            //continue;
         }
 
         if (InitializeContextFunction != NULL)
index 314408f..d3e13e3 100644 (file)
@@ -42,7 +42,8 @@ class CContextRepository :
 {
     private:
         CSimpleMutex                 m_mtxFileIO;
-        std::vector<ISSMResource *>   m_lstSensor;
+        std::vector<ISSMResource *>   m_lstPrimitiveSensor;
+        std::vector<ISSMResource *>   m_lstSoftSensor;
         CObjectPtr<IResourceFinder>  m_resourceFinder;
         std::string                  m_name;
         std::string                  m_type;
@@ -72,21 +73,21 @@ class CContextRepository :
 
 
         /**
-        * @fn           setCurrentDeviceInfo
-        * @brief        set device information
+        * @fn           initRepository
+        * @brief        initialize repository using given info
         *
         * @param        [in] std::string name - Device name
         * @param        [in] std::string type - Device Type
         * @param        [in] std::string pathSoftSensors - SoftSensors Repository path
         * @param        [in] std::string pathDescription - SoftSensors Description path
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void setCurrentDeviceInfo(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
-                                  IN std::string pathDescription);
+        SSMRESULT initRepository(IN std::string name, IN std::string type, IN std::string pathSoftSensors,
+                                 IN std::string pathDescription);
 
         /**
         * @fn           getSoftSensorList
diff --git a/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp b/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.cpp
deleted file mode 100644 (file)
index 67214c8..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
-#include "ResourceConnectivity.h"
-
-SSMRESULT CResourceConnectivity::finalConstruct()
-{
-    SSMRESULT res = SSM_E_FAIL;
-    OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
-                           "134.134.161.33", 56831, OC::QualityOfService::NonConfirmable);
-
-    m_pPlatform = new OC::OCPlatform(cfg);
-
-    SSM_CLEANUP_NULL_ASSERT(m_pPlatform);
-
-    res = SSM_S_OK;
-
-CLEANUP:
-    return res;
-}
-
-void CResourceConnectivity::finalRelease()
-{
-    SAFE_DELETE(m_pPlatform);
-}
-
-void *CResourceConnectivity::getPlatform()
-{
-    return m_pPlatform;
-}
diff --git a/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h b/service/soft-sensor-manager/SSMCore/src/SensorProcessor/ResourceConnectivity.h
deleted file mode 100644 (file)
index ec28c81..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/******************************************************************
-*
-* Copyright 2014 Samsung Electronics All Rights Reserved.
-*
-*
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-******************************************************************/
-#ifndef _ResourceConnectivity_H_
-#define _ResourceConnectivity_H_
-
-#include "SSMInterface/SSMCore.h"
-#include "Common/PlatformLayer.h"
-#include "Common/InternalInterface.h"
-#include "OCPlatform.h"
-
-class CResourceConnectivity :
-    public CObjectRoot<CObjectMultiThreadModel>
-    , public IResourceConnectivity
-{
-    public:
-        SSMRESULT queryInterface(const OID &objectID, IBase **ppObject)
-        {
-            if (ppObject == NULL)
-                return SSM_E_POINTER;
-
-            if (IsEqualOID(objectID, OID_IResourceConnectivity))
-            {
-                IBase *pBase = (IResourceConnectivity *)this;
-                pBase->addRef();
-                *ppObject = pBase;
-                return SSM_S_OK;
-            }
-
-            return SSM_E_NOINTERFACE;
-        }
-
-        SSMRESULT finalConstruct();
-        void finalRelease();
-
-        void *getPlatform();
-
-    private:
-        OC::OCPlatform      *m_pPlatform;
-};
-
-#endif
index dcf1f1c..0fc67b3 100644 (file)
@@ -23,12 +23,14 @@ SSMRESULT CResourceFinder::finalConstruct()
 {
     SSMRESULT res = SSM_E_FAIL;
 
+    OC::PlatformConfig cfg(OC::ServiceType::InProc, OC::ModeType::Both,
+                           "0.0.0.0", 0, OC::QualityOfService::LowQos);
+
     SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_ITasker, (IBase **)&m_pTasker));
-    SSM_CLEANUP_ASSERT(CreateGlobalInstance(OID_IResourceConnectivity,
-                                            (IBase **)&m_pResourceConnectivity));
+
+    OC::OCPlatform::Configure(cfg);
 
     m_pResourceFinderEvent = NULL;
-    m_pPlatform = (OC::OCPlatform *)m_pResourceConnectivity->getPlatform();
 
 CLEANUP:
     return res;
@@ -52,15 +54,21 @@ void CResourceFinder::onResourceFound(std::shared_ptr<OC::OCResource> resource)
         pMessage[0] = RESOURCE_DISCOVER_REQUESTPROFILE;
         pMessage[1] = (int)new std::shared_ptr<OC::OCResource>(resource);
 
+        std::string path = resource->host() + resource->uri();
+
         m_pTasker->addTask(this, pMessage);
     }
 }
 
 SSMRESULT CResourceFinder::startResourceFinder()
 {
-    //m_pPlatform->findResource("", "oc/core/service/SoftSensorManager/SoftSensor",
-    m_pPlatform->findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
-                              std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+    OCStackResult res = OC_STACK_ERROR;
+
+    res = OC::OCPlatform::findResource("", "coap://224.0.1.187/oc/core?rt=SoftSensorManager.Sensor",
+                                       std::bind(&CResourceFinder::onResourceFound, this, std::placeholders::_1));
+
+    if (res != OC_STACK_OK)
+        return SSM_E_FAIL;
 
     return SSM_S_OK;
 }
@@ -91,7 +99,7 @@ void CResourceFinder::onExecute(IN void *pArg)
             SSM_CLEANUP_ASSERT(pResourceHandler->initHandler(*pResource, this));
             m_mapResourceHandler[pResource->get()->host() + pResource->get()->uri()] = pResourceHandler;
             pResource->get()->get(queryParams, std::bind(&OICResourceHandler::onGetResourceProfile,
-                                  pResourceHandler, std::placeholders::_1, std::placeholders::_2));
+                                  pResourceHandler, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
             break;
 
         case RESOURCE_DISCOVER_SETUP_RESOURCE:
index dc1b524..0c73dc3 100644 (file)
@@ -24,6 +24,7 @@
 #include "Common/PlatformLayer.h"
 #include "Common/InternalInterface.h"
 #include "OCPlatform.h"
+#include "OCApi.h"
 
 class CResourceFinder :
     public CObjectRoot<CObjectMultiThreadModel>
@@ -90,7 +91,7 @@ CLEANUP:
 
                     m_pResource.get()->observe(OC::ObserveType::Observe, queryParams,
                                                std::bind(&OICResourceHandler::onResourceDataReceived,
-                                                         this, std::placeholders::_1, std::placeholders::_2));
+                                                         this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
 
                     return SSM_S_OK;
                 }
@@ -102,7 +103,9 @@ CLEANUP:
                     return SSM_S_OK;
                 }
 
-                void onResourceDataReceived(const OC::OCRepresentation &representation, const int &eCode)
+                void onResourceDataReceived(const OC::HeaderOptions headerOptions,
+                                            const OC::OCRepresentation &representation,
+                                            const int &eCode, const int &sequenceNumber)
                 {
                     if (eCode == 0)
                     {
@@ -121,9 +124,9 @@ CLEANUP:
                         {
                             for (size_t i = 0; i < attributeMap.size() / 3; i++)
                             {
-                                outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
-                                outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
-                                outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+                                outputProperty["name"] = attributeMap.find(toString(i * 3))->second;
+                                outputProperty["type"] = attributeMap.find(toString(i * 3 + 1))->second;
+                                outputProperty["value"] = attributeMap.find(toString(i * 3 + 2))->second;
                                 ctxData.outputProperty.push_back(outputProperty);
                             }
 
@@ -138,7 +141,8 @@ CLEANUP:
                     }
                 }
 
-                void onGetResourceProfile(const OC::OCRepresentation &representation, const int &eCode)
+                void onGetResourceProfile(const OC::HeaderOptions &headerOptions,
+                                          const OC::OCRepresentation &representation, const int &eCode)
                 {
                     //unpack attributeMap
 
@@ -162,9 +166,9 @@ CLEANUP:
                     //TODO: Temporally used for json parsing limitation
                     for (size_t i = 0; i < attributeMap.size() / 3; i++)
                     {
-                        outputProperty["name"] = attributeMap.find(std::to_string(i * 3))->second.front();
-                        outputProperty["type"] = attributeMap.find(std::to_string(i * 3 + 1))->second.front();
-                        outputProperty["value"] = attributeMap.find(std::to_string(i * 3 + 2))->second.front();
+                        outputProperty["name"] = attributeMap.find(toString(i * 3))->second;
+                        outputProperty["type"] = attributeMap.find(toString(i * 3 + 1))->second;
+                        outputProperty["value"] = attributeMap.find(toString(i * 3 + 2))->second;
                         pSSMResource->outputProperty.push_back(outputProperty);
                     }
                     /////////////////////////////////////////////////////
@@ -181,11 +185,16 @@ CLEANUP:
                 std::shared_ptr<OC::OCResource>     m_pResource;
                 IThreadClient                       *m_pResourceFinderClient;
                 IEvent                              *m_pEvent;
+
+                std::string toString(int t)
+                {
+                    std::ostringstream os;
+                    os << t;
+                    return os.str();
+                }
         };
 
         enum RESOURCE_DISCOVER_STATE {RESOURCE_DISCOVER_REQUESTPROFILE, RESOURCE_DISCOVER_SETUP_RESOURCE};
-        OC::OCPlatform                      *m_pPlatform;
-        CObjectPtr<IResourceConnectivity>   m_pResourceConnectivity;
         IResourceFinderEvent                *m_pResourceFinderEvent;
         CObjectPtr<ITasker>             m_pTasker;
         std::map<std::string , OICResourceHandler *> m_mapResourceHandler;
@@ -17,9 +17,9 @@
 * limitations under the License.
 *
 ******************************************************************/
-#include "ResponseReactor.h"
+#include "SensingEngine.h"
 
-SSMRESULT CResponseReactor::finalConstruct()
+SSMRESULT CSensingEngine::finalConstruct()
 {
     SSMRESULT res = SSM_S_OK;
 
@@ -31,12 +31,12 @@ CLEANUP:
     return res;
 }
 
-void CResponseReactor::finalRelease()
+void CSensingEngine::finalRelease()
 {
 }
 
-void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
-                                       IEvent *pEvent)
+SSMRESULT CSensingEngine::registerContext(TypeofEvent callType, ISSMResource *pSSMResource,
+        IEvent *pEvent)
 {
     m_mtxRequestedContextData.lock();
     // if already exists
@@ -53,9 +53,11 @@ void CResponseReactor::registerContext(TypeofEvent callType, ISSMResource *pSSMR
     m_pContextExecutor->registerContext(callType, pSSMResource, this);
 
     m_mtxRequestedContextData.unlock();
+
+    return SSM_S_OK;
 }
 
-void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
+SSMRESULT CSensingEngine::unregisterContext(TypeofEvent callType, ISSMResource *pSSMResource,
         IEvent *pEvent)
 {
     m_mtxUnregisterContext.lock();
@@ -70,20 +72,24 @@ void CResponseReactor::unregisterContext(TypeofEvent callType, ISSMResource *pSS
     }
 
     m_mtxUnregisterContext.unlock();
+
+    return SSM_S_OK;
 }
 
-void CResponseReactor::getList(std::vector<ISSMResource *> *pList)
+SSMRESULT CSensingEngine::getList(std::vector<ISSMResource *> *pList)
 {
     pList->clear();
 
     m_pContextRepository->getSoftSensorList(pList);
 
     m_pContextRepository->getPrimitiveSensorList(pList);
+
+    return SSM_S_OK;
 }
 
 //Dispatch to upper layer
-int CResponseReactor::onEvent(std::string type, TypeofEvent callType,
-                              std::vector<ContextData> ctxData)
+int CSensingEngine::onEvent(std::string type, TypeofEvent callType,
+                            std::vector<ContextData> ctxData)
 {
     std::map<std::string, CallbackData >::iterator  itor;
 
 
 #include "SSMInterface/SSMCore.h"
 #include "Common/PlatformLayer.h"
-
-//temp include
-#include "ContextRepository.h"
-#include "ContextExecutor.h"
+#include "Common/InternalInterface.h"
 
 /**
- * @class    CResponseReactor
- * @brief    Class for implement of reactor pattern
- *           Delegate requested context to context executor layer.
+ * @class    CSensingEngine
+ * @brief    Class for implementing main abstration of SensorProcessor
  *
  *
  * @see
  */
-class CResponseReactor :
+class CSensingEngine :
     public CObjectRoot<CObjectMultiThreadModel>
-    , public IResponseReactor
+    , public ISensingEngine
 {
     private:
         CObjectPtr<IContextRepository>  m_pContextRepository;
@@ -57,7 +53,6 @@ class CResponseReactor :
         CSimpleMutex                        m_mtxUnregisterContext;
 
     public:
-
         SSMRESULT finalConstruct();
         void finalRelease();
 
@@ -66,7 +61,7 @@ class CResponseReactor :
             if (ppObject == NULL)
                 return SSM_E_POINTER;
 
-            if (IsEqualOID(objectID, OID_IResponseReactor))
+            if (IsEqualOID(objectID, OID_ISensingEngine))
             {
                 IBase *pBase = this;
                 pBase->addRef();
@@ -85,13 +80,14 @@ class CResponseReactor :
         * @param        [in]  ISSMResource *pSSMResource -  Requested context model resource.
         * @param        [in]  IEvent *pEvent -  IEvent class for callback.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+        SSMRESULT registerContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+                                  IN IEvent *pEvent);
 
         /**
         * @fn           unregisterContext
@@ -101,13 +97,14 @@ class CResponseReactor :
         * @param        [in]  ISSMResource *pSSMResource -  Requested context model resource.
         * @param        [in]  IEvent *pEvent -  IEvent class for callback.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        void  unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource, IN IEvent *pEvent);
+        SSMRESULT  unregisterContext(IN TypeofEvent callType, IN ISSMResource *pSSMResource,
+                                     IN IEvent *pEvent);
 
         /**
         * @fn           getList
@@ -115,13 +112,13 @@ class CResponseReactor :
         *
         * @param        [out]  std::vector<ISSMResource> *pList - ISSMResource vector of low level context models or high level context models.
         *
-        * @return       void
+        * @return       SSMRESULT
         *
         * @warning
         * @exception
         * @see
         */
-        virtual void getList(OUT std::vector<ISSMResource *> *pList);
+        SSMRESULT getList(OUT std::vector<ISSMResource *> *pList);
 
         /**
         * @fn           onEvent
@@ -140,6 +137,4 @@ class CResponseReactor :
         */
         int onEvent(IN std::string name, IN TypeofEvent callType, IN std::vector<ContextData> ctxData);
 };
-
-
-#endif
+#endif
\ No newline at end of file
index 52a3596..67a1609 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../build/linux/root_path.inc
 -include ../../build/linux/environment.mk
 
 MAKE=make
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -7,15 +7,19 @@ INC_PATH=../include
 RST_NAME=release
 
 # Insert your project name.
-TARGET=ClientApp
+TARGET=SSMTesterApp
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${SRC_PATH}/ -I${INC_PATH}/ -I${OUTPUTS_DIR} -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+
 
+CXX_LIB+=${OUTPUTS_DIR}/${SSM_LIB} 
+CXX_LIB+=${OUTPUTS_DIR}/${SSMCORE_LIB} 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
-CXX_LIB+=-lpthread
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
+CXX_LIB+=-lpthread -ldl
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
 OBJPATH=${SRCLIST:.cpp=.o}
@@ -28,11 +32,11 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "--------- ClientApp Build Begin. -----------" 
+       @echo "--------- ${TARGET} Build Begin. -----------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
-${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
+${TARGET}: ${OBJLIST}
        $(CXX) $(CXX_FLAGS) -o ./${RST_NAME}/$@ $^ ${CXX_LIB}
        @echo " "
 
@@ -43,7 +47,7 @@ ${TARGET}: ${OBJLIST} ${OUTPUTS_DIR}/SSMClient.o
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/${TARGET} ${OUTPUTS_DIR}/
-       @echo "----------- ClientApp Build Successful. ------------"
+       @echo "----------- ${TARGET} Build Successful. ------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
@@ -29,6 +29,7 @@
 
 #include "OCResource.h"
 #include "OCPlatform.h"
+#include "SSMInterface.h"
 #include "SSMClient.h"
 #include "ISSMClientListener.h"
 
@@ -47,9 +48,11 @@ typedef enum
 } DIResult;
 
 class SSMTestApp: public ISSMClientListener
+    , public IQueryEngineEvent
 {
     private:
-        SSMClient m_SSMClient;
+        //SSMClient m_SSMClient;
+        SSMInterface m_SSMClient;
 
     public:
 
@@ -61,7 +64,7 @@ class SSMTestApp: public ISSMClientListener
 
         /* operations from listener interface */
         void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode);
-
+        SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult);
 };
 
 #endif /* SSMTESTAPP_H_ */
@@ -23,7 +23,6 @@
 #include <iostream>
 
 #include "SSMTestApp.h"
-#include "SSMClient.h"
 
 SSMTestApp::SSMTestApp()
 {
@@ -45,8 +44,8 @@ void SSMTestApp::displayMenu()
 /* Register Query.*/
 void SSMTestApp::registerQuery(std::string queryString)
 {
-    std::string qid;
-    SSMReturn rtn = SSM_ERROR;
+    int qid;
+    SSMRESULT rtn = SSM_E_FAIL;
 
     if (queryString.size() == 0)
     {
@@ -57,10 +56,10 @@ void SSMTestApp::registerQuery(std::string queryString)
 
     rtn = m_SSMClient.registerQuery(queryString, this, qid);
 
-    if (rtn == SSM_SUCCESS)
+    if (rtn == SSM_S_OK)
     {
         printf("The query has been registered!\n");
-        printf("QID : %s\n", qid.c_str());
+        printf("QID : %d\n", qid);
     }
     else
         printf("Error occured(%d)", rtn);
@@ -70,15 +69,15 @@ void SSMTestApp::registerQuery(std::string queryString)
 void SSMTestApp::unregisterQuery(void)
 {
     std::string qid;
-    SSMReturn rtn = SSM_ERROR;
+    SSMRESULT rtn = SSM_E_FAIL;
 
     printf("   Please Enter query string: ");
     cin.ignore();
     getline(cin, qid);
 
-    rtn = m_SSMClient.unregisterQuery(qid);
+    rtn = m_SSMClient.unregisterQuery(atoi(qid.c_str()));
 
-    if (rtn == SSM_SUCCESS)
+    if (rtn == SSM_S_OK)
         printf("The query has been unregistered!\n");
     else
         printf("Error occured(%d)\n", (int) rtn);
@@ -108,15 +107,15 @@ void SSMTestApp::onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eC
         {
             if (strcmp(itor->first.c_str(), "temperature") == 0)
             {
-                std::cout << "* Temperature : " << itor->second.front().c_str() << "℃" << std::endl;
+                std::cout << "* Temperature : " << itor->second.c_str() << "℃" << std::endl;
             }
             else if (strcmp(itor->first.c_str(), "humidity") == 0)
             {
-                std::cout << "* Humidity : " << itor->second.front().c_str() << "%" << std::endl;
+                std::cout << "* Humidity : " << itor->second.c_str() << "%" << std::endl;
             }
             else if (strcmp(itor->first.c_str(), "discomfortIndex") == 0)
             {
-                int DI = std::stoi(itor->second.front().c_str());
+                int DI = std::stoi(itor->second.c_str());
 
                 std::cout << "* DiscomfortIndex : " << DI << "%" << std::endl;
 
@@ -144,6 +143,36 @@ void SSMTestApp::onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eC
     }
 }
 
+SSMRESULT SSMTestApp::onQueryEngineEvent(int cqid, IDataReader *pResult)
+{
+    int     dataCount = 0;
+    IModelData      *pModelData = NULL;
+    std::vector<std::string>        affectedModels;
+
+    cout << "Event received! cqid = " << cqid << endl;
+
+    pResult->getAffectedModels(&affectedModels);
+
+    for (std::vector<std::string>::iterator itor = affectedModels.begin();
+         itor != affectedModels.end(); ++itor)
+    {
+        cout << "Printing " << *itor << " model" << endl;
+        pResult->getModelDataCount(*itor, &dataCount);
+        for (int i = 0; i < dataCount; i++)
+        {
+            pResult->getModelData(*itor, i, &pModelData);
+            cout << "dataId: " << pModelData->getDataId() << endl;
+            for (int j = 0; j < pModelData->getPropertyCount(); j++)
+            {
+                cout << "Type: " << pModelData->getPropertyName(j) << " Value: " << pModelData->getPropertyValue(
+                         j) << endl;
+            }
+        }
+    }
+
+    return SSM_S_OK;
+}
+
 /**
  * APP. Main Function.
  */
index eaa5630..28802e8 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -11,10 +11,11 @@ TARGET=THSensorApp
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
 CXX_LIB+=-lpthread
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -28,7 +29,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- THSensorApp Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -43,7 +44,7 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
-       @echo "----------- THSensorApp Build Successful. -------------"
+       @echo "----------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index 8431ceb..d8b5dc8 100644 (file)
@@ -35,8 +35,8 @@ using namespace std;
 #include <string>
 #include <cstdlib>
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               56830
+#define COAP_IP                 "0.0.0.0"
+#define COAP_PORT               0
 #define COAP_MODE               ModeType::Server
 #define COAP_SRVTYPE        ServiceType::InProc
 
@@ -50,27 +50,39 @@ class TemphumidResource
         /// Access this property from a TB client
         int m_humid;
         int m_temp;
-        string m_resourceUri;
+        std::string m_resourceUri;
+        std::vector<std::string> m_resourceTypes;
+        std::vector<std::string> m_resourceInterfaces;
         OCResourceHandle m_resourceHandle;
+        OCRepresentation m_resourceRep;
+        ObservationIds m_interestedObservers;
 
     public:
         /// Constructor
         TemphumidResource() :
-            m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor"), m_resourceHandle(NULL)
+            m_humid(0), m_temp(0)
         {
+            m_resourceUri = "/Thing_TempHumSensor";
+            m_resourceTypes.push_back(COAP_TYPE_NAME);
+            m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+            printf("Running thing as %s\n", m_resourceUri.c_str());
+            m_resourceRep.setUri(m_resourceUri);
+            m_resourceRep.setResourceTypes(m_resourceTypes);
+            m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
         }
 
         ~TemphumidResource()
         {
         }
 
-        void registerResource(OC::OCPlatform &platform);
+        void registerResource();
 
         OCResourceHandle getHandle();
 
-        void setRepresentation(AttributeMap &attributeMap);
+        void setResourceRepresentation(OCRepresentation &rep);
 
-        void getRepresentation(AttributeMap &attributeMap);
+        OCRepresentation getResourceRepresentation();
 };
 
 #endif /* THINGRESOURCESERVER_H_ */
index 8c32639..2950101 100644 (file)
 
 int g_Observation = 0;
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+                                    std::shared_ptr< OCResourceResponse > response);
 
 /*
  * TempResourceFunctions
  */
 
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
 {
-    string resourceURI = m_resourceUri; // URI of the resource
-    string resourceTypeName = COAP_TYPE_NAME; // resource type name.
-    string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
-                           resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+    OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+                           m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
 
     if (OC_STACK_OK != result)
     {
@@ -52,29 +48,37 @@ OCResourceHandle TemphumidResource::getHandle()
     return m_resourceHandle;
 }
 
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
 {
-    cout << "\t\t\t" << "Received representation: " << endl;
-    cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
-    cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+    int tempHumid;
+    int tempTemp;
+
+    rep.getValue("2", tempTemp);
+    rep.getValue("5", tempHumid);
 
-    m_temp = std::stoi(attributeMap["temp"][0]);
-    m_humid = std::stoi(attributeMap["humid"][0]);
+    m_humid = tempHumid;
+    m_temp = tempTemp;
+
+    cout << "\t\t\t" << "Received representation: " << endl;
+    cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+    cout << "\t\t\t\t" << "humid: " << m_temp << endl;
 }
 
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
 {
-    attributeMap["0"].push_back("temperature");
-    attributeMap["1"].push_back("int");
-
-    attributeMap["2"].push_back(to_string(m_temp));
 
-    attributeMap["3"].push_back("humidity");
-    attributeMap["4"].push_back("int");
+    // This representation is temporaily for soft-sensor-management - name, type, vale
+    m_resourceRep.setValue("0", std::string("temperature"));
+    m_resourceRep.setValue("1", std::string("int"));
+    m_resourceRep.setValue("2", std::to_string(m_temp));
+    m_resourceRep.setValue("3", std::string("humidity"));
+    m_resourceRep.setValue("4", std::string("int"));
+    m_resourceRep.setValue("5", std::to_string(m_humid));
 
-    attributeMap["5"].push_back(to_string(m_humid));
+    return m_resourceRep;
 }
 
+// Create the instance of the TemphumidResource class
 TemphumidResource g_myResource;
 
 void *TestSensorVal(void *param)
@@ -97,7 +101,7 @@ void *TestSensorVal(void *param)
             cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
                  << endl;
 
-            OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+            OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
 
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -109,8 +113,8 @@ void *TestSensorVal(void *param)
     return NULL;
 }
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+                                    std::shared_ptr< OCResourceResponse > response)
 {
     cout << "\tIn Server CPP entity handler:\n";
 
@@ -118,15 +122,16 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
 
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
 
@@ -136,20 +141,14 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 cout << "\t\t\trequestType : GET\n";
 
                 // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
                 // Process query params and do required operations ..
 
                 // Get the representation of this resource at this point and send it as response
-                OCRepresentation rep = request->getResourceRepresentation();
-                AttributeMap attributeMap;
-
-                g_myResource.getRepresentation(attributeMap);
+                OCRepresentation rep = g_myResource.getResourceRepresentation();
 
                 if (response)
                 {
                     // TODO Error Code
-                    rep.setAttributeMap(attributeMap);
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
                 }
@@ -167,7 +166,8 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             pthread_t threadId;
 
@@ -187,18 +187,20 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         std::cout << "Request invalid" << std::endl;
     }
+
+    return OC_EH_OK;
 }
 
 int main()
 {
     // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
 
     try
     {
-        OCPlatform platform(cfg);
+        OC::OCPlatform::Configure(cfg);
 
-        g_myResource.registerResource(platform);
+        g_myResource.registerResource();
 
         int input = 0;
         cout << "Type any key to terminate" << endl;
index 360f3ef..a195f01 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 BOOST=${BOOST_BASE}
@@ -11,10 +11,11 @@ TARGET=THSensorApp1
 
 CXX=g++
 CXX_FLAGS=-std=c++0x -Wall -DLINUX
-CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
+CXX_INC=-I${INC_PATH}/ -I${IOT_BASE}/include/ -I${IOT_LOG_DIR}/include/ -I${IOT_BASE}/csdk/stack/include -I${IOT_BASE}/csdk/ocsocket/include -I${IOT_BASE}/csdk/ocrandom/include -I${IOT_BASE}/csdk/logger/include -I${BOOST}
 
 CXX_LIB+=${IOT_RELEASE}/${IOT_LIB}
 CXX_LIB+=${IOT_CSDK_RELEASE}/${IOT_CSDK_LIB} 
+CXX_LIB+=${IOT_LOG_DIR}/lib/${IOT_LOG_LIB}
 CXX_LIB+=-lpthread
 
 SRCLIST=${wildcard ${SRC_PATH}/*.cpp}
@@ -28,7 +29,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- THSensorApp Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -43,7 +44,7 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/* ${OUTPUTS_DIR}/
-       @echo "----------- THSensorApp Build Successful. -------------"
+       @echo "----------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index eada4e6..b32b589 100644 (file)
@@ -35,8 +35,8 @@ using namespace std;
 #include <string>
 #include <cstdlib>
 
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               56838
+#define COAP_IP                 "0.0.0.0"
+#define COAP_PORT               0
 #define COAP_MODE               ModeType::Server
 #define COAP_SRVTYPE        ServiceType::InProc
 
@@ -50,27 +50,39 @@ class TemphumidResource
         /// Access this property from a TB client
         int m_humid;
         int m_temp;
-        string m_resourceUri;
+        std::string m_resourceUri;
+        std::vector<std::string> m_resourceTypes;
+        std::vector<std::string> m_resourceInterfaces;
         OCResourceHandle m_resourceHandle;
+        OCRepresentation m_resourceRep;
+        ObservationIds m_interestedObservers;
 
     public:
         /// Constructor
         TemphumidResource() :
-            m_humid(0), m_temp(0), m_resourceUri("/Thing_TempHumSensor1"), m_resourceHandle(NULL)
+            m_humid(0), m_temp(0)
         {
+            m_resourceUri = "/Thing_TempHumSensor1";
+            m_resourceTypes.push_back(COAP_TYPE_NAME);
+            m_resourceInterfaces.push_back(DEFAULT_INTERFACE);
+
+            printf("Running thing as %s\n", m_resourceUri.c_str());
+            m_resourceRep.setUri(m_resourceUri);
+            m_resourceRep.setResourceTypes(m_resourceTypes);
+            m_resourceRep.setResourceInterfaces(m_resourceInterfaces);
         }
 
         ~TemphumidResource()
         {
         }
 
-        void registerResource(OC::OCPlatform &platform);
+        void registerResource();
 
         OCResourceHandle getHandle();
 
-        void setRepresentation(AttributeMap &attributeMap);
+        void setResourceRepresentation(OCRepresentation &rep);
 
-        void getRepresentation(AttributeMap &attributeMap);
+        OCRepresentation getResourceRepresentation();
 };
 
 #endif /* THINGRESOURCESERVER_H_ */
index b1d3857..6652fef 100644 (file)
 
 int g_Observation = 0;
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response);
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+                                    std::shared_ptr< OCResourceResponse > response);
 
 /*
- * TempResourceFunctions
- */
+* TempResourceFunctions
+*/
 
-void TemphumidResource::registerResource(OC::OCPlatform &platform)
+void TemphumidResource::registerResource()
 {
-    string resourceURI = m_resourceUri; // URI of the resource
-    string resourceTypeName = COAP_TYPE_NAME; // resource type name.
-    string resourceInterface = DEFAULT_INTERFACE; // resource interface.
-
     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
 
     // This will internally create and register the resource.
-    OCStackResult result = platform.registerResource(m_resourceHandle, resourceURI,
-                           resourceTypeName, resourceInterface, &entityHandler, resourceProperty);
+    OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle, m_resourceUri,
+                           m_resourceTypes[0], m_resourceInterfaces[0], &entityHandler, resourceProperty);
 
     if (OC_STACK_OK != result)
     {
@@ -52,29 +48,37 @@ OCResourceHandle TemphumidResource::getHandle()
     return m_resourceHandle;
 }
 
-void TemphumidResource::setRepresentation(AttributeMap &attributeMap)
+void TemphumidResource::setResourceRepresentation(OCRepresentation &rep)
 {
-    cout << "\t\t\t" << "Received representation: " << endl;
-    cout << "\t\t\t\t" << "temp: " << attributeMap["temp"][0] << endl;
-    cout << "\t\t\t\t" << "humid: " << attributeMap["humid"][0] << endl;
+    int tempHumid;
+    int tempTemp;
+
+    rep.getValue("2", tempTemp);
+    rep.getValue("5", tempHumid);
 
-    m_temp = std::stoi(attributeMap["temp"][0]);
-    m_humid = std::stoi(attributeMap["humid"][0]);
+    m_humid = tempHumid;
+    m_temp = tempTemp;
+
+    cout << "\t\t\t" << "Received representation: " << endl;
+    cout << "\t\t\t\t" << "temp: " << m_humid << endl;
+    cout << "\t\t\t\t" << "humid: " << m_temp << endl;
 }
 
-void TemphumidResource::getRepresentation(AttributeMap &attributeMap)
+OCRepresentation TemphumidResource::getResourceRepresentation()
 {
-    attributeMap["0"].push_back("temperature");
-    attributeMap["1"].push_back("int");
-
-    attributeMap["2"].push_back(to_string(m_temp));
 
-    attributeMap["3"].push_back("humidity");
-    attributeMap["4"].push_back("int");
+    // This representation is temporaily for soft-sensor-management - name, type, vale
+    m_resourceRep.setValue("0", std::string("temperature"));
+    m_resourceRep.setValue("1", std::string("int"));
+    m_resourceRep.setValue("2", std::to_string(m_temp));
+    m_resourceRep.setValue("3", std::string("humidity"));
+    m_resourceRep.setValue("4", std::string("int"));
+    m_resourceRep.setValue("5", std::to_string(m_humid));
 
-    attributeMap["5"].push_back(to_string(m_humid));
+    return m_resourceRep;
 }
 
+// Create the instance of the TemphumidResource class
 TemphumidResource g_myResource;
 
 void *TestSensorVal(void *param)
@@ -97,7 +101,7 @@ void *TestSensorVal(void *param)
             cout << "Notifying observers with resource handle: " << g_myResource.getHandle()
                  << endl;
 
-            OCStackResult result = OCPlatform::notifyObservers(g_myResource.getHandle());
+            OCStackResult result = OCPlatform::notifyAllObservers(g_myResource.getHandle());
 
             if (OC_STACK_NO_OBSERVERS == result)
             {
@@ -109,8 +113,8 @@ void *TestSensorVal(void *param)
     return NULL;
 }
 
-void entityHandler(std::shared_ptr< OCResourceRequest > request,
-                   std::shared_ptr< OCResourceResponse > response)
+OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request,
+                                    std::shared_ptr< OCResourceResponse > response)
 {
     cout << "\tIn Server CPP entity handler:\n";
 
@@ -118,15 +122,16 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         // Get the request type and request flag
         std::string requestType = request->getRequestType();
-        RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
+        int requestFlag = request->getRequestHandlerFlag();
 
-        if (requestFlag == RequestHandlerFlag::InitFlag)
+        if (requestFlag & RequestHandlerFlag::InitFlag)
         {
             cout << "\t\trequestFlag : Init\n";
 
             // entity handler to perform resource initialization operations
         }
-        else if (requestFlag == RequestHandlerFlag::RequestFlag)
+
+        if (requestFlag & RequestHandlerFlag::RequestFlag)
         {
             cout << "\t\trequestFlag : Request\n";
 
@@ -136,20 +141,14 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 cout << "\t\t\trequestType : GET\n";
 
                 // Check for query params (if any)
-                QueryParamsMap queryParamsMap = request->getQueryParameters();
-
                 // Process query params and do required operations ..
 
                 // Get the representation of this resource at this point and send it as response
-                OCRepresentation rep = request->getResourceRepresentation();
-                AttributeMap attributeMap;
-
-                g_myResource.getRepresentation(attributeMap);
+                OCRepresentation rep = g_myResource.getResourceRepresentation();
 
                 if (response)
                 {
                     // TODO Error Code
-                    rep.setAttributeMap(attributeMap);
                     response->setErrorCode(200);
                     response->setResourceRepresentation(rep, DEFAULT_INTERFACE);
                 }
@@ -167,7 +166,8 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
                 // DELETE request operations
             }
         }
-        else if (requestFlag == RequestHandlerFlag::ObserverFlag)
+
+        if (requestFlag & RequestHandlerFlag::ObserverFlag)
         {
             pthread_t threadId;
 
@@ -178,7 +178,7 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
 
             if (!startedThread)
             {
-                pthread_create(&threadId, NULL, TestSensorVal, (void *) NULL);
+                pthread_create(&threadId, NULL, TestSensorVal, (void *)NULL);
                 startedThread = 1;
             }
         }
@@ -187,19 +187,20 @@ void entityHandler(std::shared_ptr< OCResourceRequest > request,
     {
         std::cout << "Request invalid" << std::endl;
     }
+
+    return OC_EH_OK;
 }
 
 int main()
 {
     // Create PlatformConfig object
-
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::NonConfirmable);
+    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, OC::QualityOfService::LowQos);
 
     try
     {
-        OCPlatform platform(cfg);
+        OC::OCPlatform::Configure(cfg);
 
-        g_myResource.registerResource(platform);
+        g_myResource.registerResource();
 
         int input = 0;
         cout << "Type any key to terminate" << endl;
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/CMakeLists.txt
deleted file mode 100644 (file)
index 95611d0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(oic)
-
-SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
-SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
-SET(EX_SERVER "simpleserver")
-SET(EX_CLIENT "simpleclient")
-SET(EX_CLIENTSERVER "simpleclientserver")
-SET(OCTBSTACK "octbstack")
-
-INCLUDE_DIRECTORIES(include)
-INCLUDE_DIRECTORIES(csdk/stack/include)
-INCLUDE_DIRECTORIES(csdk/ocsocket/include)
-INCLUDE_DIRECTORIES(csdk/ocrandom/include)
-INCLUDE_DIRECTORIES(csdk/logger/include)
-INCLUDE_DIRECTORIES(csdk/libcoap-4.1.1)
-INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
-LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
-
-#SET(EXTRA_CXXFLAGS "-std=c++11")
-SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
-SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
-
-SET(SRCS
-       OCLib/OCReflect.cpp
-       OCLib/OCPlatform.cpp
-       OCLib/OCResource.cpp
-       OCLib/OCUtilities.cpp
-       OCLib/InProcServerWrapper.cpp
-       OCLib/InProcClientWrapper.cpp)
-ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
-
-ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
-TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
-INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
-
-ADD_SUBDIRECTORY(csdk)
-#ADD_SUBDIRECTORY(examples)
-ADD_SUBDIRECTORY(oic-sample)
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/build.sh
deleted file mode 100644 (file)
index 7b56050..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-# Prevent Support Tool(Defect analysis and commit) Execution Batch File!!
-
-# variables
-SDBPATH=/home/iotivity/tizen-sdk/tools/sdb
-GBSRPMPATH=/home/iotivity/GBS-ROOT/rsa/local/repos/rsa/armv7l/RPMS
-PACKAGE=oic-0.0.1-0.armv7l.rpm
-
-gbs build -A armv7l --include-all --ccache
-
-$SDBPATH root on
-
-$SDBPATH push $GBSRPMPATH/$PACKAGE /root/
-
-$SDBPATH shell rpm -Uvh --force /root/oic-0.0.1-0.armv7l.rpm
-
-$SDBPATH shell /usr/apps/com.samsung.oicapp-test/bin/oicapp-test
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.rule
deleted file mode 100644 (file)
index fad1929..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-com.samsung.oicapp-test system::use_internet r
-
-system::use_internet com.samsung.oicapp-test r
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/com.samsung.oicapp-test.xml
deleted file mode 100644 (file)
index 5a79f6e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.oicapp-test" version="0.1.0" install-location="internal-only">
-       <label>OIC tset</label>
-       <author email="email@samsung.com" href="www.samsung.com">Name</author>
-       <description>OIC test Application</description>
-       <ui-application appid="com.samsung.oicapp-test" exec="/usr/apps/com.samsung.oicapp-test/bin/oicapp-test" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
-               <icon>com.samsung.oicapp-test.png</icon>
-               <label>OIC test</label>
-       </ui-application>
-</manifest>
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/ISSMClientListener.h
deleted file mode 100644 (file)
index f425b3d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************
- *
- * Copyright 2014 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ******************************************************************/
-
-/**
- * @file    ISSMClientListener.h
- * @brief   This file contains client listener interfaces.
- */
-
-#ifndef ISSMCLIENTLISTENER_H_
-#define ISSMCLIENTLISTENER_H_
-#include <string>
-#include "OCPlatform.h"
-
-/**
- * @brief This enum defines Soft Sensor return types
- */
-typedef enum
-{
-    SSM_SUCCESS, SSM_ERROR, SSM_ERROR_QUERY_PARSING, SSM_ERROR_NO_QUERY, SSM_ERROR_NETWORK
-} SSMReturn;
-
-using namespace OC;
-/**
- *  @brief  ISSMClientListener is a listener interface from which application is derived to get callback from SoftSensorManager service
- */
-class ISSMClientListener
-{
-    public:
-        /**
-         * @brief   onRegisterQuery is a pure virtual operation which should be implemented in applications to get callback messages.
-         * @param [in] attributeMap - A data map in which SoftSensorManager service sends sensor data with cqid.
-         * @param [in] eCode - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the appication.
-         * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-
-         */
-        virtual void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn &eCode) = 0;
-        virtual ~ISSMClientListener()
-        {
-        }
-};
-
-#endif /* ISSMCLIENTLISTENER_H_ */
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.cpp
deleted file mode 100644 (file)
index e3375f2..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-#include <iostream>
-#include <string>
-
-#include "SSMClient.h"
-#include "OCPlatform.h"
-#include "OCApi.h"
-
-const char *SSM_RESOURCE_URI = "/service/SoftSensorManager";
-
-#define SSM_RESOURCE_TYPE       = "core.SoftSensorManager"
-
-#define COAP_IP                 "134.134.161.33"
-#define COAP_PORT               5683
-#define COAP_MODE               ModeType::Client
-#define COAP_SRVTYPE            ServiceType::InProc
-
-#define COAP_SERVER_ADDR        "coap://224.0.1.187/oc/core?rt=core.SoftSensorManager"
-
-SSMClient::SSMClient()
-{
-    m_sem.create(100000);
-    m_pPlatform = NULL;
-    m_appListener = NULL;
-    m_retResponse = SSM_ERROR;
-    _findResource();
-    _createQueryEngine();
-}
-
-SSMClient::~SSMClient()
-{
-    _releaseQueryEngine(m_queryEngineId);
-    if (m_pPlatform)
-    {
-        delete m_pPlatform;
-        m_pPlatform = NULL;
-    }
-}
-
-void SSMClient::_findResource()
-{
-    // Create PlatformConfig object
-    PlatformConfig cfg(COAP_SRVTYPE, COAP_MODE, COAP_IP, COAP_PORT, QualityOfService::Confirmable);
-
-    // Create a OCPlatform instance.
-    // Note: Platform creation is synchronous call.
-    try
-    {
-        m_pPlatform = new OCPlatform(cfg);
-
-        // Find all resources
-        OCStackResult result;
-        if ((result = m_pPlatform->findResource("", COAP_SERVER_ADDR,
-                                                std::bind(&SSMClient::onFoundResource, this, std::placeholders::_1)))
-            != OC_STACK_OK)
-        {
-            delete m_pPlatform;
-            m_pPlatform = NULL;
-            return;
-        }
-
-        m_sem.wait();
-
-    }
-    catch (OCException e)
-    {
-        //log(e.what());
-    }
-}
-
-void SSMClient::_createQueryEngine(void)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("CreateQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onCreateQueryEngine, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-    {
-        return;
-    }
-
-    m_sem.wait();
-}
-
-void SSMClient::_releaseQueryEngine(std::string queryEngineId)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("ReleaseQueryEngine");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    m_SSMResource->put(rep, queryParamsMap,
-                       std::bind(&SSMClient::onReleaseQueryEngine, this, std::placeholders::_1,
-                                 std::placeholders::_2));
-
-    m_sem.wait();
-}
-
-SSMReturn SSMClient::registerQuery(std::string queryString, ISSMClientListener *listener,
-                                   std::string &cqid)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues contextQueryValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("ExecuteContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    contextQueryValue.push_back(queryString);
-
-    requestAttributeMap["contextQuery"] = contextQueryValue;
-
-    m_appListener = listener;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onRegisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-        return SSM_ERROR_NETWORK;
-
-    m_sem.wait();
-
-    if (m_retResponse == SSM_SUCCESS)
-    {
-        cqid = m_responseAttributeMap["CQID"].back();
-    }
-
-    return m_retResponse;
-}
-
-SSMReturn SSMClient::unregisterQuery(std::string cqid)
-{
-    OCRepresentation rep;
-
-    AttributeMap requestAttributeMap;
-    AttributeValues commandValue;
-    AttributeValues queryEngineIdValue;
-    AttributeValues cqidValue;
-
-    QueryParamsMap queryParamsMap;
-
-    commandValue.push_back("KillContextQuery");
-
-    requestAttributeMap["command"] = commandValue;
-
-    queryEngineIdValue.push_back(m_queryEngineId);
-
-    requestAttributeMap["queryEngineId"] = queryEngineIdValue;
-
-    cqidValue.push_back(cqid);
-
-    requestAttributeMap["CQID"] = cqidValue;
-
-    rep.setAttributeMap(requestAttributeMap);
-
-    if (m_SSMResource->put(rep, queryParamsMap,
-                           std::bind(&SSMClient::onUnregisterQuery, this, std::placeholders::_1,
-                                     std::placeholders::_2)) != OC_STACK_OK)
-        return SSM_ERROR_NETWORK;
-
-    m_sem.wait();
-
-    return m_retResponse;
-}
-
-/**
- * Callback Function List.
- */
-// Callback to found resources
-void SSMClient::onFoundResource(std::shared_ptr< OCResource > resource)
-{
-    std::string resourceURI;
-    try
-    {
-        // Do some operations with resource object.
-        if (resource)
-        {
-            // Get the resource URI
-            resourceURI = resource->uri();
-
-            if (resourceURI.compare(SSM_RESOURCE_URI) == 0)
-            {
-                m_SSMResource = resource;
-            }
-        }
-    }
-    catch (std::exception &e)
-    {
-        //log(e.what());
-    }
-
-    m_sem.release();
-}
-
-void SSMClient::onCreateQueryEngine(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-    m_queryEngineId = m_responseAttributeMap["queryEngineId"].back();
-    m_responseAttributeMap["queryEngineId"].pop_back();
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onRegisterQuery(const OCRepresentation &rep, const int eCode)
-{
-    QueryParamsMap queryParamsMap;
-
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
-    {
-        m_retResponse = SSM_ERROR_QUERY_PARSING;
-        goto CLEANUP;
-    }
-
-    m_SSMResource->observe(ObserveType::Observe, queryParamsMap,
-                           std::bind(&SSMClient::onObserve, this, std::placeholders::_1, std::placeholders::_2));
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onUnregisterQuery(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    if (m_responseAttributeMap.find("error") != m_responseAttributeMap.end())
-    {
-        m_retResponse = SSM_ERROR_NO_QUERY;
-        goto CLEANUP;
-    }
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onReleaseQueryEngine(const OCRepresentation &rep, const int eCode)
-{
-    if (eCode != 0)
-    {
-        m_retResponse = SSM_ERROR_NETWORK;
-        goto CLEANUP;
-    }
-
-    m_responseAttributeMap = rep.getAttributeMap();
-
-    m_retResponse = SSM_SUCCESS;
-
-CLEANUP: m_sem.release();
-}
-
-void SSMClient::onObserve(const OCRepresentation &rep, const int &eCode)
-{
-    SSMReturn ret = SSM_SUCCESS;
-
-    if (eCode != 0)
-    {
-        ret = SSM_ERROR_NETWORK;
-    }
-
-    m_appListener->onRegisterQuery(rep.getAttributeMap(), ret);
-}
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/oic-sample/src/SSMClient.h
deleted file mode 100644 (file)
index 1ee47bd..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 Samsung Electronics All Rights Reserved.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-
-/**
- * @file    SSMClient.h
- * @brief   This file contains the declaration of classes and its members related to SSMClient.
- */
-
-#ifndef RESOURCECLIENT_H_
-#define RESOURCECLIENT_H_
-
-#include <string>
-
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "ISSMClientListener.h"
-
-using namespace OC;
-
-#if defined(WIN32)
-class CSemaphore
-{
-    private:
-        HANDLE hSemaphore;
-        int m_MaxTimeOut;
-
-    public:
-        /**
-         * This is CSemaphore constructor.
-         */
-        CSemaphore()
-        {
-            m_MaxTimeOut = 0;
-        }
-        /**
-         *This is CSemaphore destructor.
-         */
-        ~CSemaphore()
-        {
-        }
-
-        /**
-         * This is a function to creat a semaphore
-         * This is syncronus call.
-         * @param maximumRequestTimeOut
-         *          [IN] Request Time out.
-         *
-         * @return  None
-         *
-         */
-        void create(int maximumRequestTimeOut)
-        {
-            hSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
-            m_MaxTimeOut = maximumRequestTimeOut;
-        }
-
-        /**
-         * This is a function to wait for semaphore
-         *
-         * @return  None
-         *
-         */
-        void wait()
-        {
-            WaitForSingleObject(hSemaphore, m_MaxTimeOut);
-        }
-
-        /**
-         * This is a function to release  semaphore
-         *
-         * @return  None
-         *
-         */
-        void release()
-        {
-            ReleaseSemaphore(hSemaphore, 1, NULL);
-        }
-
-};
-
-#elif defined(LINUX)
-#include <semaphore.h>
-
-#define SEM_SUCCESS     0
-
-class CSemaphore
-{
-    private:
-        sem_t hSemaphore;
-        timespec m_MaxTimeOut;
-
-    public:
-        /**
-         * This is CSemaphore constructor.
-         */
-        CSemaphore()
-        {
-            m_MaxTimeOut.tv_sec = 0;
-            m_MaxTimeOut.tv_nsec = 0;
-        }
-        /**
-         *This is CSemaphore destructor.
-         */
-        ~CSemaphore()
-        {
-        }
-        /**
-         * This is a function to creat a semaphore
-         * This is syncronus call.
-         * @param maximumRequestTimeOut
-         *          [IN] Request Time out.
-         *
-         * @return  None
-         *
-         */
-        void create(int maximumRequestTimeOut)
-        {
-            if ( sem_init(&hSemaphore, 1, 0) < SEM_SUCCESS )
-            {
-                perror("Error : sem_init.");
-                exit(0);
-            }
-            m_MaxTimeOut.tv_sec = maximumRequestTimeOut;
-        }
-
-        void wait()
-        {
-            sem_wait( &hSemaphore );
-        }
-
-        /**
-         * This is a function to release  semaphore
-         *
-         * @return  None
-         *
-         */
-        void release()
-        {
-            sem_post(&hSemaphore);
-        }
-
-};
-#endif
-
-/**
- *  @brief  SSMClient is a wrapper class to provide SoftSensorManager functionality to Application.
- *          Basically, SoftSensorManager is developed in Resource model (i.e. messaging with basic functions of put, get, and post).
- *          SSMClient abstracts the resource based operations from client applications and provides c++ style functions.
- */
-class SSMClient
-{
-    private:
-        SSMReturn m_retResponse;
-        OCPlatform *m_pPlatform;
-        CSemaphore m_sem;
-        /**
-         * @brief SoftSensorManager Resource.
-         */
-        std::shared_ptr< OCResource > m_SSMResource;
-        /**
-         * @brief attribute map .
-         */
-        AttributeMap m_responseAttributeMap;
-        /**
-         * @brief query engine.
-         */
-        std::string m_queryEngineId;
-        /**
-         * @brief app listener
-         */
-        ISSMClientListener *m_appListener;
-
-        /**
-         * @brief internal find resource function
-         */
-        void _findResource(void);
-
-        /**
-         * @brief internal Query engine function
-         */
-        void _createQueryEngine(void);
-
-        /**
-         * @brief internal release query function
-         */
-        void _releaseQueryEngine(std::string queryEngineId);
-
-    public:
-        /**
-         * Constructor for SSMClient.
-         */
-        SSMClient();
-        ~SSMClient();
-
-        /**
-         * This API sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
-         *
-         * @param [in] queryString - A conditions query statement where the caller application specifies sensors for required data and conditions when the caller wants to get the data.
-         * @param [in] listener - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the application.
-         * @param [out] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-
-         */
-        SSMReturn registerQuery(std::string queryString, ISSMClientListener *listener,
-                                std::string &cqid);
-        /**
-         * This API is to cancel the registered sends query strings of applications to SoftSensorManager on Iotivity Base messaging.
-         *
-         * @param [in] listener - The address of listener class.  When an application which inherits the ISSMClientListener calls this operation, it sends its address for the listener so that
-         *                          SSMClient can callback message to the application.
-         * @param [in] cqid - A query id generated from SoftSensorManager service for the queryString request.
-         * @return  SSMReturn
-         */
-        SSMReturn unregisterQuery(std::string cqid);
-
-        // friend option. for callback from SSMResource
-        void onFoundResource(std::shared_ptr< OCResource > resource);
-        void onCreateQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onReleaseQueryEngine(const OCRepresentation &rep, const int eCode);
-        void onRegisterQuery(const OCRepresentation &rep, const int eCode);
-        void onUnregisterQuery(const OCRepresentation &rep, const int eCode);
-        void onObserve(const OCRepresentation &rep, const int &eCode);
-};
-
-#endif /* RESOURCECLIENT_H_ */
diff --git a/service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service b/service/soft-sensor-manager/SampleApp/tizen/ClientApp/packaging/oic.service
deleted file mode 100644 (file)
index e15779f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=OIC
-After=deviced.service
-
-[Service]
-Type=simple
-ExecStart=/usr/bin/simpleserver
-TimeoutStopSec=1s
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7aa6d40
--- /dev/null
@@ -0,0 +1,45 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(ssm)
+
+SET(CMAKE_SHARED_LINKER_FLAGS " -Wl,--as-needed")
+SET(CMAKE_EXE_LINKER_FLAGS " -Wl,--as-needed -Wl,--hash-style=both")
+#SET(EX_SERVER "simpleserver")
+#SET(EX_CLIENT "simpleclient")
+#SET(EX_CLIENTSERVER "simpleclientserver")
+#SET(OCTBSTACK "octbstack")
+
+#INCLUDE_DIRECTORIES(include)
+#INCLUDE_DIRECTORIES(csdk/stack/include)
+#INCLUDE_DIRECTORIES(csdk/ocsocket/include)
+#INCLUDE_DIRECTORIES(csdk/ocrandom/include)
+#INCLUDE_DIRECTORIES(csdk/logger/include)
+#INCLUDE_DIRECTORIES(${INCLUDE_INSTALL_DIR}/boost)
+#LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
+
+#SET(EXTRA_CXXFLAGS "-std=c++11")
+#SET(EXTRA_CXXFLAGS "-g3 -std=c++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}")
+
+#SET(SRCS
+#      OCLib/OCReflect.cpp
+#      OCLib/OCPlatform.cpp
+#      OCLib/OCResource.cpp
+#      OCLib/InProcServerWrapper.cpp
+#      OCLib/InProcClientWrapper.cpp)
+#ADD_LIBRARY(${PROJECT_NAME} STATIC ${SRCS})
+
+#ADD_EXECUTABLE(${EX_SERVER} examples/simpleserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_SERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_SERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENT} examples/simpleclient.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENT} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENT} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_EXECUTABLE(${EX_CLIENTSERVER} examples/simpleclientserver.cpp)
+#TARGET_LINK_LIBRARIES(${EX_CLIENTSERVER} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+#INSTALL(TARGETS ${EX_CLIENTSERVER} DESTINATION ${BIN_INSTALL_DIR})
+
+#ADD_SUBDIRECTORY(csdk)
+#ADD_SUBDIRECTORY(examples)
+ADD_SUBDIRECTORY(oic-sample)
@@ -1,11 +1,11 @@
-SET(TESTAPP "oicapp-test")
+SET(TESTAPP "ssmtester")
 
 FILE(GLOB SRCS src/*.c src/*.cpp)
 
 SET(VENDOR "samsung")
 SET(PACKAGE ${TESTAPP})
 SET(PKGNAME "com.${VENDOR}.${PACKAGE}")
-SET(PREFIX "/usr/apps/com.samsung.oicapp-test")
+SET(PREFIX "/usr/apps/com.samsung.ssmtester")
 SET(BINDIR "${PREFIX}/bin")
 SET(RESDIR "${PREFIX}/res")
 SET(DATADIR "${PREFIX}/data")
@@ -38,8 +38,10 @@ ADD_DEFINITIONS("-DEDJDIR=\"${EDJDIR}\"")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 
+LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lib)
+
 ADD_EXECUTABLE(${TESTAPP} ${SRCS})
-TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ${PROJECT_NAME} ${OCTBSTACK} pthread)
+TARGET_LINK_LIBRARIES(${TESTAPP} ${pkgs_LDFLAGS} ssmcore oc octbstack oc_logger oc_logger_core pthread dl)
 
 INSTALL(TARGETS ${TESTAPP} DESTINATION ${BINDIR})
 
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.rule
new file mode 100644 (file)
index 0000000..701ef6f
--- /dev/null
@@ -0,0 +1,3 @@
+com.samsung.ssmtester system::use_internet r
+
+system::use_internet com.samsung.ssmtester r
diff --git a/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml b/service/soft-sensor-manager/SampleApp/tizen/SSMTesterApp/oic-sample/com.samsung.ssmtester.xml
new file mode 100644 (file)
index 0000000..ea0671f
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="com.samsung.ssmtester" version="0.1.0" install-location="internal-only">
+       <label>OIC test</label>
+       <author email="email@samsung.com" href="www.samsung.com">Name</author>
+       <description>SSM test Application</description>
+       <ui-application appid="com.samsung.ssmtester" exec="/usr/apps/com.samsung.ssmtester/bin/ssmtester" nodisplay="false" multiple="false" type="capp" taskmanage="true" mainapp="true">
+               <icon>com.samsung.oicapp-test.png</icon>
+               <label>SSM test</label>
+       </ui-application>
+</manifest>
 #include <efl_assist.h>
 
 #include <string>
+#include <sstream>
 
 #include "oicapp-test.h"
 #include "oicapp-utils.h"
 
-#include "OCResource.h"
-#include "OCPlatform.h"
-#include "SSMClient.h"
-#include "ISSMClientListener.h"
+#include "SSMInterface.h"
 
 static oicapp_data *g_ad = NULL;
 
-class CSSMClientListener: public ISSMClientListener
+int g_CQID = 9999;
+
+class CQueryEngineEvent : public IQueryEngineEvent
 {
     public:
-        void onRegisterQuery(const AttributeMap &attributeMap, SSMReturn::SSMReturn &eCode)
-        {
-            //EFL UI printing
 
-            char *queryResult = "";
+        SSMRESULT onQueryEngineEvent(int cqid, IDataReader *pResult)
+        {
             std::stringstream sstream;
 
-            for (AttributeMap::const_iterator itor = attributeMap.begin(); itor != attributeMap.end(); itor++)
+            int     dataCount = 0;
+            IModelData      *pModelData = NULL;
+            std::vector<std::string>        affectedModels;
+
+            pResult->getAffectedModels(&affectedModels);
+
+            for (std::vector<std::string>::iterator itor = affectedModels.begin();
+                 itor != affectedModels.end(); ++itor)
             {
-                //if (itor->first == "queryEngineId")
-                //{
-                //  sstream << itor->first.c_str() << " : " << std::hex << stoi(itor->second.front().c_str()) << "\n";
-                //}
-                //else
-                //{
-                sstream << itor->first.c_str() << " : " << itor->second.front().c_str() << "\n";
-                //}
+                printf("Printing %s\n", itor->c_str());
+                pResult->getModelDataCount(*itor, &dataCount);
+                for (int i = 0; i < dataCount; i++)
+                {
+                    pResult->getModelData(*itor, i, &pModelData);
+                    printf("dataId: %d\n", pModelData->getDataId());
+                    for (int j = 0; j < pModelData->getPropertyCount(); j++)
+                    {
+                        sstream << "Type: " << pModelData->getPropertyName(j).c_str() <<
+                                " Value: " << pModelData->getPropertyValue(j).c_str() << "<br>";
+                    }
+                }
             }
 
-//      queryResult = const_cast<char *>(sstream .str().c_str());
-            oicapp_util_put_msg (g_ad, g_ad->input_msg);
+            sstream << std::ends;
 
+            oicapp_util_put_msg(g_ad, sstream.str().c_str());
 
+            return SSM_S_OK;
         }
 };
 
-CSSMClientListener  *g_SSMClientListener = new CSSMClientListener();
-SSMClient           *g_SSMClient        = NULL;
+CQueryEngineEvent   *g_SSMClientListener = new CQueryEngineEvent();
+SSMInterface        *g_SSMClient = new SSMInterface();
 
 static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
         oicapp_data *ad)
@@ -64,7 +74,7 @@ static Elm_Object_Item *oicapp_append_separator(Evas_Object *genlist,
 
     item = elm_genlist_item_append(genlist, &ad->itc_seperator, NULL, NULL,
                                    ELM_GENLIST_ITEM_NONE, NULL, NULL);
-    elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
+    //elm_genlist_item_select_mode_set(item, ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY);
 
     return item;
 }
@@ -181,7 +191,7 @@ static Elm_Object_Item *_gl_append_item(oicapp_data *ad, Elm_Genlist_Item_Class
 static void oicapp_append_contents(oicapp_data *ad)
 {
     Elm_Object_Item *item;
-
+    /*
     oicapp_append_separator(ad->genlist, ad);
 
     _gl_append_item(ad, &ad->itc_edit);
@@ -196,6 +206,26 @@ static void oicapp_append_contents(oicapp_data *ad)
     ad->item_multiline = item;
 
     oicapp_append_separator(ad->genlist, ad);
+    */
+    oicapp_append_separator(ad->genlist, ad);
+
+    elm_genlist_item_append(ad->genlist, &ad->itc_edit, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    elm_genlist_item_append(ad->genlist, &ad->itc_btn, ad, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    oicapp_append_separator(ad->genlist, ad);
+
+    item = _gl_append_item(ad, &ad->itc_multiline);
+
+    ad->item_multiline = item;
+
+    oicapp_append_separator(ad->genlist, ad);
 }
 
 static Evas_Object *oicapp_create_conform(Evas_Object *win)
@@ -236,9 +266,33 @@ static void _btn_clicked(void *data, Evas_Object *obj, void *event_info)
 {
     oicapp_data *ad = (oicapp_data *)data;
 
-    std::string cqid;
+    std::string str = std::string(ad->input_msg);
+
+    std::string strGT = "&gt;";
+
+    std::string strLT = "&lt;";
+
+    std::size_t foundGT = str.find(strGT);
 
-    g_SSMClient->registerQuery(std::string(ad->input_msg), g_SSMClientListener, cqid);
+    std::size_t foundLT = str.find(strLT);
+
+    std::stringstream sstream;
+
+    if (foundGT != std::string::npos)
+    {
+        str.replace(foundGT, strGT.length(), ">");
+    }
+
+    if (foundLT != std::string::npos)
+    {
+        str.replace(foundLT, strLT.length(), "<");
+    }
+
+    g_SSMClient->registerQuery(str, g_SSMClientListener, g_CQID);
+
+    sstream << "Query executed! cqid = " << g_CQID << std::ends;
+
+    oicapp_util_put_msg(ad, sstream.str().c_str());
 
     ERR("button clicked(%s)", ad->input_msg);
 }
@@ -264,8 +318,6 @@ static void _edit_unfocused(void *data, Evas_Object *obj, void *event_info)
 
     ad->input_msg = strdup(elm_entry_entry_get(obj));
 
-//  oicapp_util_put_msg(ad, ad->input_msg);
-
     DBG("Clicked : %s", ad->input_msg);
 
 }
@@ -282,6 +334,14 @@ static Evas_Object *_gl_edit_content_get(void *data, Evas_Object *obj,
     return entry;
 }
 
+static char *_item_Text_get(void *data, Evas_Object *obj, const char *part)
+{
+    char *buf =
+        "subscribe Device.DiscomfortIndexSensor if Device.DiscomfortIndexSensor.discomfortIndex > 0";
+
+    return strdup(buf);
+}
+
 static inline void oicapp_init_itcs(oicapp_data *ad)
 {
     ad->itc_seperator.item_style = "dialogue/separator";
@@ -291,7 +351,7 @@ static inline void oicapp_init_itcs(oicapp_data *ad)
     ad->itc_seperator.func.del = NULL;
 
     ad->itc_edit.item_style = "dialogue/editfield";
-    ad->itc_edit.func.text_get = NULL;
+    ad->itc_edit.func.text_get = _item_Text_get;
     ad->itc_edit.func.content_get = _gl_edit_content_get;
     ad->itc_edit.func.state_get = NULL;
     ad->itc_edit.func.del = NULL;
@@ -304,7 +364,6 @@ static inline void oicapp_init_itcs(oicapp_data *ad)
 
     ad->itc_multiline.item_style = "multiline/1text";
     ad->itc_multiline.func.text_get = _gl_multiline_text_get;
-    //ad->itc_multiline.func.text_get = NULL;
     ad->itc_multiline.func.content_get = NULL;
     ad->itc_multiline.func.state_get = NULL;
     ad->itc_multiline.func.del = NULL;
@@ -344,7 +403,7 @@ static int oicapp_create(void *data)
 
     ad->genlist = oicapp_create_genlist(ad->navi);
 
-    it = elm_naviframe_item_push(ad->navi, "OIC Tester", NULL, NULL, ad->genlist, NULL);
+    it = elm_naviframe_item_push(ad->navi, "SSM Tester", NULL, NULL, ad->genlist, NULL);
     elm_naviframe_item_pop_cb_set(it, _back_cb, ad);
 
     ad->ip_addr = oicapp_util_wifi();
@@ -360,8 +419,6 @@ static int oicapp_create(void *data)
 
     oicapp_append_contents(ad);
 
-    g_SSMClient = new SSMClient();
-
     return 0;
 }
 
@@ -369,6 +426,9 @@ static int oicapp_terminate(void *data)
 {
     oicapp_data *ad = (oicapp_data *)data;
 
+    if (g_CQID != 9999)
+        g_SSMClient->unregisterQuery(g_CQID);
+
     if (ad->win)
         evas_object_del(ad->win);
 
@@ -63,6 +63,7 @@ void oicapp_util_put_msg(oicapp_data *ad, const char *msg)
        DBG("Output msg : %s", ad->output_msg);
 
        elm_genlist_item_update(ad->item_multiline);
+       elm_genlist_item_item_class_update(ad->item_multiline, &(ad->itc_multiline));
 }
 
 char* oicapp_util_wifi()
@@ -1,16 +1,17 @@
-Name:       oic
+Name:       ssm
 Summary:    Open Interconnect Consortium
 Version:       0.0.1
 Release:    0
 Group:      Network & Connectivity/Service
 License:    Apache-2.0
 Source0:    %{name}-%{version}.tar.gz
-Source1:    %{name}.service
+Source1:    libDiscomfortIndexSensor.so
+Source2:    SoftSensorDescription.xml
 Source1001:    %{name}.manifest
 BuildRequires: cmake
-BuildRequires: boost-devel
+#BuildRequires: boost-devel
 #BuildRequires: pkgconfig(glib-2.0)
-Buildrequires: gettext-tools
+#Buildrequires: gettext-tools
 BuildRequires: pkgconfig(appcore-efl)
 BuildRequires: pkgconfig(ecore-x)
 BuildRequires: pkgconfig(elementary)
@@ -32,8 +33,10 @@ cp %{SOURCE1001} .
 
 
 %install
-rm -rf %{buildroot}/BUILD/oic*
+rm -rf %{buildroot}/BUILD/ssm*
 #%make_install
+cp -af %{SOURCE1} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
+cp -af %{SOURCE2} %{buildroot}/usr/apps/com.samsung.ssmtester/bin/
 
 %post
 
@@ -44,8 +47,7 @@ rm -rf %{buildroot}/BUILD/oic*
 %files
 %manifest %{name}.manifest
 %defattr(-,root,root,-)
-%{_bindir}/simple*
-/usr/apps/com.samsung.oicapp-test/*
+/usr/apps/com.samsung.ssmtester/*
 /usr/share/*
-/etc/smack/accesses2.d/com.samsung.oicapp-test.rule
+/etc/smack/accesses2.d/com.samsung.ssmtester.rule
 #%%license LICENSE.APLv2
diff --git a/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml b/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/SoftSensorDescription.xml
new file mode 100644 (file)
index 0000000..7910214
--- /dev/null
@@ -0,0 +1,41 @@
+<softsensors>
+       
+  <softsensor>
+    <name>DiscomfortIndexSensor</name>
+    <attributes>
+      <attribute>
+        <name>version</name>
+        <type>string</type>
+        <value>1.0</value>
+      </attribute>
+      <attribute>
+        <name>lifetime</name>
+        <type>int</type>
+        <value>60</value>
+      </attribute>
+    </attributes>
+    <outputs>
+      <output>
+        <name>timestamp</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>temperature</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>humidity</name>
+        <type>string</type>
+      </output>
+      <output>
+        <name>discomfortIndex</name>
+        <type>int</type>
+      </output>
+    </outputs>
+    <inputs>
+      <input>Thing_TempHumSensor</input>
+      <input>Thing_TempHumSensor1</input>
+    </inputs>
+  </softsensor>
+  
+</softsensors>
diff --git a/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml b/service/soft-sensor-manager/SoftSensorPlugin/DiscomfortIndexSensor/build/linux/HighContextDictionary.xml
deleted file mode 100644 (file)
index 4e5e413..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-<high_context_dictionary>
-       
-  <high_context>
-    <root_name>DiscomfortIndexSensor</root_name>
-    <attributes>
-      <attribute_property_count>2</attribute_property_count>
-      <attribute_property>
-        <name>version</name>
-        <type>string</type>
-        <value>1.0</value>
-      </attribute_property>
-      <attribute_property>
-        <name>lifetime</name>
-        <type>int</type>
-        <value>60</value>
-      </attribute_property>
-    </attributes>
-    <outputs>
-      <output_property_count>4</output_property_count>
-      <output_property>
-        <name>timestamp</name>
-        <type>string</type>
-        <value>&quot;&quot;</value>
-      </output_property>
-      <output_property>
-        <name>temperature</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-      <output_property>
-        <name>humidity</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-      <output_property>
-        <name>discomfortIndex</name>
-        <type>int</type>
-        <value>0</value>
-      </output_property>
-    </outputs>
-    <app_inputs>
-      <app_input_count>0</app_input_count>
-    </app_inputs>
-    <inputs>
-      <input_count>2</input_count>
-      <input>Thing_TempHumSensor</input>
-      <input>Thing_TempHumSensor1</input>
-    </inputs>
-    <enter_conditions>
-      <enter_condition>
-        <name>Thing_TempHumSensor</name>
-        <name>Thing_TempHumSensor1</name>
-      </enter_condition>
-    </enter_conditions>
-  </high_context>
-  
-</high_context_dictionary>
index 4fc2c18..4aae123 100644 (file)
@@ -1,4 +1,4 @@
-
+-include ../../../../build/linux/root_path.inc
 -include ../../../../build/linux/environment.mk
 
 SRC_PATH=../../src
@@ -23,7 +23,7 @@ all: pre_job ${TARGET} post_job
 
 pre_job:
        @echo " " 
-       @echo "---------- SoftSensor Build Begin. ------------" 
+       @echo "---------- ${TARGET} Build Begin. ------------" 
        @mkdir -p ${RST_NAME}
        @echo " "
 
@@ -38,8 +38,8 @@ ${TARGET}: ${OBJLIST}
 post_job:
        @echo " " 
        cp -Rdp ./${RST_NAME}/lib${TARGET}.so ${OUTPUTS_DIR}/
-       cp -Rdp ./HighContextDictionary.xml ${OUTPUTS_DIR}/
-       @echo "-------------- SoftSensor Build Successful. -------------"
+       cp -Rdp ../../${SSXML_NAME} ${OUTPUTS_DIR}/
+       @echo "-------------- ${TARGET} Build Successful. -------------"
        @echo "Enter to ${RST_NAME} folder."
        @echo " " 
        
index aebbf9b..2dfe1a7 100644 (file)
@@ -180,6 +180,9 @@ DIResult DiscomfortIndexSensor::makeDiscomfortIndex(InValue *data)
     int discomfortIndex = (int) ERROR;
     double sumDI = 0.0;
 
+    m_result.m_temperature = "";
+    m_result.m_humidity = "";
+
     for (int i = 0; i < PHYSICAL_EA; i++)
     {
         if (i != 0)
@@ -256,14 +259,14 @@ ContextData DiscomfortIndexSensor::setOutput(int property_count, InValue *data)
 
     output_property.clear();
     output_property.insert(std::make_pair("name", "temperature"));
-    output_property.insert(std::make_pair("type", "int"));
+    output_property.insert(std::make_pair("type", "string"));
     output_property.insert(std::make_pair("value", m_result.m_temperature));
 
     out.outputProperty.push_back(output_property);
 
     output_property.clear();
     output_property.insert(std::make_pair("name", "humidity"));
-    output_property.insert(std::make_pair("type", "int"));
+    output_property.insert(std::make_pair("type", "string"));
     output_property.insert(std::make_pair("value", m_result.m_humidity));
 
     out.outputProperty.push_back(output_property);
index ee41b51..2b79304 100644 (file)
@@ -1,4 +1,7 @@
+IOTIVITY_DIR=${shell cd ../../../../ && pwd}
+${shell echo "ROOT_DIR=${IOTIVITY_DIR}" > ./root_path.inc}
 
+-include ./root_path.inc
 -include ./environment.mk
 
 MAKE=make
@@ -21,7 +24,6 @@ pre_job:
        @echo "*                                                       *"
        @echo "* It's build script for SoftSensorManagement system.    *"
        @echo "* Before build, Open the environment.mk file.           *"
-       @echo "* And, Modify ROOT_DIR path, which depend on your PC.   *"
        @echo "* And, Modify BOOST_BASE path, which depend on your PC. *"
        @echo "*                                                       *"
        @echo "*********************************************************" 
@@ -51,13 +53,10 @@ post_job:
 
 clean:
        
-#      @cd ${CUR_DIR}/../../../resource/ && make clean
-#      @cd ${CUR_DIR}/../../../resource/csdk && make deepclean
-#      @cd ${CUR_DIR}/9_Arduino_THSensorApp && make clean
-#      @cd ${CUR_DIR} 
        rm -rf ./${RST_NAME}
        @for subdir in ${MAKE_LIST} ; do \
        echo ">>>>>>>>>>>> $${subdir}/Makefile clean run <<<<<<<<<<<<<<" ; \
        ${MAKE} clean -C $${subdir} ; \
        echo " " ; \
        done
+       rm -rf ./root_path.inc
index c10c51f..6652271 100644 (file)
@@ -1,16 +1,15 @@
-# root path of each PC.
-ROOT_DIR=${PWD}/../../../..
-
 # boost folder path.
-BOOST_BASE=/home/iotivity/Desktop/boost_1_56_0
+BOOST_BASE=/usr/include
 
 # ioc-resource folder path.
 IOT_BASE=${ROOT_DIR}/resource
 IOT_MAKE_PATH=${IOT_BASE}
 IOT_RELEASE=${IOT_MAKE_PATH}/release/obj
-IOT_CSDK_RELEASE=${IOT_BASE}/csdk/release
+IOT_CSDK_RELEASE=${IOT_BASE}/csdk/linux/release
+IOT_LOG_DIR=${IOT_BASE}/oc_logger
 IOT_LIB=liboc.a
 IOT_CSDK_LIB=liboctbstack.a
+IOT_LOG_LIB=liboc_logger.a
 
 # service folder path.
 FD_SSM=${ROOT_DIR}/service/soft-sensor-manager
@@ -23,15 +22,18 @@ FD_BUILD=${FD_SSM}/build
 # outputs directory path.
 OUTPUTS_DIR=${FD_BUILD}/linux/release
 EXEC_DIR=${OUTPUTS_DIR}
-MODEL_DIR="\"${EXEC_DIR}/\""
-HIGH_LOCATION="\"${EXEC_DIR}/HighContextDictionary.xml\""
+SSXML_NAME="SoftSensorDescription.xml"
+SSM_LIB = libSSM.a
+SSMCORE_LIB=libSSMCore.a
 
 # SoftSensorManager makefile path
-MAKE_01=${FD_SDK}/build/linux
-MAKE_02=${FD_SSMCORE}/build/linux
+MAKE_01=${FD_SSMCORE}/build/linux
+MAKE_02=${FD_SDK}/build/linux
 MAKE_03=${FD_SAMPLEAPP}/linux
 MAKE_04=${FD_SAMPLEAPP}/arduino
 MAKE_05=${FD_SOFTSENSOR}/DiscomfortIndexSensor/build/linux
+MAKE_06=${FD_SOFTSENSOR}/IndoorTrajectorySensor/build/linux
 
-MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}
 
+MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_06} ${MAKE_03}
+#MAKE_LIST=${MAKE_01} ${MAKE_02} ${MAKE_05} ${MAKE_03}