From 6fa3b76472189d3d623af598ff1792c5d058fe80 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sat, 30 May 2020 11:00:33 -0400 Subject: [PATCH 01/53] added new Utils class for Response, added all methods --- src/cpp/main/common/RecordUtils.cpp | 19 +++- src/cpp/main/common/RecordUtils.h | 2 + src/cpp/main/common/ResponseUtils.cpp | 144 ++++++++++++++++++++++++++ src/cpp/main/common/ResponseUtils.h | 75 ++++++++++++++ 4 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 src/cpp/main/common/ResponseUtils.cpp create mode 100644 src/cpp/main/common/ResponseUtils.h diff --git a/src/cpp/main/common/RecordUtils.cpp b/src/cpp/main/common/RecordUtils.cpp index 4388d03..d45e9a7 100644 --- a/src/cpp/main/common/RecordUtils.cpp +++ b/src/cpp/main/common/RecordUtils.cpp @@ -29,6 +29,13 @@ bool RecordUtils::isValid(struct record *record) return (bool)this->jvm->CallBooleanMethod(record->jrecord, this->isValidMethodId); } +void RecordUtils::setValid(struct record *record, bool isValid) +{ + jobject jBoolVal = jvm->NewObject(this->typeUtils->getBoolClass(), this->typeUtils->createBoolMethod(), (jboolean)isValid); + this->jvm->CallVoidMethod(record->jrecord, this->setValidMethodId, jBoolVal); + this->jvm->DeleteLocalRef(jBoolVal); +} + struct record *RecordUtils::getCopy(struct record *record) { jobject jRecordCopy = this->jvm->CallObjectMethod(record->jrecord, this->getCopyMethodId); @@ -166,6 +173,7 @@ void RecordUtils::loadMethodIds() jclass recordClass = JniUtils::getNamedClass(this->jvm, "gov/noaa/messageapi/interfaces/IRecord"); /*Intrinsic Methods*/ this->isValidMethodId = JniUtils::getMethod(this->jvm, recordClass, "isValid", this->getMethodSignature("isValid"), false); + this->setValidMethodId = JniUtils::getMethod(this->jvm, recordClass, "setValid", this->getMethodSignature("setValid"), false); this->getCopyMethodId = JniUtils::getMethod(this->jvm, recordClass, "getCopy", this->getMethodSignature("getCopy"), false); /*Field Related Methods*/ this->getFieldIdsMethodId = JniUtils::getMethod(this->jvm, recordClass, "getFieldIds", this->getMethodSignature("getFieldIds"), false); @@ -184,8 +192,13 @@ const char *RecordUtils::getMethodSignature(const char *methodName) { if (strcmp(methodName, "isValid") == 0) { - return "()Ljava/lang/Boolean;"; + return "()Z"; } + else if (strcmp(methodName, "setValid") == 0) + { + return "(Z)V"; + } + else if (strcmp(methodName, "getCopy") == 0) { return "()Lgov/noaa/messageapi/interfaces/IRecord;"; @@ -196,7 +209,7 @@ const char *RecordUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "hasField") == 0) { - return "(Ljava/lang/String;)Ljava/lang/Boolean;"; + return "(Ljava/lang/String;)Z"; } else if (strcmp(methodName, "getFields") == 0) { @@ -212,7 +225,7 @@ const char *RecordUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "hasCondition") == 0) { - return "(Ljava/lang/String;)Ljava/lang/Boolean;"; + return "(Ljava/lang/String;)Z"; } else if (strcmp(methodName, "getConditions") == 0) { diff --git a/src/cpp/main/common/RecordUtils.h b/src/cpp/main/common/RecordUtils.h index 56d2a40..d3cfe33 100644 --- a/src/cpp/main/common/RecordUtils.h +++ b/src/cpp/main/common/RecordUtils.h @@ -35,6 +35,7 @@ public: struct record *getCopy(struct record *record); bool isValid(struct record *record); + void setValid(struct record *record, bool isValid); bool hasField(struct record *record, const char *fieldId); struct string_list *getFieldIds(struct record *record); @@ -54,6 +55,7 @@ private: /*Record Methods*/ jmethodID isValidMethodId; + jmethodID setValidMethodId; jmethodID getCopyMethodId; jmethodID getFieldIdsMethodId; jmethodID getFieldsMethodId; diff --git a/src/cpp/main/common/ResponseUtils.cpp b/src/cpp/main/common/ResponseUtils.cpp new file mode 100644 index 0000000..21bfc82 --- /dev/null +++ b/src/cpp/main/common/ResponseUtils.cpp @@ -0,0 +1,144 @@ +#include "ResponseUtils.h" + +#include + +/** + * Responses are returned by calling submit on a request. Responses operate asynchronously, + * setting an isComplete flag from false to true whenever the specified process is complete. + * Responses execute the request, and holds any records and/or rejections + * that are returned by the evaluation of the request. These records are an aggregate of all + * computation paths through a given request, so may contain records gathered from multiple sources + * in the same computation. + * + * @author Ryan Berkheimer + */ + +/* Default Constructor */ +ResponseUtils::ResponseUtils(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +{ + this->loadGlobalRefs(jvm, typeUtils, listUtils); + this->loadMethodIds(); +} + +/* Default Destructor */ +ResponseUtils::~ResponseUtils() +{ + try + {} + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +/* Public API */ + +bool ResponseUtils::isComplete(struct response *response) +{ + return (bool)this->jvm->CallBooleanMethod(response->jresponse, this->isCompleteMethodId); +} + +struct request *ResponseUtils::getRequest(struct response *response) +{ + jobject jrequest = this->jvm->CallObjectMethod(response->jresponse, this->getRequestMethodId); + struct request *request = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); + request->jrequest = jrequest; + return request; +} + +struct rejection_list *ResponseUtils::getRejections(struct response *response) +{ + jobject jRejections = this->jvm->CallObjectMethod(response->jresponse, this->getRejectionsMethodId); + int rejectionCount = this->listUtils->getListLength(jRejections); + struct rejection_list *rejection_list = (struct rejection_list *)malloc(sizeof(struct rejection_list)); + rejection_list->count = rejectionCount; + rejection_list->jrejections = jRejections; + + return rejection_list; +} + +struct record_list *ResponseUtils::getRecords(struct response *response) +{ + jobject jRecords = this->jvm->CallObjectMethod(response->jresponse, this->getRecordsMethodId); + int recordCount = this->listUtils->getListLength(jRecords); + struct record_list *record_list = (struct record_list *)malloc(sizeof(struct record_list)); + record_list->count = recordCount; + record_list->jrecords = jRecords; + + return record_list; +} + +void ResponseUtils::setRejections(struct response *response, struct rejection_list *rejections) +{ + this->jvm->CallVoidMethod(response->jresponse, this->setRejectionsMethodId, rejections->jrejections); +} + +void ResponseUtils::setRecords(struct response *response, struct record_list *records) +{ + this->jvm->CallVoidMethod(response->jresponse, this->setRecordsMethodId, records->jrecords); +} + +void ResponseUtils::setComplete(struct response *response, bool isComplete) +{ + jobject jBoolVal = jvm->NewObject(this->typeUtils->getBoolClass(), this->typeUtils->createBoolMethod(), (jboolean)isComplete); + this->jvm->CallVoidMethod(response->jresponse, this->setCompleteMethodId, jBoolVal); + this->jvm->DeleteLocalRef(jBoolVal); +} + +/* Private Methods */ + +void ResponseUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +{ + this->jvm = jvm; + this->typeUtils = typeUtils; + this->listUtils = listUtils; +} + +void ResponseUtils::loadMethodIds() +{ + jclass responseClass = JniUtils::getNamedClass(this->jvm, "gov/noaa/messageapi/interfaces/IResponse"); + + this->isCompleteMethodId = JniUtils::getMethod(this->jvm, responseClass, "isComplete", this->getMethodSignature("isComplete"), false); + this->getRequestMethodId = JniUtils::getMethod(this->jvm, responseClass, "getRequest", this->getMethodSignature("getRequest"), false); + this->getRejectionsMethodId = JniUtils::getMethod(this->jvm, responseClass, "getRejections", this->getMethodSignature("getRejections"), false); + this->getRecordsMethodId = JniUtils::getMethod(this->jvm, responseClass, "getRecords", this->getMethodSignature("getRecords"), false); + this->setRejectionsMethodId = JniUtils::getMethod(this->jvm, responseClass, "setRejections", this->getMethodSignature("setRejections"), false); + this->setRecordsMethodId = JniUtils::getMethod(this->jvm, responseClass, "setRecords", this->getMethodSignature("setRecords"), false); + this->setCompleteMethodId = JniUtils::getMethod(this->jvm, responseClass, "setComplete", this->getMethodSignature("setComplete"), false); + + jvm->DeleteLocalRef(responseClass); +} + + +const char *ResponseUtils::getMethodSignature(const char *methodName) +{ + if (strcmp(methodName, "isComplete") == 0) + { + return "()Z"; + } + else if (strcmp(methodName, "getRequest") == 0) + { + return "()Lgov/noaa/messageapi/interfaces/IRequest;"; + } + else if (strcmp(methodName, "getRejections") == 0) + { + return "()Ljava/util/List;"; + } + else if (strcmp(methodName, "getRecords") == 0) + { + return "()Ljava/util/List;"; + } + else if (strcmp(methodName, "setRejections") == 0) + { + return "(Ljava/util/List;)V"; + } + else if (strcmp(methodName, "setRecords") == 0) + { + return "(Ljava/util/List;)V"; + } + else if (strcmp(methodName, "setComplete") == 0) + { + return "(Z)V"; + } + return NULL; +} \ No newline at end of file diff --git a/src/cpp/main/common/ResponseUtils.h b/src/cpp/main/common/ResponseUtils.h new file mode 100644 index 0000000..0ae889a --- /dev/null +++ b/src/cpp/main/common/ResponseUtils.h @@ -0,0 +1,75 @@ + +#ifndef _RESPONSEUTILS_H +#define _RESPONSEUTILS_H + +#include +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus +#include +#include +#include "ListUtils.h" +#include "TypeUtils.h" + +/** + * Responses are returned by calling submit on a request. Responses operate asynchronously, + * setting an isComplete flag from false to true whenever the specified process is complete. + * Responses execute the request, and holds records and/or rejections + * that are returned by the evaluation of the request. These records are an aggregate of all + * computation paths through a given request, so may contain records gathered from multiple sources + * in the same computation. + * + * @author Ryan Berkheimer + */ +class ResponseUtils +{ + +public: + /*Default constructor/destructors*/ + ResponseUtils(JNIEnv *javaEnv, TypeUtils *typeUtils, ListUtils *listUtils); + ~ResponseUtils(); + + /* Response Methods */ + bool isComplete(struct response *response); + struct request *getRequest(struct response *response); + struct rejection_list *getRejections(struct response *response); + struct record_list *getRecords(struct response *response); + void setRejections(struct response *response, struct rejection_list *rejections); + void setRecords(struct response *response, struct record_list *records); + void setComplete(struct response *response, bool isComplete); + +private: + /*Vars*/ + JNIEnv *jvm; + ListUtils *listUtils; + TypeUtils *typeUtils; + + /*Request Methods*/ + jmethodID isCompleteMethodId; + jmethodID getRequestMethodId; + jmethodID getRejectionsMethodId; + jmethodID getRecordsMethodId; + jmethodID setRejectionsMethodId; + jmethodID setRecordsMethodId; + jmethodID setCompleteMethodId; + + + /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ + void loadMethodIds(); + void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, ListUtils *listUtils); + + /*Grouped methods for returning the matching method signature string for a given interface*/ + const char *getMethodSignature(const char *methodName); +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif -- GitLab From 6249067450d63158d446626158237ee1ebb85d23 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sat, 30 May 2020 11:31:12 -0400 Subject: [PATCH 02/53] completed adding SessionUtils class --- .../main/common/structs/messageapi_structs.h | 5 ++ src/cpp/main/common/ConditionUtils.h | 1 - src/cpp/main/common/EndpointUtils.h | 1 - src/cpp/main/common/FieldUtils.h | 1 - src/cpp/main/common/JniUtils.h | 1 - src/cpp/main/common/ListUtils.h | 1 - src/cpp/main/common/MessageApiEndpoint.h | 1 - src/cpp/main/common/PacketUtils.h | 1 - src/cpp/main/common/ProtocolRecordUtils.h | 1 - src/cpp/main/common/RecordUtils.h | 1 - src/cpp/main/common/RejectionUtils.h | 1 - src/cpp/main/common/RequestUtils.h | 1 - src/cpp/main/common/ResponseUtils.h | 1 - src/cpp/main/common/SessionUtils.cpp | 65 +++++++++++++++++++ src/cpp/main/common/SessionUtils.h | 59 +++++++++++++++++ src/cpp/main/common/TypeUtils.h | 1 - 16 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 src/cpp/main/common/SessionUtils.cpp create mode 100644 src/cpp/main/common/SessionUtils.h diff --git a/src/c/main/common/structs/messageapi_structs.h b/src/c/main/common/structs/messageapi_structs.h index 27f2bdc..062a0d2 100644 --- a/src/c/main/common/structs/messageapi_structs.h +++ b/src/c/main/common/structs/messageapi_structs.h @@ -19,6 +19,11 @@ struct val_list jobject jlist; }; +struct session +{ + jobject jsession; +}; + struct response { jobject jresponse; diff --git a/src/cpp/main/common/ConditionUtils.h b/src/cpp/main/common/ConditionUtils.h index fb6d3d4..f947d11 100644 --- a/src/cpp/main/common/ConditionUtils.h +++ b/src/cpp/main/common/ConditionUtils.h @@ -1,4 +1,3 @@ - #ifndef _CONDITIONUTILS_H #define _CONDITIONUTILS_H diff --git a/src/cpp/main/common/EndpointUtils.h b/src/cpp/main/common/EndpointUtils.h index 484fbb0..ed44aa0 100644 --- a/src/cpp/main/common/EndpointUtils.h +++ b/src/cpp/main/common/EndpointUtils.h @@ -1,4 +1,3 @@ - #ifndef _ENDPOINTUTILS_H #define _ENDPOINTUTILS_H diff --git a/src/cpp/main/common/FieldUtils.h b/src/cpp/main/common/FieldUtils.h index 22574e1..2fcb08a 100644 --- a/src/cpp/main/common/FieldUtils.h +++ b/src/cpp/main/common/FieldUtils.h @@ -1,4 +1,3 @@ - #ifndef _FIELDUTILS_H #define _FIELDUTILS_H diff --git a/src/cpp/main/common/JniUtils.h b/src/cpp/main/common/JniUtils.h index e920e03..b014855 100644 --- a/src/cpp/main/common/JniUtils.h +++ b/src/cpp/main/common/JniUtils.h @@ -1,4 +1,3 @@ - #ifndef _JNIUTILS_H #define _JNIUTILS_H diff --git a/src/cpp/main/common/ListUtils.h b/src/cpp/main/common/ListUtils.h index eab6052..c04dc7f 100644 --- a/src/cpp/main/common/ListUtils.h +++ b/src/cpp/main/common/ListUtils.h @@ -1,4 +1,3 @@ - #ifndef _LISTUTILS_H #define _LISTUTILS_H diff --git a/src/cpp/main/common/MessageApiEndpoint.h b/src/cpp/main/common/MessageApiEndpoint.h index 6265bb6..1d248b5 100644 --- a/src/cpp/main/common/MessageApiEndpoint.h +++ b/src/cpp/main/common/MessageApiEndpoint.h @@ -1,4 +1,3 @@ - #ifndef _Included_MessageApiEndpoint #define _Included_MessageApiEndpoint diff --git a/src/cpp/main/common/PacketUtils.h b/src/cpp/main/common/PacketUtils.h index ea1033a..0c745de 100644 --- a/src/cpp/main/common/PacketUtils.h +++ b/src/cpp/main/common/PacketUtils.h @@ -1,4 +1,3 @@ - #ifndef _PACKETUTILS_H #define _PACKETUTILS_H diff --git a/src/cpp/main/common/ProtocolRecordUtils.h b/src/cpp/main/common/ProtocolRecordUtils.h index 9c5e523..c896108 100644 --- a/src/cpp/main/common/ProtocolRecordUtils.h +++ b/src/cpp/main/common/ProtocolRecordUtils.h @@ -1,4 +1,3 @@ - #ifndef _PROTOCOLRECORDUTILS_H #define _PROTOCOLRECORDUTILS_H diff --git a/src/cpp/main/common/RecordUtils.h b/src/cpp/main/common/RecordUtils.h index d3cfe33..c1002d5 100644 --- a/src/cpp/main/common/RecordUtils.h +++ b/src/cpp/main/common/RecordUtils.h @@ -1,4 +1,3 @@ - #ifndef _RECORDUTILS_H #define _RECORDUTILS_H diff --git a/src/cpp/main/common/RejectionUtils.h b/src/cpp/main/common/RejectionUtils.h index 1f8c072..da8d3c6 100644 --- a/src/cpp/main/common/RejectionUtils.h +++ b/src/cpp/main/common/RejectionUtils.h @@ -1,4 +1,3 @@ - #ifndef _REJECTIONUTILS_H #define _REJECTIONUTILS_H diff --git a/src/cpp/main/common/RequestUtils.h b/src/cpp/main/common/RequestUtils.h index 843f737..b7347c4 100644 --- a/src/cpp/main/common/RequestUtils.h +++ b/src/cpp/main/common/RequestUtils.h @@ -1,4 +1,3 @@ - #ifndef _REQUESTUTILS_H #define _REQUESTUTILS_H diff --git a/src/cpp/main/common/ResponseUtils.h b/src/cpp/main/common/ResponseUtils.h index 0ae889a..d08e7bd 100644 --- a/src/cpp/main/common/ResponseUtils.h +++ b/src/cpp/main/common/ResponseUtils.h @@ -1,4 +1,3 @@ - #ifndef _RESPONSEUTILS_H #define _RESPONSEUTILS_H diff --git a/src/cpp/main/common/SessionUtils.cpp b/src/cpp/main/common/SessionUtils.cpp new file mode 100644 index 0000000..adcf31a --- /dev/null +++ b/src/cpp/main/common/SessionUtils.cpp @@ -0,0 +1,65 @@ +#include "SessionUtils.h" + +#include + +/** + * Sessions are the top level API container of any given computation. Sessions + * bootstrap from a specification map and 'lock-in' a computation environment, + * allowing requests to be created. + * + * @author Ryan Berkheimer + */ + +/* Default Constructor */ +SessionUtils::SessionUtils(JNIEnv *jvm) +{ + this->loadGlobalRefs(jvm); + this->loadMethodIds(); +} + +/* Default Destructor */ +SessionUtils::~SessionUtils() +{ + try + {} + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +/* Public API */ + +struct request *SessionUtils::createRequest(struct session *session) +{ + jobject jrequest = this->jvm->CallObjectMethod(session->jsession, this->createRequestMethodId); + struct request *request = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); + request->jrequest = jrequest; + return request; +} + +/* Private Methods */ + +void SessionUtils::loadGlobalRefs(JNIEnv *jvm) +{ + this->jvm = jvm; +} + +void SessionUtils::loadMethodIds() +{ + jclass sessionClass = JniUtils::getNamedClass(this->jvm, "gov/noaa/messageapi/interfaces/ISession"); + + this->createRequestMethodId = JniUtils::getMethod(this->jvm, sessionClass, "createRequest", this->getMethodSignature("createRequest"), false); + + jvm->DeleteLocalRef(sessionClass); +} + + +const char *SessionUtils::getMethodSignature(const char *methodName) +{ + if (strcmp(methodName, "createRequest") == 0) + { + return "()Lgov/noaa/messageapi/interfaces/IRequest;"; + } + return NULL; +} \ No newline at end of file diff --git a/src/cpp/main/common/SessionUtils.h b/src/cpp/main/common/SessionUtils.h new file mode 100644 index 0000000..77c2c04 --- /dev/null +++ b/src/cpp/main/common/SessionUtils.h @@ -0,0 +1,59 @@ +#ifndef _SESSIONUTILS_H +#define _SESSIONUTILS_H + +#include +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus +#include +#include + +#include "JniUtils.h" + +/** + * Sessions are the top level API container of any given computation. Sessions + * bootstrap from a specification map and 'lock-in' a computation environment, + * allowing requests to be created. + * + * @author Ryan Berkheimer + */ +class SessionUtils +{ + +public: + /*Default constructor */ + SessionUtils(JNIEnv *javaEnv); + + /*Default Destructor */ + ~SessionUtils(); + + /* Session Methods */ + struct request *createRequest(struct session *session); + +private: + /*Vars*/ + JNIEnv *jvm; + + /*Request Methods*/ + jmethodID createRequestMethodId; + + + /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ + void loadMethodIds(); + void loadGlobalRefs(JNIEnv *env); + + /*Grouped methods for returning the matching method signature string for a given interface*/ + const char *getMethodSignature(const char *methodName); +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpp/main/common/TypeUtils.h b/src/cpp/main/common/TypeUtils.h index 54719a0..5e0dc32 100644 --- a/src/cpp/main/common/TypeUtils.h +++ b/src/cpp/main/common/TypeUtils.h @@ -1,4 +1,3 @@ - #ifndef _TYPEUTILS_H #define _TYPEUTILS_H -- GitLab From eaca699a0f2498c9575240daf7d06daa09a44070 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sat, 30 May 2020 17:47:45 -0400 Subject: [PATCH 03/53] simplified primary API - removed Transformation Factories in favor of direct class specification as the operator within the session parameter manifest. --- README.md | 26 +- .../simple/clisam/transformations.json | 25 +- .../condition-test/transformations.json | 25 +- resources/test/file-reader/parameters.json | 8 +- resources/test/sessions/condition-test.json | 5 +- resources/test/sessions/email-smtp-test.json | 3 +- .../test/sessions/sqlite-jdbc-clisam.json | 3 +- .../main/common/structs/messageapi_structs.h | 15 + src/cpp/main/common/MapUtils.cpp | 264 ++++++++++++++++++ src/cpp/main/common/MapUtils.h | 89 ++++++ src/cpp/main/common/TransformationUtils.cpp | 60 ++++ src/cpp/main/common/TransformationUtils.h | 55 ++++ .../test/endtoend/FileReaderTests.groovy | 2 + .../connections/DefaultConnection.java | 9 +- .../definitions/ContainerDefinition.java | 21 -- .../SimpleTransformationFactory.java | 32 --- .../interfaces/ITransformationFactory.java | 13 - .../TransformationFactoryParser.java | 23 -- .../plugins/ContainerPluginParser.java | 2 +- .../parsers/plugins/ProtocolPluginParser.java | 2 +- .../parsers/plugins/SchemaPluginParser.java | 2 +- .../parsers/plugins/SessionPluginParser.java | 3 - .../transformations/NativeTransformation.java | 53 ++++ .../joins/StringFieldJoin.java | 2 +- .../reductions/ReduceTransformation.java | 2 +- .../utils/protocol/ConnectionUtils.java | 19 +- .../transformations/FileReaderFactory.java | 29 -- .../FixRelativePathsTransformation.java | 5 +- 28 files changed, 619 insertions(+), 178 deletions(-) create mode 100644 src/cpp/main/common/MapUtils.cpp create mode 100644 src/cpp/main/common/MapUtils.h create mode 100644 src/cpp/main/common/TransformationUtils.cpp create mode 100644 src/cpp/main/common/TransformationUtils.h delete mode 100644 src/java/main/gov/noaa/messageapi/factories/SimpleTransformationFactory.java delete mode 100644 src/java/main/gov/noaa/messageapi/interfaces/ITransformationFactory.java delete mode 100644 src/java/main/gov/noaa/messageapi/parsers/containers/TransformationFactoryParser.java create mode 100644 src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java delete mode 100644 src/java/test/gov/noaa/messageapi/test/factories/transformations/FileReaderFactory.java diff --git a/README.md b/README.md index 470a552..d39b966 100644 --- a/README.md +++ b/README.md @@ -164,10 +164,10 @@ Note that both Conditions and Transformations specify 'factories'. These factori "fields": ["file-path"], "conditions": ["is-relative-path"]}], "transformations": [{"id": "trans-1", - "operator": "fix-relative-paths", - "constructor": {"transform-key": "file-collection"}, - "records": {"file-collection": {"COLLECTION": "coll-1"}}, - "fields": ["file-path"]}], + "operator": "gov.noaa.messageapi.test.transformations.FixRelativePathsTransformation", + "constructor": {"transform-key": "file-collection", + "fields": ["file-path"]}, + "records": {"file-collection": {"COLLECTION": "coll-1"}}}], "connections": [{"id": "conn-1", "transformations": ["trans-1"], "constructor": {"file-fields": "file-path"}, @@ -419,7 +419,7 @@ There are three types of container groupings provided by the default MessageAPI - **Transformations** are computational containers. They are an optional component of MessageAPI. Transformations act as instances of immutable functions that can hold global, configurable constructor/initialization parameters, use other arbitrary named containers as arguments in a process function, return a list of records, and list the fields that each record will provide in a 'fields' map entry. Transformations are always immutable, executed lazily (only when called in an Endpoint), and always operate on and produce lists of records. -The 'records' entry on the Transformation map itself holds a map of named parameter keys that correspond to values describing what type of container and the id of that container to use as that particular input. For example, in the following Transformation map, the first Transformation is called 'join-test'. The Transformation has an operator of 'join', which corresponds to a java class in the TransformationFactory listed in the Session manifest. This Transformation provides a constructor map containing two keys, 'join_field' and 'collection_field', both which specify constants that are set in the Transformation when it is initialized. +The 'records' entry on the Transformation map itself holds a map of named parameter keys that correspond to values describing what type of container and the id of that container to use as that particular input. For example, in the following Transformation map, the first Transformation is called 'join-test'. The Transformation has an operator of the fully qualified join Class listed in the Session manifest. This Transformation provides a constructor map containing two keys, 'join_field' and 'collection_field', both which specify constants that are set in the Transformation when it is initialized. The 'join-test' Transformation defines three parameters in its process method map - 'parent', 'child', and 'other'. Each of these corresponds to a different container - when used in the Transformation, the 'parent' parameter will provide a list of all records contained by the 'namespace=condition-test' classifier; the 'child' parameter will provide a list of records contained by the 'mix-and-match' collection; and the 'other' parameter contains a special case - the UUID - which will provide every collection for a given UUID, and map the Transformation to every UUID, and all returned records for every UUID in this Transformation will be merged on return. The use of UUID as a Transformation record parameter is a special case, and due to its mapping ability, limits its use to once per Transformation. @@ -434,21 +434,21 @@ It is the view of the package authors that Transformations hold computational ta "transformations": [ { "id": "join-test", - "operator": "join", + "operator": "gov.noaa.messageapi.transformations.joins.StringFieldJoin", "constructor": {"join_field": "key", - "collection_field": "mix-and-match"}, + "collection_field": "mix-and-match", + "fields": ["key", "record", "filename", "type", "mix-and-match"]}, "records": {"parent": {"CLASSIFIER": ["namespace", "condition-test"]}, "child": {"COLLECTION": "mix-and-match"}, - "other": "UUID"}, - "fields": ["key", "record", "filename", "type", "mix-and-match"] + "other": "UUID"} }, { "id": "reduce-test", - "operator": "reduce-sum", + "operator": "gov.noaa.messageapi.transformations.reductions.ReduceTransformation", "constructor": {"reduce-field": "mix-and-match", - "reduce-target": "mix-and-match-reduction"}, - "records": {"reduce-list" : {"TRANSFORMATION": "join-test"}}, - "fields": ["key", "mix-and-match-reduction"] + "reduce-target": "mix-and-match-reduction", + "fields": ["key", "mix-and-match-reduction"]}, + "records": {"reduce-list" : {"TRANSFORMATION": "join-test"}} }] } ``` diff --git a/resources/test/containers/simple/clisam/transformations.json b/resources/test/containers/simple/clisam/transformations.json index 1fef7fc..a16ae7c 100644 --- a/resources/test/containers/simple/clisam/transformations.json +++ b/resources/test/containers/simple/clisam/transformations.json @@ -2,19 +2,28 @@ "transformations": [ { "id": "join-test", - "operator": "join", + "operator": "gov.noaa.messageapi.transformations.joins.StringFieldJoin", "constructor": {"join-field": "key", - "collection-field": "mix-and-match"}, + "collection-field": "mix-and-match", + "fields": [ + "key", + "record", + "filename", + "type", + "mix-and-match" + ]}, "records": {"parent": {"CLASSIFIER": ["namespace", "condition-test"]}, - "child": {"COLLECTION": "mix-and-match"}}, - "fields": ["key", "record", "filename", "type", "mix-and-match"] + "child": {"COLLECTION": "mix-and-match"}} }, { "id": "reduce-test", - "operator": "reduce-sum", + "operator": "gov.noaa.messageapi.transformations.reductions.ReduceTransformation", "constructor": {"reduce-field": "mix-and-match", - "reduce-target": "mix-and-match-reduction"}, - "records": {"reduce-list" : {"TRANSFORMATION": "join-test"}}, - "fields": ["key", "mix-and-match-reduction"] + "reduce-target": "mix-and-match-reduction", + "fields":[ + "key", + "mix-and-match-reduction" + ]}, + "records": {"reduce-list" : {"TRANSFORMATION": "join-test"}} }] } diff --git a/resources/test/containers/simple/condition-test/transformations.json b/resources/test/containers/simple/condition-test/transformations.json index 1295c60..f1972e6 100644 --- a/resources/test/containers/simple/condition-test/transformations.json +++ b/resources/test/containers/simple/condition-test/transformations.json @@ -2,19 +2,28 @@ "transformations": [ { "id": "join-test", - "operator": "join", + "operator": "gov.noaa.messageapi.transformations.joins.StringFieldJoin", "constructor": {"join-field": "key", - "collection-field": "mix-and-match"}, + "collection-field": "mix-and-match", + "fields": [ + "key", + "record", + "filename", + "type", + "mix-and-match" + ]}, "records": {"parent": {"CLASSIFIER": ["namespace", "condition-test"]}, - "child": {"TRANSFORMATION": "reduce-test"}}, - "fields": ["key", "record", "filename", "type", "mix-and-match"] + "child": {"TRANSFORMATION": "reduce-test"}} }, { "id": "reduce-test", - "operator": "reduce", + "operator": "gov.noaa.messageapi.transformations.reductions.ReduceTransformation", "constructor": {"reduce-field": "mix-and-match", - "reduce-target": "mix-and-match-reduction"}, - "records": {"reduce-list" : "UUID"}, - "fields": ["key", "mix-and-match-reduction"] + "reduce-target": "mix-and-match-reduction", + "fields": [ + "key", + "mix-and-match-reduction" + ]}, + "records": {"reduce-list" : "UUID"} }] } diff --git a/resources/test/file-reader/parameters.json b/resources/test/file-reader/parameters.json index f3617f9..3bbac60 100644 --- a/resources/test/file-reader/parameters.json +++ b/resources/test/file-reader/parameters.json @@ -12,10 +12,10 @@ "fields": ["file-path"], "conditions": ["is-relative-path"]}], "transformations": [{"id": "trans-1", - "operator": "fix-relative-paths", - "constructor": {"transform-key": "file-collection"}, - "records": {"file-collection": {"COLLECTION": "coll-1"}}, - "fields": ["file-path"]}], + "operator": "gov.noaa.messageapi.test.transformations.FixRelativePathsTransformation", + "constructor": {"transform-key": "file-collection", + "fields": ["file-path"]}, + "records": {"file-collection": {"COLLECTION": "coll-1"}}}], "connections": [{"id": "conn-1", "transformations": ["trans-1"], "constructor": {"file-fields": "file-path"}, diff --git a/resources/test/sessions/condition-test.json b/resources/test/sessions/condition-test.json index e5f0289..efb490a 100644 --- a/resources/test/sessions/condition-test.json +++ b/resources/test/sessions/condition-test.json @@ -12,10 +12,7 @@ "constructor": { "metadata": "{}/resources/test/containers/simple/condition-test/metadata.json", "collections": "{}/resources/test/containers/simple/condition-test/collections.json", - "transformations": { - "map": "{}/resources/test/containers/simple/condition-test/transformations.json", - "factory": "gov.noaa.messageapi.factories.SimpleTransformationFactory" - } + "transformations": {"map": "{}/resources/test/containers/simple/condition-test/transformations.json"} } }, "protocol": { diff --git a/resources/test/sessions/email-smtp-test.json b/resources/test/sessions/email-smtp-test.json index 9d507d4..22b6af6 100644 --- a/resources/test/sessions/email-smtp-test.json +++ b/resources/test/sessions/email-smtp-test.json @@ -7,8 +7,7 @@ "container": {"plugin": "gov.noaa.messageapi.containers.DefaultContainer", "constructor": {"metadata": "{}/resources/test/containers/simple/email/metadata.json", "collections": "{}/resources/test/containers/simple/email/collections.json", - "transformations": {"map": "{}/resources/test/containers/simple/email/transformations.json", - "factory": "gov.noaa.messageapi.factories.SimpleTransformationFactory"}}}, + "transformations": {"map": "{}/resources/test/containers/simple/email/transformations.json"}}}, "protocol": {"plugin": "gov.noaa.messageapi.protocols.DefaultProtocol", "constructor": {"metadata": "{}/resources/test/protocols/email/simple/metadata.json", "endpoints": [{"plugin": "gov.noaa.messageapi.test.endpoints.EmailEndpointTest", diff --git a/resources/test/sessions/sqlite-jdbc-clisam.json b/resources/test/sessions/sqlite-jdbc-clisam.json index ad7161a..5f5122d 100644 --- a/resources/test/sessions/sqlite-jdbc-clisam.json +++ b/resources/test/sessions/sqlite-jdbc-clisam.json @@ -7,8 +7,7 @@ "container": {"plugin": "gov.noaa.messageapi.containers.DefaultContainer", "constructor": {"metadata": "{}/resources/test/containers/simple/clisam/metadata.json", "collections": "{}/resources/test/containers/simple/clisam/collections.json", - "transformations": {"map": "{}/resources/test/containers/simple/clisam/transformations.json", - "factory": "gov.noaa.messageapi.factories.SimpleTransformationFactory"}}}, + "transformations": {"map": "{}/resources/test/containers/simple/clisam/transformations.json"}}}, "protocol": {"plugin": "gov.noaa.messageapi.protocols.DefaultProtocol", "constructor": {"metadata": "{}/resources/test/protocols/jdbc/sqlite/clisam/metadata.json", "endpoints": [{"plugin": "gov.noaa.messageapi.test.endpoints.EmailEndpointTest", diff --git a/src/c/main/common/structs/messageapi_structs.h b/src/c/main/common/structs/messageapi_structs.h index 062a0d2..b97ce34 100644 --- a/src/c/main/common/structs/messageapi_structs.h +++ b/src/c/main/common/structs/messageapi_structs.h @@ -13,6 +13,11 @@ struct list_item jobject jitem; }; +struct val_map +{ + jobject jmap; +}; + struct val_list { int count; @@ -24,6 +29,16 @@ struct session jobject jsession; }; +struct transformation +{ + jobject jtransformation; +}; + +struct transformation_map +{ + jobject jtransformation_map; +}; + struct response { jobject jresponse; diff --git a/src/cpp/main/common/MapUtils.cpp b/src/cpp/main/common/MapUtils.cpp new file mode 100644 index 0000000..cf79aa0 --- /dev/null +++ b/src/cpp/main/common/MapUtils.cpp @@ -0,0 +1,264 @@ +#include "ListUtils.h" + +ListUtils::ListUtils(JNIEnv *env, TypeUtils *typeUtils) +{ + this->loadGlobalRefs(env, typeUtils); + this->loadMethodIds(); +} + +ListUtils::~ListUtils() +{ + try + { + } + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +void ListUtils::loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils) +{ + this->jvm = env; + this->typeUtils = typeUtils; +} + +void ListUtils::loadMethodIds() +{ + jclass listClass = JniUtils::getNamedClass(this->jvm, "java/util/List"); + this->getListSizeMethodId = this->jvm->GetMethodID(listClass, "size", "()I"); + this->getListItemMethodId = this->jvm->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;"); + this->addListItemMethodId = this->jvm->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z"); + this->jvm->DeleteLocalRef(listClass); + + this->createListMethodId = this->jvm->GetMethodID(this->typeUtils->getListClass(), "", "()V"); +} + +jmethodID ListUtils::createListMethod() +{ + return this->createListMethodId; +} + +jmethodID ListUtils::getListSizeMethod() +{ + return this->getListSizeMethodId; +} + +jmethodID ListUtils::getListItemMethod() +{ + return this->getListItemMethodId; +} + +jmethodID ListUtils::addListItemMethod() +{ + return this->addListItemMethodId; +} + +struct val_list *ListUtils::createList() +{ + jobject jList = this->jvm->NewObject(this->typeUtils->getListClass(), this->createListMethod()); + struct val_list *valueList = (struct val_list *)malloc(sizeof(struct val_list)); + valueList->count = 0; + valueList->jlist = jList; + return valueList; +} + +int ListUtils::getListLength(jobject jList) +{ + return (int)this->jvm->CallIntMethod(jList, this->getListSizeMethod()); +} + +struct list_item *ListUtils::getItem(struct val_list *list, int index) +{ + struct list_item *listItem = (struct list_item *)malloc(sizeof(struct list_item)); + listItem->jitem = this->getObjectItem(list, index); + return listItem; +} + +jobject ListUtils::getObjectItem(struct val_list *val_list, int index) +{ + return static_cast(this->jvm->CallObjectMethod(val_list->jlist, this->getListItemMethod(), index)); +} + +struct val_list *ListUtils::getListItem(struct val_list *list, int index) +{ + jobject listItem = this->getObjectItem(list, index); + int itemCount = this->getListLength(listItem); + struct val_list *valueList = (struct val_list *)malloc(sizeof(struct val_list)); + valueList->count = itemCount; + valueList->jlist = listItem; + return valueList; +} + +int ListUtils::getIntItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + int val = (int)this->jvm->CallIntMethod(list_item, this->typeUtils->getIntMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +long ListUtils::getLongItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + long val = (long)this->jvm->CallLongMethod(list_item, this->typeUtils->getLongMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +float ListUtils::getFloatItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + float val = (float)this->jvm->CallFloatMethod(list_item, this->typeUtils->getFloatMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +double ListUtils::getDoubleItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + double val = (double)this->jvm->CallDoubleMethod(list_item, this->typeUtils->getDoubleMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +signed char ListUtils::getByteItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + signed char val = (signed char)this->jvm->CallByteMethod(list_item, this->typeUtils->getByteMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +const char *ListUtils::getStringItem(struct val_list *list, int index) +{ + jstring jString = static_cast(this->jvm->CallObjectMethod(list->jlist, this->getListItemMethod(), index)); + const char *val = this->typeUtils->fromJavaString(jString); + jvm->DeleteLocalRef(jString); + return val; +} + +bool ListUtils::getBoolItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + bool val = (bool)this->jvm->CallBooleanMethod(list_item, this->typeUtils->getBoolMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +short ListUtils::getShortItem(struct val_list *list, int index) +{ + jobject list_item = this->getObjectItem(list, index); + short val = (short)this->jvm->CallShortMethod(list_item, this->typeUtils->getShortMethod()); + jvm->DeleteLocalRef(list_item); + return val; +} + +void ListUtils::addObjectItem(struct val_list *list, jobject val) +{ + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), val); + list->count += 1; +} + +void ListUtils::addItem(struct val_list *list, struct list_item *item) +{ + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), item->jitem); + list->count += 1; +} + +void ListUtils::addIntItem(struct val_list *list, int val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getIntClass(), this->typeUtils->createIntMethod(), (jint)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addLongItem(struct val_list *list, long val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getLongClass(), this->typeUtils->createLongMethod(), (jlong)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addFloatItem(struct val_list *list, float val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getFloatClass(), this->typeUtils->createFloatMethod(), (jfloat)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addDoubleItem(struct val_list *list, double val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getDoubleClass(), this->typeUtils->createDoubleMethod(), (jdouble)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addByteItem(struct val_list *list, signed char val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getByteClass(), this->typeUtils->createByteMethod(), (jbyte)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addStringItem(struct val_list *list, const char *val) +{ + jstring jVal = this->typeUtils->toJavaString(val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addBoolItem(struct val_list *list, bool val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getBoolClass(), this->typeUtils->createBoolMethod(), (jboolean)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addShortItem(struct val_list *list, short val) +{ + jobject jVal = jvm->NewObject(this->typeUtils->getShortClass(), this->typeUtils->createShortMethod(), (jshort)val); + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); + list->count += 1; + this->jvm->DeleteLocalRef(jVal); +} + +void ListUtils::addListItem(struct val_list *list, struct val_list *val) +{ + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), val->jlist); + list->count += 1; +} + +struct string_list *ListUtils::translateStringList(jobject jList) +{ + int stringCount = this->getListLength(jList); + char **strings = (char **)malloc(sizeof(char *) * stringCount); + int maxStringLength = 0; + for (int i = 0; i < stringCount; i++) + { + jstring jString = static_cast(this->jvm->CallObjectMethod(jList, this->getListItemMethod(), i)); + const char *tempString = this->jvm->GetStringUTFChars(jString, NULL); + int tempMaxStringLength = strlen(tempString); + if (tempMaxStringLength > maxStringLength) + { + maxStringLength = tempMaxStringLength; + } + strings[i] = (char *)malloc((tempMaxStringLength + 1) * sizeof(char)); + strcpy(strings[i], tempString); + this->jvm->ReleaseStringUTFChars(jString, tempString); + this->jvm->DeleteLocalRef(jString); + } + + struct string_list *string_list = (struct string_list *)malloc(sizeof(struct string_list) + sizeof(strings)); + string_list->count = stringCount; + string_list->max_length = maxStringLength; + string_list->strings = strings; + return string_list; +} diff --git a/src/cpp/main/common/MapUtils.h b/src/cpp/main/common/MapUtils.h new file mode 100644 index 0000000..7d51e83 --- /dev/null +++ b/src/cpp/main/common/MapUtils.h @@ -0,0 +1,89 @@ +#ifndef _MAPUTILS_H +#define _MAPUTILS_H + +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus + +#include "JniUtils.h" +#include "TypeUtils.h" +#include +#include + +/** + * This is the header for the MapUtils object class. MapUtils contains a set of methods used for manipulation of Java Maps + * in C++ or C code. MapUtils is a class to be instantiated so that it remains thread safe for implementors. + */ +class MapUtils +{ + +public: + /* Default constructor for ListUtils */ + MapUtils(JNIEnv *env, TypeUtils *typeUtils); + + /* Default destructor for ListUtils */ + ~MapUtils(); + + /* Utility methods */ + struct val_map *createMap(); + int getListLength(jobject jList); + struct string_list *translateStringList(jobject jList); + + /*List Item Retrieval Methods*/ + struct list_item *getItem(struct val_list *list, int index); + jobject getObjectItem(struct val_list *list, int index); + int getIntItem(struct val_list *list, int index); + long getLongItem(struct val_list *list, int index); + float getFloatItem(struct val_list *list, int index); + double getDoubleItem(struct val_list *list, int index); + signed char getByteItem(struct val_list *list, int index); + const char *getStringItem(struct val_list *list, int index); + bool getBoolItem(struct val_list *list, int index); + short getShortItem(struct val_list *list, int index); + struct val_list *getListItem(struct val_list *list, int index); + + /*List Item Insertion Methods*/ + void addItem(struct val_list *list, struct list_item *item); + void addObjectItem(struct val_list *list, jobject val); + void addIntItem(struct val_list *list, int val); + void addLongItem(struct val_list *list, long val); + void addFloatItem(struct val_list *list, float val); + void addDoubleItem(struct val_list *list, double val); + void addByteItem(struct val_list *list, signed char val); + void addStringItem(struct val_list *list, const char *val); + void addBoolItem(struct val_list *list, bool val); + void addShortItem(struct val_list *list, short val); + void addListItem(struct val_list *list, struct val_list *val); + + jmethodID createListMethod(); + jmethodID getListSizeMethod(); + jmethodID getListItemMethod(); + jmethodID addListItemMethod(); + + +private: + JNIEnv *jvm; + TypeUtils *typeUtils; + + jmethodID createListMethodId; + jmethodID getListSizeMethodId; + jmethodID getListItemMethodId; + jmethodID addListItemMethodId; + + /* Initialization Methods */ + void loadGlobalRefs(JNIEnv *env, TypeUtils *TypeUtils); + void loadMethodIds(); + +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpp/main/common/TransformationUtils.cpp b/src/cpp/main/common/TransformationUtils.cpp new file mode 100644 index 0000000..a8ed67e --- /dev/null +++ b/src/cpp/main/common/TransformationUtils.cpp @@ -0,0 +1,60 @@ +#include "TransformationUtils.h" + +#include + +/** + * Sessions are the top level API container of any given computation. Sessions + * bootstrap from a specification map and 'lock-in' a computation environment, + * allowing requests to be created. + * + * @author Ryan Berkheimer + */ + +/* Default Constructor */ +TransformationUtils::TransformationUtils(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +{ + this->loadGlobalRefs(jvm, typeUtils, mapUtils, listUtils); + this->loadMethodIds(); +} + +/* Default Destructor */ +TransformationUtils::~TransformationUtils() +{ + try + {} + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +/* Public API */ + + +/* Private Methods */ + +void TransformationUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +{ + this->jvm = jvm; + this->typeUtils = typeUtils; + this->mapUtils = mapUtils; + this->listUtils = listUtils; +} + +void TransformationUtils::loadMethodIds() +{ + jclass transformationClass = JniUtils::getNamedClass(this->jvm, "gov/noaa/messageapi/interfaces/ITransformation"); + + /*this->createRequestMethodId = JniUtils::getMethod(this->jvm, sessionClass, "createRequest", this->getMethodSignature("createRequest"), false);*/ + + jvm->DeleteLocalRef(transformationClass); +} + +const char *TransformationUtils::getMethodSignature(const char *methodName) +{ + /*if (strcmp(methodName, "createRequest") == 0) + { + return "()Lgov/noaa/messageapi/interfaces/IRequest;"; + }*/ + return NULL; +} \ No newline at end of file diff --git a/src/cpp/main/common/TransformationUtils.h b/src/cpp/main/common/TransformationUtils.h new file mode 100644 index 0000000..0dd20d2 --- /dev/null +++ b/src/cpp/main/common/TransformationUtils.h @@ -0,0 +1,55 @@ +#ifndef _TRANSFORMATIONUTILS_H +#define _TRANSFORMATIONUTILS_H + +#include +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus +#include +#include + +#include "JniUtils.h" +#include "TypeUtils.h" +#include "MapUtils.h" +#include "ListUtils.h" + +/** + * + * @author Ryan Berkheimer + */ +class TransformationUtils +{ + +public: + /*Default constructor */ + TransformationUtils(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + + /*Default Destructor */ + ~TransformationUtils(); + +private: + /*Vars*/ + JNIEnv *jvm; + TypeUtils *typeUtils; + MapUtils *mapUtils; + ListUtils *listUtils; + + /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ + void loadMethodIds(); + void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + + /*Grouped methods for returning the matching method signature string for a given interface*/ + const char *getMethodSignature(const char *methodName); +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/groovy/test/endtoend/FileReaderTests.groovy b/src/groovy/test/endtoend/FileReaderTests.groovy index ee658d3..ad68c90 100644 --- a/src/groovy/test/endtoend/FileReaderTests.groovy +++ b/src/groovy/test/endtoend/FileReaderTests.groovy @@ -39,6 +39,8 @@ def "Tests submission of a full file reader task with 1 large input."() { IResponse response = request.submit(); while (!response.isComplete()) {} then: "We should have no rejections and there should be 79794 records in the return set." + //println "FIELD VALUE!!!" + //println response.getRecords().get(0).getField("value").getValue() response.getRejections().size() == 0 response.getRecords().size() == 79794 } diff --git a/src/java/main/gov/noaa/messageapi/connections/DefaultConnection.java b/src/java/main/gov/noaa/messageapi/connections/DefaultConnection.java index 309e140..f62a83c 100644 --- a/src/java/main/gov/noaa/messageapi/connections/DefaultConnection.java +++ b/src/java/main/gov/noaa/messageapi/connections/DefaultConnection.java @@ -9,7 +9,6 @@ import java.util.UUID; import gov.noaa.messageapi.interfaces.IConnection; import gov.noaa.messageapi.interfaces.IPacket; import gov.noaa.messageapi.interfaces.IProtocolRecord; -import gov.noaa.messageapi.interfaces.ITransformationFactory; import gov.noaa.messageapi.definitions.ContainerDefinition; @@ -44,8 +43,7 @@ public class DefaultConnection extends BaseConnection implements IConnection { this.setClassifiers(new HashMap>()); } if (connectionMap.containsKey("transformations")) { - this.integrateTransformations((List) connectionMap.get("transformations"), - containerDefinition.getTransformationFactory(), containerDefinition.getTransformationMaps()); + this.integrateTransformations((List) connectionMap.get("transformations"), containerDefinition.getTransformationMaps()); } else { this.setTransformationMap(new HashMap>()); } @@ -178,16 +176,15 @@ public class DefaultConnection extends BaseConnection implements IConnection { * are parent transformations of named transformations, as well as classifiers and connections * used by any transformation. * @param transformations The named transformations included on the connection spec itself - * @param transformationFactory A class factory that contains key/value pairs of transformation operator keywords and class references * @param rawTransformationMaps The raw transformation maps containing entire transformation specifications */ - private void integrateTransformations(List transformations,ITransformationFactory transformationFactory, List> rawTransformationMaps) { + private void integrateTransformations(List transformations, List> rawTransformationMaps) { List allTransformationIds = ConnectionUtils.getAllTransformationIds(transformations, rawTransformationMaps); List transformationCollections = ConnectionUtils.getTransformationCollections(allTransformationIds, rawTransformationMaps); Map> transformationClassifiers = ConnectionUtils.getTransformationClassifiers(allTransformationIds, rawTransformationMaps); Map> transformationMap = ConnectionUtils.buildTransformationMap(allTransformationIds, - rawTransformationMaps, transformationFactory); + rawTransformationMaps); this.addCollections(transformationCollections); this.addClassifiers(transformationClassifiers); this.setTransformationMap(transformationMap); diff --git a/src/java/main/gov/noaa/messageapi/definitions/ContainerDefinition.java b/src/java/main/gov/noaa/messageapi/definitions/ContainerDefinition.java index 3bedd10..b5fbea9 100644 --- a/src/java/main/gov/noaa/messageapi/definitions/ContainerDefinition.java +++ b/src/java/main/gov/noaa/messageapi/definitions/ContainerDefinition.java @@ -6,12 +6,10 @@ import java.util.HashMap; import java.util.ArrayList; import java.util.stream.Collectors; -import gov.noaa.messageapi.interfaces.ITransformationFactory; import gov.noaa.messageapi.parsers.containers.MetadataParser; import gov.noaa.messageapi.parsers.containers.CollectionParser; import gov.noaa.messageapi.parsers.containers.TransformationParser; -import gov.noaa.messageapi.parsers.containers.TransformationFactoryParser; /** * A container definition holds the definition of a container. It essentially @@ -26,16 +24,10 @@ public class ContainerDefinition { private Map metadataMap = null; private List> collectionMaps = null; private List> transformationMaps = null; - private ITransformationFactory transformationFactory = null; private List collections = null; private List transformations = null; private List> classifiers = null; - - private static final String DEFAULT_TRANSFORMATION_FACTORY = - "gov.noaa.messageapi.factories.SimpleTransformationFactory"; - - @SuppressWarnings("unchecked") public ContainerDefinition(Map properties) throws Exception { if (properties.containsKey("metadata")) { @@ -64,9 +56,6 @@ public class ContainerDefinition { this.transformationMaps = new ArrayList>(definition.getTransformationMaps()); } - private void createTransformationFactory(String transformationClass) throws Exception { - this.transformationFactory = TransformationFactoryParser.build(transformationClass); - } private void parseMetadataSpec(String spec) throws Exception { MetadataParser parser = new MetadataParser(spec); @@ -85,11 +74,6 @@ public class ContainerDefinition { TransformationParser parser = new TransformationParser(transformationSpec.get("map")); this.transformationMaps = parser.getTransformationMaps(); this.transformations = parser.getTransformations(); - if (transformationSpec.containsKey("factory")) { - this.createTransformationFactory((String) transformationSpec.get("factory")); - } else { - this.createTransformationFactory(DEFAULT_TRANSFORMATION_FACTORY); - } } else { this.setEmptyTransformationMaps(); } @@ -123,10 +107,6 @@ public class ContainerDefinition { return this.transformationMaps; } - public ITransformationFactory getTransformationFactory() { - return this.transformationFactory; - } - /** * Sets the definition transformation maps to be empty, the transformation * factory to be the default. @@ -134,7 +114,6 @@ public class ContainerDefinition { private void setEmptyTransformationMaps() throws Exception { this.transformationMaps = new ArrayList>(); this.transformations = new ArrayList(); - this.createTransformationFactory(DEFAULT_TRANSFORMATION_FACTORY); } /** diff --git a/src/java/main/gov/noaa/messageapi/factories/SimpleTransformationFactory.java b/src/java/main/gov/noaa/messageapi/factories/SimpleTransformationFactory.java deleted file mode 100644 index 72272e4..0000000 --- a/src/java/main/gov/noaa/messageapi/factories/SimpleTransformationFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package gov.noaa.messageapi.factories; - -import java.util.Map; -import java.util.List; - -import gov.noaa.messageapi.interfaces.ITransformation; -import gov.noaa.messageapi.interfaces.ITransformationFactory; - -import gov.noaa.messageapi.transformations.joins.StringFieldJoin; -import gov.noaa.messageapi.transformations.reductions.ReduceTransformation; - -/** - * @author Ryan Berkheimer - */ -public class SimpleTransformationFactory implements ITransformationFactory { - - /** - * Returns an operator based on a data type name as a string. - * @param type The type of operator to return - * @return A new operator based on the specified type - */ - public ITransformation getTransformation(String type, List fields, Map params) { - switch (type) { - case "join": - return new StringFieldJoin(fields, params); - case "reduce": - return new ReduceTransformation(fields, params); - } - return null; - } - -} diff --git a/src/java/main/gov/noaa/messageapi/interfaces/ITransformationFactory.java b/src/java/main/gov/noaa/messageapi/interfaces/ITransformationFactory.java deleted file mode 100644 index af502cc..0000000 --- a/src/java/main/gov/noaa/messageapi/interfaces/ITransformationFactory.java +++ /dev/null @@ -1,13 +0,0 @@ -package gov.noaa.messageapi.interfaces; - -import java.util.Map; -import java.util.List; - -/** - * @author Ryan Berkheimer - */ -public interface ITransformationFactory { - - public ITransformation getTransformation(String id, List fields, Map params); - -} diff --git a/src/java/main/gov/noaa/messageapi/parsers/containers/TransformationFactoryParser.java b/src/java/main/gov/noaa/messageapi/parsers/containers/TransformationFactoryParser.java deleted file mode 100644 index 37a2195..0000000 --- a/src/java/main/gov/noaa/messageapi/parsers/containers/TransformationFactoryParser.java +++ /dev/null @@ -1,23 +0,0 @@ -package gov.noaa.messageapi.parsers.containers; - -import gov.noaa.messageapi.interfaces.ITransformationFactory; - -/** - * @author Ryan Berkheimer - */ -public class TransformationFactoryParser { - - public static ITransformationFactory build(String transformationClass) throws Exception { - try { - return (ITransformationFactory) constructPlugin(Class.forName(transformationClass)); - } catch (Exception e) { - System.err.println(String.format("Could not construct the TransformationFactory using the given class %s", transformationClass)); - return null; - } - } - - private static Object constructPlugin(Class pluginClass) throws Exception { - return pluginClass.getConstructor().newInstance(); - } - -} diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java index 8df3109..26aecd0 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java @@ -29,7 +29,7 @@ public class ContainerPluginParser extends BasePluginParser implements IPluginPa protected Set getRequiredConstructorKeys() { Set set = new HashSet(); - set.add("metadata"); + //set.add("metadata"); set.add("collections"); return set; } diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java index 1520533..6ab3aad 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java @@ -30,7 +30,7 @@ public class ProtocolPluginParser extends BasePluginParser implements IPluginPar protected Set getRequiredConstructorKeys() { Set set = new HashSet(); - set.add("metadata"); + //set.add("metadata"); set.add("endpoints"); return set; } diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java index 68d3d14..99454c1 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java @@ -29,7 +29,7 @@ public class SchemaPluginParser extends BasePluginParser implements IPluginParse protected Set getRequiredConstructorKeys() { Set set = new HashSet(); - set.add("metadata"); + //set.add("metadata"); set.add("fields"); return set; } diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java index 46535c0..d33a70c 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java @@ -12,9 +12,6 @@ import gov.noaa.messageapi.interfaces.ISchema; import gov.noaa.messageapi.interfaces.IPluginParser; import gov.noaa.messageapi.parsers.plugins.BasePluginParser; -//import gov.noaa.messageapi.parsers.plugins.ContainerPluginParser; -//import gov.noaa.messageapi.parsers.plugins.ProtocolPluginParser; -//import gov.noaa.messageapi.parsers.plugins.SchemaPluginParser; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java new file mode 100644 index 0000000..7ef0056 --- /dev/null +++ b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java @@ -0,0 +1,53 @@ +package gov.noaa.messageapi.transformations; + +import java.util.Map; +import java.util.List; + +import gov.noaa.messageapi.interfaces.ITransformation; +import gov.noaa.messageapi.interfaces.IRecord; + +/** + *

NativeTransformation

This is a wrapper class for transformations that call into + * native code held as binary libs through the JNI (Java Native + * Interface). + *

+ * This transformation is designed so that native code doesn't have to provide an + * additional Java wrapper. The native library code will have to be built + * with a C wrapper that imports the Transformation.h header. A guide for building these + * native libraries can be seen in the examples, and is facilitated by the use of the + * provided makefile templates. + *

+ * To make use of this transformation, users are asked to configure 1 + * property in the manifest: + *

+ * native-library(required, string) - corresponds to a fully + * qualified path pointing to the native library binary. This is usually a .so, + * .dll, or .jnilib, depending on operating system. + *

+ * + * @author Ryan Berkheimer + */ +public class NativeTransformation implements ITransformation { + + private native List process(long nativeInstance); + private synchronized native long create(Map> recordMap); + private synchronized native void release(long instanceId); + + public NativeTransformation(Map params) { + this.loadNativeLib((String)params.get("native-library")); + } + + public void loadNativeLib(String nativeLibrary) { + try { + System.load(nativeLibrary); + } catch (Exception e) {} + } + + public List process(Map> recordMap) { + long nativeInstance = this.create(recordMap); + List transformedRecords = this.process(nativeInstance); + this.release(nativeInstance); + return transformedRecords; + } + +} \ No newline at end of file diff --git a/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java b/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java index adc48bb..2f5d93c 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java +++ b/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java @@ -64,7 +64,7 @@ public class StringFieldJoin implements ITransformation { private IField joinField = null; private IField collectionField = null; - public StringFieldJoin(List fields, Map params) { + public StringFieldJoin(Map params) { this.setJoinField((String) params.get("join-field")); this.setCollectionField((String) params.get("collection-field")); } diff --git a/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java index 12cd71d..23e9e88 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java +++ b/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java @@ -12,7 +12,7 @@ import gov.noaa.messageapi.interfaces.ITransformation; */ public class ReduceTransformation implements ITransformation { - public ReduceTransformation(List fields, Map params) {} + public ReduceTransformation(Map params) {} public List process(Map> transformationMap) { return transformationMap.get("reduce-list"); diff --git a/src/java/main/gov/noaa/messageapi/utils/protocol/ConnectionUtils.java b/src/java/main/gov/noaa/messageapi/utils/protocol/ConnectionUtils.java index c0d1323..98d7666 100644 --- a/src/java/main/gov/noaa/messageapi/utils/protocol/ConnectionUtils.java +++ b/src/java/main/gov/noaa/messageapi/utils/protocol/ConnectionUtils.java @@ -4,14 +4,15 @@ import java.util.Map; import java.util.List; import java.util.Optional; import java.util.HashMap; +import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.stream.Collectors; import java.util.concurrent.CompletableFuture; import gov.noaa.messageapi.interfaces.IConnection; import gov.noaa.messageapi.interfaces.IProtocolRecord; +import gov.noaa.messageapi.interfaces.ITransformation; import gov.noaa.messageapi.interfaces.IPacket; -import gov.noaa.messageapi.interfaces.ITransformationFactory; import gov.noaa.messageapi.utils.general.ListUtils; import gov.noaa.messageapi.utils.general.MapUtils; @@ -103,14 +104,26 @@ public class ConnectionUtils { return returnMap; } + public static ITransformation getTransformationInstance(String transformationClass, Map args) { + try { + Class pluginClass = Class.forName(transformationClass); + Class[] ctrClasses = { Map.class }; + Constructor constructor = pluginClass.getDeclaredConstructor(ctrClasses); + return (ITransformation) constructor.newInstance(args); + } catch (Exception e){ + System.out.println("couldnt build a transformation instance!!!"); + return null; + } + } + @SuppressWarnings("unchecked") - public static Map> buildTransformationMap(List ids, List> allMaps, ITransformationFactory factory) { + public static Map> buildTransformationMap(List ids, List> allMaps) { List> idMaps = allMaps.stream().filter(m -> ids.contains((String)m.get("id"))).collect(Collectors.toList()); List>> tMaps = idMaps.stream().map(m -> { Map> templateMap = new HashMap>(); Map valMap = new HashMap(); - valMap.put("instance", factory.getTransformation((String)m.get("operator"), (List)m.get("fields"), (Map)m.get("constructor"))); + valMap.put("instance", ConnectionUtils.getTransformationInstance((String)m.get("operator"), (Map)m.get("constructor"))); valMap.put("parameters", ConnectionUtils.makeRecordSymbolMaps((Map)m.get("records"))); templateMap.put((String)m.get("id"), valMap); return templateMap; diff --git a/src/java/test/gov/noaa/messageapi/test/factories/transformations/FileReaderFactory.java b/src/java/test/gov/noaa/messageapi/test/factories/transformations/FileReaderFactory.java deleted file mode 100644 index 146224f..0000000 --- a/src/java/test/gov/noaa/messageapi/test/factories/transformations/FileReaderFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package gov.noaa.messageapi.test.factories.transformations; - -import java.util.Map; -import java.util.List; - -import gov.noaa.messageapi.interfaces.ITransformation; -import gov.noaa.messageapi.interfaces.ITransformationFactory; -import gov.noaa.messageapi.test.transformations.FixRelativePathsTransformation; - -/** - * @author Ryan Berkheimer - */ -public class FileReaderFactory implements ITransformationFactory { - - /** - * Returns an operator based on a data type name as a string. - * @param type The type of operator to return - * @return A new operator based on the specified type - */ - public ITransformation getTransformation(String type, List fields, Map params) { - switch (type) { - case "fix-relative-paths": - return new FixRelativePathsTransformation(fields, params); - default: - return null; - } - } - -} diff --git a/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java b/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java index 42bdab2..5e0cc67 100644 --- a/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java +++ b/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java @@ -30,8 +30,9 @@ public class FixRelativePathsTransformation implements ITransformation { private List relativePathFields = null; private String transformKey = null; - public FixRelativePathsTransformation(List fields, Map params) { - this.setRelativePathFields(fields); + @SuppressWarnings("unchecked") + public FixRelativePathsTransformation(Map params) { + this.setRelativePathFields((List) params.get("fields")); this.setTransformKey((String) params.get("transform-key")); } -- GitLab From 996b9ff0b4d588dab47aef4792285ca1475c5ddc Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sat, 30 May 2020 18:08:00 -0400 Subject: [PATCH 04/53] remove copy action from filterFieldlessConditions method. Turn off filterNonValuedFields on record validation (this was breaking the native interop in some cases). --- src/groovy/test/endtoend/NativeEndpointTests.groovy | 7 ------- .../gov/noaa/messageapi/utils/request/PacketUtils.java | 3 +-- .../gov/noaa/messageapi/utils/request/SchemaUtils.java | 8 +++++--- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/groovy/test/endtoend/NativeEndpointTests.groovy b/src/groovy/test/endtoend/NativeEndpointTests.groovy index e2504ed..1b5e379 100644 --- a/src/groovy/test/endtoend/NativeEndpointTests.groovy +++ b/src/groovy/test/endtoend/NativeEndpointTests.groovy @@ -39,15 +39,8 @@ def 'Session with one endpoint that calls into C, populates a return record, and IResponse response = request.submit() while (!response.isComplete()) { } then: 'No rejections, one return record, field values match..' - println "finished!!!!" response.getRejections().size() == 0 - println "rejection size:" - println response.getRejections().size() - println "record size:" - println response.getRecords().size() response.getRecords().size() == 1 - println "test-integer value:" - println response.getRecords().get(0).getField('test-integer').getValue() response.getRecords().get(0).getField('test-integer').getValue() == 5 response.getRecords().get(0).getField('return-list').getValue().get(0) == "first element of our string!" response.getRecords().get(0).getField('return-list').getValue().get(1) == "second element of our string!!" diff --git a/src/java/main/gov/noaa/messageapi/utils/request/PacketUtils.java b/src/java/main/gov/noaa/messageapi/utils/request/PacketUtils.java index f53d4d9..d810916 100644 --- a/src/java/main/gov/noaa/messageapi/utils/request/PacketUtils.java +++ b/src/java/main/gov/noaa/messageapi/utils/request/PacketUtils.java @@ -27,8 +27,7 @@ public class PacketUtils { List primaryRejections = RejectionUtils.getRequiredFieldRejections(records); List filteredRecords = SchemaUtils.filterFieldlessConditions( SchemaUtils.filterNonValuedConditions( - SchemaUtils.filterNonValuedFields( - SchemaUtils.filterRejections(records, primaryRejections)))); + SchemaUtils.filterRejections(records, primaryRejections))); List secondaryRejections = RejectionUtils.getFieldConditionRejections(schema, filteredRecords); dataPacket.setRecords(SchemaUtils.filterRejections(filteredRecords, secondaryRejections)); dataPacket.setRejections(ListUtils.flatten(new ArrayList>(Arrays.asList(primaryRejections, secondaryRejections)))); diff --git a/src/java/main/gov/noaa/messageapi/utils/request/SchemaUtils.java b/src/java/main/gov/noaa/messageapi/utils/request/SchemaUtils.java index 3bde2ef..c46c59f 100644 --- a/src/java/main/gov/noaa/messageapi/utils/request/SchemaUtils.java +++ b/src/java/main/gov/noaa/messageapi/utils/request/SchemaUtils.java @@ -63,9 +63,11 @@ public class SchemaUtils { public static List filterNonValuedConditions(List records) { return records.stream().map(r -> { List conditions = ConditionUtils.filterNonValuedConditions(r.getConditions()); - IRecord newR = r.getCopy(); - newR.setConditions(conditions); - return newR; + //IRecord newR = r.getCopy(); + //newR.setConditions(conditions); + r.setConditions(conditions); + //return newR; + return r; }).collect(Collectors.toList()); } -- GitLab From be6578325b629e81fbb0ad0d105bff8066ad4739 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sat, 30 May 2020 18:23:46 -0400 Subject: [PATCH 05/53] update boolean to Boolean in Interface methods available to C/C++, update signature strings in C/C++ api refs. This is to maintain uniformity (Bool chosen over bool) --- resources/test/basic-native/parameters.json | 3 ++- src/cpp/main/common/FieldUtils.cpp | 4 ++-- src/cpp/main/common/RecordUtils.cpp | 8 ++++---- src/cpp/main/common/ResponseUtils.cpp | 4 ++-- src/groovy/test/endtoend/NativeEndpointTests.groovy | 2 +- .../main/gov/noaa/messageapi/fields/DefaultField.java | 6 +++--- src/java/main/gov/noaa/messageapi/interfaces/IField.java | 6 +++--- .../main/gov/noaa/messageapi/interfaces/IResponse.java | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/resources/test/basic-native/parameters.json b/resources/test/basic-native/parameters.json index 768cf2b..bf0c8ca 100644 --- a/resources/test/basic-native/parameters.json +++ b/resources/test/basic-native/parameters.json @@ -30,7 +30,8 @@ "constructor": {"native-library": "/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/lib/test/native/demoendpointlibrary/libDemoEndpointLibrary.jnilib", "default-fields": [{"id": "test-integer", "type": "integer", - "required": false}, + "required": false, + "value": 5}, {"id": "return-list", "type": "list(string)", "required": false}], diff --git a/src/cpp/main/common/FieldUtils.cpp b/src/cpp/main/common/FieldUtils.cpp index 9bf2083..e5bc3a3 100644 --- a/src/cpp/main/common/FieldUtils.cpp +++ b/src/cpp/main/common/FieldUtils.cpp @@ -240,11 +240,11 @@ const char *FieldUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "isValid") == 0) { - return "()Z"; + return "()Ljava/lang/Boolean;"; } else if (strcmp(methodName, "isRequired") == 0) { - return "()Z"; + return "()Ljava/lang/Boolean;"; } else if (strcmp(methodName, "setValue") == 0) { diff --git a/src/cpp/main/common/RecordUtils.cpp b/src/cpp/main/common/RecordUtils.cpp index d45e9a7..86ca840 100644 --- a/src/cpp/main/common/RecordUtils.cpp +++ b/src/cpp/main/common/RecordUtils.cpp @@ -192,11 +192,11 @@ const char *RecordUtils::getMethodSignature(const char *methodName) { if (strcmp(methodName, "isValid") == 0) { - return "()Z"; + return "()Ljava/lang/Boolean;"; } else if (strcmp(methodName, "setValid") == 0) { - return "(Z)V"; + return "(Ljava/lang/Boolean;)V"; } else if (strcmp(methodName, "getCopy") == 0) @@ -209,7 +209,7 @@ const char *RecordUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "hasField") == 0) { - return "(Ljava/lang/String;)Z"; + return "(Ljava/lang/String;)Ljava/lang/Boolean;"; } else if (strcmp(methodName, "getFields") == 0) { @@ -225,7 +225,7 @@ const char *RecordUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "hasCondition") == 0) { - return "(Ljava/lang/String;)Z"; + return "(Ljava/lang/String;)Ljava/lang/Boolean;"; } else if (strcmp(methodName, "getConditions") == 0) { diff --git a/src/cpp/main/common/ResponseUtils.cpp b/src/cpp/main/common/ResponseUtils.cpp index 21bfc82..9dcf712 100644 --- a/src/cpp/main/common/ResponseUtils.cpp +++ b/src/cpp/main/common/ResponseUtils.cpp @@ -114,7 +114,7 @@ const char *ResponseUtils::getMethodSignature(const char *methodName) { if (strcmp(methodName, "isComplete") == 0) { - return "()Z"; + return "()Ljava/lang/Boolean;"; } else if (strcmp(methodName, "getRequest") == 0) { @@ -138,7 +138,7 @@ const char *ResponseUtils::getMethodSignature(const char *methodName) } else if (strcmp(methodName, "setComplete") == 0) { - return "(Z)V"; + return "(Ljava/lang/Boolean;)V"; } return NULL; } \ No newline at end of file diff --git a/src/groovy/test/endtoend/NativeEndpointTests.groovy b/src/groovy/test/endtoend/NativeEndpointTests.groovy index 1b5e379..6263382 100644 --- a/src/groovy/test/endtoend/NativeEndpointTests.groovy +++ b/src/groovy/test/endtoend/NativeEndpointTests.groovy @@ -28,7 +28,7 @@ def 'Session with one endpoint that calls into C, populates a return record, and record1.setField('null-test', 'null') record2.setField('string-test', 'cool!') record2.setField('initial-value', 5000) - record2.setField('null-test', 'null') + //record2.setField('null-test', 'null') /*for (int i=0; i<500; i++) { IRecord r = request.createRecord(); r.setField("initial-value", i); diff --git a/src/java/main/gov/noaa/messageapi/fields/DefaultField.java b/src/java/main/gov/noaa/messageapi/fields/DefaultField.java index 4e36245..7f98448 100644 --- a/src/java/main/gov/noaa/messageapi/fields/DefaultField.java +++ b/src/java/main/gov/noaa/messageapi/fields/DefaultField.java @@ -67,15 +67,15 @@ public class DefaultField implements IField { return this.type; } - public boolean isRequired() { + public Boolean isRequired() { return this.required; } - public boolean isValid() { + public Boolean isValid() { return this.valid; } - public void setValid(boolean valid) { + public void setValid(Boolean valid) { this.valid = valid; } diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IField.java b/src/java/main/gov/noaa/messageapi/interfaces/IField.java index b19adb2..8f9f737 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IField.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IField.java @@ -34,14 +34,14 @@ public interface IField { * Used contextually to determine whether * or not this field is required for subsequent processing. */ - public boolean isRequired(); + public Boolean isRequired(); /** * Used contextually to determine whether or not * this field is valid. This could be used in type validation * or some other way. */ - public boolean isValid(); + public Boolean isValid(); /** * Returns the value of the field. @@ -58,7 +58,7 @@ public interface IField { * Sets true or false whether or not the field is * valid against some generalized criteria */ - public void setValid(boolean valid); + public void setValid(Boolean valid); /** * Allows setting of the type of the field as a string. diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IResponse.java b/src/java/main/gov/noaa/messageapi/interfaces/IResponse.java index f766e7f..b0a371d 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IResponse.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IResponse.java @@ -9,7 +9,7 @@ import java.util.List; * any processing steps (validation, factoring, transformation, etc.) * in sequence, eventually yielding a set of returned data packets from * endpoint connections, where it combines them and sets a response - * list of records, list of rejections, and changes the isComplete boolean + * list of records, list of rejections, and changes the isComplete Boolean * to true. * @author Ryan Berkheimer */ -- GitLab From 375a4c31acf117d510697d56ba603d7ed09d4630 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 10:57:25 -0400 Subject: [PATCH 06/53] completed MapUtils class --- .../main/common/structs/messageapi_structs.h | 9 +- src/cpp/main/common/MapUtils.cpp | 270 ++++++++++-------- src/cpp/main/common/MapUtils.h | 85 +++--- src/cpp/main/common/MessageApiEndpoint.cpp | 7 + src/cpp/main/common/MessageApiEndpoint.h | 3 + src/cpp/main/common/TypeUtils.cpp | 7 + src/cpp/main/common/TypeUtils.h | 2 + 7 files changed, 215 insertions(+), 168 deletions(-) diff --git a/src/c/main/common/structs/messageapi_structs.h b/src/c/main/common/structs/messageapi_structs.h index b97ce34..089b969 100644 --- a/src/c/main/common/structs/messageapi_structs.h +++ b/src/c/main/common/structs/messageapi_structs.h @@ -8,9 +8,9 @@ * @author Ryan Berkheimer */ -struct list_item +struct map_val { - jobject jitem; + jobject jval; }; struct val_map @@ -18,6 +18,11 @@ struct val_map jobject jmap; }; +struct list_item +{ + jobject jitem; +}; + struct val_list { int count; diff --git a/src/cpp/main/common/MapUtils.cpp b/src/cpp/main/common/MapUtils.cpp index cf79aa0..99d9f8b 100644 --- a/src/cpp/main/common/MapUtils.cpp +++ b/src/cpp/main/common/MapUtils.cpp @@ -1,12 +1,14 @@ -#include "ListUtils.h" +#include "MapUtils.h" -ListUtils::ListUtils(JNIEnv *env, TypeUtils *typeUtils) +/* Default Constructor */ +MapUtils::MapUtils(JNIEnv *env, TypeUtils *typeUtils) { this->loadGlobalRefs(env, typeUtils); this->loadMethodIds(); } -ListUtils::~ListUtils() +/* Default destructor */ +MapUtils::~MapUtils() { try { @@ -17,248 +19,262 @@ ListUtils::~ListUtils() } } -void ListUtils::loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils) +void MapUtils::loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils) { this->jvm = env; this->typeUtils = typeUtils; } -void ListUtils::loadMethodIds() +void MapUtils::loadMethodIds() { - jclass listClass = JniUtils::getNamedClass(this->jvm, "java/util/List"); - this->getListSizeMethodId = this->jvm->GetMethodID(listClass, "size", "()I"); - this->getListItemMethodId = this->jvm->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;"); - this->addListItemMethodId = this->jvm->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z"); - this->jvm->DeleteLocalRef(listClass); + jclass mapClass = JniUtils::getNamedClass(this->jvm, "java/util/Map"); - this->createListMethodId = this->jvm->GetMethodID(this->typeUtils->getListClass(), "", "()V"); + this->getSizeMethodId = this->jvm->GetMethodID(mapClass, "size", "()I"); + this->hasKeyMethodId = this->jvm->GetMethodID(mapClass, "containsKey", "(Ljava/lang/Object;)Z"); + this->getValueMethodId = this->jvm->GetMethodID(mapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); + this->putValueMethodId = this->jvm->GetMethodID(mapClass, "put", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;"); + + this->jvm->DeleteLocalRef(mapClass); + + this->createMapMethodId = this->jvm->GetMethodID(this->typeUtils->getMapClass(), "", "()V"); } -jmethodID ListUtils::createListMethod() +jmethodID MapUtils::createMapMethod() { - return this->createListMethodId; + return this->createMapMethodId; } -jmethodID ListUtils::getListSizeMethod() +jmethodID MapUtils::getSizeMethod() { - return this->getListSizeMethodId; + return this->getSizeMethodId; } -jmethodID ListUtils::getListItemMethod() +jmethodID MapUtils::hasKeyMethod() { - return this->getListItemMethodId; + return this->hasKeyMethodId; } -jmethodID ListUtils::addListItemMethod() +jmethodID MapUtils::getValueMethod() { - return this->addListItemMethodId; + return this->getValueMethodId; } -struct val_list *ListUtils::createList() +jmethodID MapUtils::putValueMethod() { - jobject jList = this->jvm->NewObject(this->typeUtils->getListClass(), this->createListMethod()); - struct val_list *valueList = (struct val_list *)malloc(sizeof(struct val_list)); - valueList->count = 0; - valueList->jlist = jList; - return valueList; + return this->putValueMethodId; } -int ListUtils::getListLength(jobject jList) +struct val_map *MapUtils::createMap() { - return (int)this->jvm->CallIntMethod(jList, this->getListSizeMethod()); + jobject jMap = this->jvm->NewObject(this->typeUtils->getMapClass(), this->createMapMethod()); + struct val_map *valueMap = (struct val_map *)malloc(sizeof(struct val_map)); + valueMap->jmap = jMap; + return valueMap; } -struct list_item *ListUtils::getItem(struct val_list *list, int index) +int MapUtils::getSize(val_map *val_map) { - struct list_item *listItem = (struct list_item *)malloc(sizeof(struct list_item)); - listItem->jitem = this->getObjectItem(list, index); - return listItem; + return (int)this->jvm->CallIntMethod(val_map->jmap, this->getSizeMethod()); } -jobject ListUtils::getObjectItem(struct val_list *val_list, int index) +bool MapUtils::hasKey(val_map *val_map, const char *key) { - return static_cast(this->jvm->CallObjectMethod(val_list->jlist, this->getListItemMethod(), index)); + return (bool)this->jvm->CallBooleanMethod(val_map->jmap, this->hasKeyMethod()); } -struct val_list *ListUtils::getListItem(struct val_list *list, int index) +/*Map Value Retrieval Methods*/ +struct map_val *MapUtils::getVal(struct val_map *map, const char *key) { - jobject listItem = this->getObjectItem(list, index); - int itemCount = this->getListLength(listItem); - struct val_list *valueList = (struct val_list *)malloc(sizeof(struct val_list)); - valueList->count = itemCount; - valueList->jlist = listItem; - return valueList; + struct map_val *mapVal = (struct map_val *)malloc(sizeof(struct map_val)); + mapVal->jval = this->getObjectVal(map, key); + return mapVal; } -int ListUtils::getIntItem(struct val_list *list, int index) +jobject MapUtils::getObjectVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - int val = (int)this->jvm->CallIntMethod(list_item, this->typeUtils->getIntMethod()); - jvm->DeleteLocalRef(list_item); + jstring jkey = this->typeUtils->toJavaString(key); + jobject objectVal = static_cast(this->jvm->CallObjectMethod(map->jmap, this->getValueMethod(), jkey)); + this->jvm->DeleteLocalRef(jkey); + return objectVal; +} + +int MapUtils::getIntVal(struct val_map *map, const char *key) +{ + jobject jval = this->getObjectVal(map, key); + int val = (int)this->jvm->CallIntMethod(jval, this->typeUtils->getIntMethod()); + jvm->DeleteLocalRef(jval); return val; } -long ListUtils::getLongItem(struct val_list *list, int index) +long MapUtils::getLongVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - long val = (long)this->jvm->CallLongMethod(list_item, this->typeUtils->getLongMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + long val = (long)this->jvm->CallLongMethod(jval, this->typeUtils->getLongMethod()); + jvm->DeleteLocalRef(jval); return val; } -float ListUtils::getFloatItem(struct val_list *list, int index) +float MapUtils::getFloatVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - float val = (float)this->jvm->CallFloatMethod(list_item, this->typeUtils->getFloatMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + float val = (float)this->jvm->CallFloatMethod(jval, this->typeUtils->getFloatMethod()); + jvm->DeleteLocalRef(jval); return val; } -double ListUtils::getDoubleItem(struct val_list *list, int index) +double MapUtils::getDoubleVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - double val = (double)this->jvm->CallDoubleMethod(list_item, this->typeUtils->getDoubleMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + double val = (double)this->jvm->CallDoubleMethod(jval, this->typeUtils->getDoubleMethod()); + jvm->DeleteLocalRef(jval); return val; } -signed char ListUtils::getByteItem(struct val_list *list, int index) +signed char MapUtils::getByteVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - signed char val = (signed char)this->jvm->CallByteMethod(list_item, this->typeUtils->getByteMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + signed char val = (signed char)this->jvm->CallByteMethod(jval, this->typeUtils->getByteMethod()); + jvm->DeleteLocalRef(jval); return val; } -const char *ListUtils::getStringItem(struct val_list *list, int index) +const char *MapUtils::getStringVal(struct val_map *map, const char *key) { - jstring jString = static_cast(this->jvm->CallObjectMethod(list->jlist, this->getListItemMethod(), index)); + jstring jString = static_cast(this->jvm->CallObjectMethod(map->jmap, this->getValueMethod(), key)); const char *val = this->typeUtils->fromJavaString(jString); jvm->DeleteLocalRef(jString); return val; } -bool ListUtils::getBoolItem(struct val_list *list, int index) +bool MapUtils::getBoolVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - bool val = (bool)this->jvm->CallBooleanMethod(list_item, this->typeUtils->getBoolMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + bool val = (bool)this->jvm->CallBooleanMethod(jval, this->typeUtils->getBoolMethod()); + jvm->DeleteLocalRef(jval); return val; } -short ListUtils::getShortItem(struct val_list *list, int index) +short MapUtils::getShortVal(struct val_map *map, const char *key) { - jobject list_item = this->getObjectItem(list, index); - short val = (short)this->jvm->CallShortMethod(list_item, this->typeUtils->getShortMethod()); - jvm->DeleteLocalRef(list_item); + jobject jval = this->getObjectVal(map, key); + short val = (short)this->jvm->CallShortMethod(jval, this->typeUtils->getShortMethod()); + jvm->DeleteLocalRef(jval); return val; } -void ListUtils::addObjectItem(struct val_list *list, jobject val) +struct val_list *MapUtils::getListVal(struct val_map *map, const char *key) +{ + jobject listItem = this->getObjectVal(map, key); + struct val_list *valueList = (struct val_list *)malloc(sizeof(struct val_list)); + valueList->jlist = listItem; + return valueList; +} + +struct val_map *MapUtils::getMapVal(struct val_map *map, const char *key) { - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), val); - list->count += 1; + jobject jValMap = this->getObjectVal(map, key); + struct val_map *valMap = (struct val_map *)malloc(sizeof(struct val_map)); + valMap->jmap = jValMap; + return valMap; } -void ListUtils::addItem(struct val_list *list, struct list_item *item) +/*Insert or Update Methods*/ +void MapUtils::putVal(struct val_map *map, const char *key, struct map_val *val) { - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), item->jitem); - list->count += 1; + jstring jKey = this->typeUtils->toJavaString(key); + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, val->jval); + this->jvm->DeleteLocalRef(jKey); } -void ListUtils::addIntItem(struct val_list *list, int val) +void MapUtils::putObjectVal(struct val_map *map, const char *key, jobject val) { + jstring jKey = this->typeUtils->toJavaString(key); + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, val); + this->jvm->DeleteLocalRef(jKey); +} + +void MapUtils::putIntVal(struct val_map *map, const char *key, int val) +{ + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getIntClass(), this->typeUtils->createIntMethod(), (jint)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addLongItem(struct val_list *list, long val) +void MapUtils::putLongVal(struct val_map *map, const char *key, long val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getLongClass(), this->typeUtils->createLongMethod(), (jlong)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addFloatItem(struct val_list *list, float val) +void MapUtils::putFloatVal(struct val_map *map, const char *key, float val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getFloatClass(), this->typeUtils->createFloatMethod(), (jfloat)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addDoubleItem(struct val_list *list, double val) +void MapUtils::putDoubleVal(struct val_map *map, const char *key, double val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getDoubleClass(), this->typeUtils->createDoubleMethod(), (jdouble)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addByteItem(struct val_list *list, signed char val) +void MapUtils::putByteVal(struct val_map *map, const char *key, signed char val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getByteClass(), this->typeUtils->createByteMethod(), (jbyte)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addStringItem(struct val_list *list, const char *val) +void MapUtils::putStringVal(struct val_map *map, const char *key, const char *val) { + jstring jKey = this->typeUtils->toJavaString(key); jstring jVal = this->typeUtils->toJavaString(val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addBoolItem(struct val_list *list, bool val) +void MapUtils::putBoolVal(struct val_map *map, const char *key, bool val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getBoolClass(), this->typeUtils->createBoolMethod(), (jboolean)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addShortItem(struct val_list *list, short val) +void MapUtils::putShortVal(struct val_map *map, const char *key, short val) { + jstring jKey = this->typeUtils->toJavaString(key); jobject jVal = jvm->NewObject(this->typeUtils->getShortClass(), this->typeUtils->createShortMethod(), (jshort)val); - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), jVal); - list->count += 1; + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, jVal); + this->jvm->DeleteLocalRef(jKey); this->jvm->DeleteLocalRef(jVal); } -void ListUtils::addListItem(struct val_list *list, struct val_list *val) +void MapUtils::putListVal(struct val_map *map, const char *key, struct val_list *val) { - this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), val->jlist); - list->count += 1; + jstring jKey = this->typeUtils->toJavaString(key); + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, val->jlist); + this->jvm->DeleteLocalRef(jKey); } -struct string_list *ListUtils::translateStringList(jobject jList) +void MapUtils::putMapVal(struct val_map *map, const char *key, struct val_map *val) { - int stringCount = this->getListLength(jList); - char **strings = (char **)malloc(sizeof(char *) * stringCount); - int maxStringLength = 0; - for (int i = 0; i < stringCount; i++) - { - jstring jString = static_cast(this->jvm->CallObjectMethod(jList, this->getListItemMethod(), i)); - const char *tempString = this->jvm->GetStringUTFChars(jString, NULL); - int tempMaxStringLength = strlen(tempString); - if (tempMaxStringLength > maxStringLength) - { - maxStringLength = tempMaxStringLength; - } - strings[i] = (char *)malloc((tempMaxStringLength + 1) * sizeof(char)); - strcpy(strings[i], tempString); - this->jvm->ReleaseStringUTFChars(jString, tempString); - this->jvm->DeleteLocalRef(jString); - } - - struct string_list *string_list = (struct string_list *)malloc(sizeof(struct string_list) + sizeof(strings)); - string_list->count = stringCount; - string_list->max_length = maxStringLength; - string_list->strings = strings; - return string_list; + jstring jKey = this->typeUtils->toJavaString(key); + this->jvm->CallVoidMethod(map->jmap, this->putValueMethod(), jKey, val->jmap); + this->jvm->DeleteLocalRef(jKey); } diff --git a/src/cpp/main/common/MapUtils.h b/src/cpp/main/common/MapUtils.h index 7d51e83..b81ecf7 100644 --- a/src/cpp/main/common/MapUtils.h +++ b/src/cpp/main/common/MapUtils.h @@ -6,11 +6,13 @@ #ifdef __cplusplus -#include "JniUtils.h" -#include "TypeUtils.h" #include #include +#include "JniUtils.h" +#include "TypeUtils.h" +#include "ListUtils.h" + /** * This is the header for the MapUtils object class. MapUtils contains a set of methods used for manipulation of Java Maps * in C++ or C code. MapUtils is a class to be instantiated so that it remains thread safe for implementors. @@ -27,49 +29,54 @@ public: /* Utility methods */ struct val_map *createMap(); - int getListLength(jobject jList); - struct string_list *translateStringList(jobject jList); - - /*List Item Retrieval Methods*/ - struct list_item *getItem(struct val_list *list, int index); - jobject getObjectItem(struct val_list *list, int index); - int getIntItem(struct val_list *list, int index); - long getLongItem(struct val_list *list, int index); - float getFloatItem(struct val_list *list, int index); - double getDoubleItem(struct val_list *list, int index); - signed char getByteItem(struct val_list *list, int index); - const char *getStringItem(struct val_list *list, int index); - bool getBoolItem(struct val_list *list, int index); - short getShortItem(struct val_list *list, int index); - struct val_list *getListItem(struct val_list *list, int index); - - /*List Item Insertion Methods*/ - void addItem(struct val_list *list, struct list_item *item); - void addObjectItem(struct val_list *list, jobject val); - void addIntItem(struct val_list *list, int val); - void addLongItem(struct val_list *list, long val); - void addFloatItem(struct val_list *list, float val); - void addDoubleItem(struct val_list *list, double val); - void addByteItem(struct val_list *list, signed char val); - void addStringItem(struct val_list *list, const char *val); - void addBoolItem(struct val_list *list, bool val); - void addShortItem(struct val_list *list, short val); - void addListItem(struct val_list *list, struct val_list *val); - - jmethodID createListMethod(); - jmethodID getListSizeMethod(); - jmethodID getListItemMethod(); - jmethodID addListItemMethod(); + int getSize(struct val_map *map); + bool hasKey(struct val_map *map, const char *key); + + /*Map Value Retrieval Methods*/ + struct map_val *getVal(struct val_map *map, const char *key); + jobject getObjectVal(struct val_map *map, const char *key); + int getIntVal(struct val_map *map, const char *key); + long getLongVal(struct val_map *map, const char *key); + float getFloatVal(struct val_map *map, const char *key); + double getDoubleVal(struct val_map *map, const char *key); + signed char getByteVal(struct val_map *map, const char *key); + const char *getStringVal(struct val_map *map, const char *key); + bool getBoolVal(struct val_map *map, const char *key); + short getShortVal(struct val_map *map, const char *key); + struct val_list *getListVal(struct val_map *map, const char *key); + struct val_map *getMapVal(struct val_map *map, const char *key); + + /*Insert or Update Methods*/ + void putVal(struct val_map *map, const char *key, struct map_val *val); + void putObjectVal(struct val_map *map, const char *key, jobject val); + void putIntVal(struct val_map *map, const char *key, int val); + void putLongVal(struct val_map *map, const char *key, long val); + void putFloatVal(struct val_map *map, const char *key, float val); + void putDoubleVal(struct val_map *map, const char *key, double val); + void putByteVal(struct val_map *map, const char *key, signed char val); + void putStringVal(struct val_map *map, const char *key, const char *val); + void putBoolVal(struct val_map *map, const char *key, bool val); + void putShortVal(struct val_map *map, const char *key, short val); + void putListVal(struct val_map *map, const char *key, struct val_list *val); + void putMapVal(struct val_map *map, const char *key, struct val_map *val); + + jmethodID createMapMethod(); + jmethodID getSizeMethod(); + jmethodID hasKeyMethod(); + jmethodID getValueMethod(); + jmethodID putValueMethod(); private: JNIEnv *jvm; TypeUtils *typeUtils; + ListUtils *listUtils; - jmethodID createListMethodId; - jmethodID getListSizeMethodId; - jmethodID getListItemMethodId; - jmethodID addListItemMethodId; + jmethodID createMapMethodId; + jmethodID getSizeMethodId; + jmethodID hasKeyMethodId; + jmethodID getValueMethodId; + jmethodID putValueMethodId; /* Initialization Methods */ void loadGlobalRefs(JNIEnv *env, TypeUtils *TypeUtils); diff --git a/src/cpp/main/common/MessageApiEndpoint.cpp b/src/cpp/main/common/MessageApiEndpoint.cpp index ed9bfe0..64ea8e1 100644 --- a/src/cpp/main/common/MessageApiEndpoint.cpp +++ b/src/cpp/main/common/MessageApiEndpoint.cpp @@ -19,6 +19,7 @@ MessageApiEndpoint::MessageApiEndpoint(JNIEnv *env, jobject jendpoint, jobject j this->typeUtils = new TypeUtils(this->jvm); this->listUtils = new ListUtils(this->jvm, typeUtils); + this->mapUtils = new MapUtils(this->jvm, typeUtils); this->endpointUtils = new EndpointUtils(this->jvm, this->endpoint, this->typeUtils, this->listUtils); this->protocolRecordUtils = new ProtocolRecordUtils(this->jvm, this->protocolRecord, this->typeUtils, this->listUtils); this->recordUtils = new RecordUtils(this->jvm, this->typeUtils, this->listUtils); @@ -41,6 +42,7 @@ MessageApiEndpoint::~MessageApiEndpoint() delete this->conditionUtils; delete this->packetUtils; delete this->listUtils; + delete this->mapUtils; delete this->typeUtils; this->jvm->DeleteGlobalRef(this->endpoint); this->jvm->DeleteGlobalRef(this->protocolRecord); @@ -91,6 +93,11 @@ ListUtils *MessageApiEndpoint::getListUtils() return this->listUtils; } +MapUtils *MessageApiEndpoint::getMapUtils() +{ + return this->mapUtils; +} + TypeUtils *MessageApiEndpoint::getTypeUtils() { return this->typeUtils; diff --git a/src/cpp/main/common/MessageApiEndpoint.h b/src/cpp/main/common/MessageApiEndpoint.h index 1d248b5..e3a435f 100644 --- a/src/cpp/main/common/MessageApiEndpoint.h +++ b/src/cpp/main/common/MessageApiEndpoint.h @@ -10,6 +10,7 @@ #include #include "JniUtils.h" +#include "MapUtils.h" #include "ListUtils.h" #include "EndpointUtils.h" #include "ProtocolRecordUtils.h" @@ -46,6 +47,7 @@ public: ConditionUtils *getConditionUtils(); PacketUtils *getPacketUtils(); ListUtils *getListUtils(); + MapUtils *getMapUtils(); TypeUtils *getTypeUtils(); private : @@ -63,6 +65,7 @@ private : PacketUtils *packetUtils; TypeUtils *typeUtils; ListUtils *listUtils; + MapUtils *mapUtils; }; diff --git a/src/cpp/main/common/TypeUtils.cpp b/src/cpp/main/common/TypeUtils.cpp index 7617b69..d2596eb 100644 --- a/src/cpp/main/common/TypeUtils.cpp +++ b/src/cpp/main/common/TypeUtils.cpp @@ -10,6 +10,7 @@ TypeUtils::~TypeUtils() { try { + this->jvm->DeleteGlobalRef(this->mapClass); this->jvm->DeleteGlobalRef(this->listClass); this->jvm->DeleteGlobalRef(this->intClass); this->jvm->DeleteGlobalRef(this->longClass); @@ -30,6 +31,7 @@ void TypeUtils::loadGlobalRefs(JNIEnv *env) { this->jvm = env; + this->mapClass = JniUtils::getGlobalClassRef(env, "java/util/HashMap"); this->listClass = JniUtils::getGlobalClassRef(env, "java/util/ArrayList"); this->intClass = JniUtils::getGlobalClassRef(env, "java/lang/Integer"); @@ -206,3 +208,8 @@ jclass TypeUtils::getListClass() { return this->listClass; } + +jclass TypeUtils::getMapClass() +{ + return this->mapClass; +} diff --git a/src/cpp/main/common/TypeUtils.h b/src/cpp/main/common/TypeUtils.h index 5e0dc32..e48f398 100644 --- a/src/cpp/main/common/TypeUtils.h +++ b/src/cpp/main/common/TypeUtils.h @@ -51,6 +51,7 @@ public: jclass getShortClass(); jclass getListClass(); + jclass getMapClass(); jstring toJavaString(const char *charString); const char *fromJavaString(jstring javaString); @@ -71,6 +72,7 @@ private: jclass shortClass; jclass listClass; + jclass mapClass; /*Type Utility Retrieval Methods*/ jmethodID getBoolMethodId; -- GitLab From 854f70133c1a639085949b034162ed4a0e4e2a2b Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 11:37:32 -0400 Subject: [PATCH 07/53] implement BaseTransformation so that getconstructor method makes constructor params from map available. Add getconstructor method to IEndpoint and ITransformation --- .../messageapi/endpoints/BaseEndpoint.java | 10 +++++++ .../noaa/messageapi/interfaces/IEndpoint.java | 8 ++++++ .../interfaces/ITransformation.java | 15 +++++++++++ .../transformations/BaseTransformation.java | 26 +++++++++++++++++++ .../transformations/NativeTransformation.java | 5 +++- .../joins/StringFieldJoin.java | 4 ++- .../reductions/ReduceTransformation.java | 8 ++++-- .../FixRelativePathsTransformation.java | 5 +++- 8 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/java/main/gov/noaa/messageapi/transformations/BaseTransformation.java diff --git a/src/java/main/gov/noaa/messageapi/endpoints/BaseEndpoint.java b/src/java/main/gov/noaa/messageapi/endpoints/BaseEndpoint.java index 0a698f6..0aa415c 100644 --- a/src/java/main/gov/noaa/messageapi/endpoints/BaseEndpoint.java +++ b/src/java/main/gov/noaa/messageapi/endpoints/BaseEndpoint.java @@ -26,10 +26,12 @@ public abstract class BaseEndpoint { public List collectionIds = null; public List> classifierIds = null; public List transformationIds = null; + public Map constructorMap = null; @SuppressWarnings("unchecked") public BaseEndpoint(Map parameters) { Map internalParameters = (Map)parameters.get("__internal__"); + this.setConstructor(parameters); this.setFields((List)internalParameters.get("fields"), this.getDefaultFields()); this.setCollectionIds((List)internalParameters.get("collections")); this.setClassifierIds((List>)internalParameters.get("classifiers")); @@ -38,6 +40,10 @@ public abstract class BaseEndpoint { protected abstract List getDefaultFields(); + public Map getConstructor() { + return this.constructorMap; + } + public IPacket createPacket() { return new DefaultPacket(); } @@ -62,6 +68,10 @@ public abstract class BaseEndpoint { return this.transformationIds; } + private void setConstructor(Map constructorMap) { + this.constructorMap = constructorMap; + } + private List getFields() { return this.fields; } diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IEndpoint.java b/src/java/main/gov/noaa/messageapi/interfaces/IEndpoint.java index 047e2e7..cfe1c8e 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IEndpoint.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IEndpoint.java @@ -1,6 +1,7 @@ package gov.noaa.messageapi.interfaces; import java.util.List; +import java.util.Map; //import gov.noaa.messageapi.interfaces.IPacket; //import gov.noaa.messageapi.interfaces.IProtocolRecord; @@ -38,6 +39,13 @@ public interface IEndpoint { */ public List getDefaultFields(); + /** + * Returns the constructor map attached to the endpoint. The constructor map + * should be used to retrieve constructor parameters. Note that thread safety + * cannot be guaranteed if these parameters are used as read only. + */ + public Map getConstructor(); + /** * Creates a new packet for returning from the endpoint. As all * processing for endpoints must return a packet, all endpoints diff --git a/src/java/main/gov/noaa/messageapi/interfaces/ITransformation.java b/src/java/main/gov/noaa/messageapi/interfaces/ITransformation.java index d1400a0..fb260cc 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/ITransformation.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/ITransformation.java @@ -8,6 +8,21 @@ import java.util.List; */ public interface ITransformation { + /** + * The process method takes in a map of string and record mappings and is + * the main runtime method for the transformation. These mapping + * definitions are contained in the parameter spec. Note that transformations + * are immutable assuming that a getCopy method is provided to any + * custom user types, and this means that individual records may be manipulated + * as desired and returned as needed in the transformation. + */ public List process(Map> transformationMap); + /** + * Returns the constructor map attached to the transformation. The constructor map + * can be used to retrieve constructor parameters. Note that thread safety + * cannot be guaranteed if these parameters are used for anything other than read only. + */ + public Map getConstructor(); + } diff --git a/src/java/main/gov/noaa/messageapi/transformations/BaseTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/BaseTransformation.java new file mode 100644 index 0000000..d495015 --- /dev/null +++ b/src/java/main/gov/noaa/messageapi/transformations/BaseTransformation.java @@ -0,0 +1,26 @@ +package gov.noaa.messageapi.transformations; + +import java.util.Map; + +/** + * The abstract base class for user transformations. This class provides extending user + * endpoints the convenience of parsing and provides all possible generic default methods. + * @author Ryan Berkheimer + */ +public abstract class BaseTransformation { + + public Map constructorMap = null; + + public BaseTransformation(Map parameters) { + this.setConstructor(parameters); + } + + public Map getConstructor() { + return this.constructorMap; + } + + private void setConstructor(Map constructorMap) { + this.constructorMap = constructorMap; + } + +} \ No newline at end of file diff --git a/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java index 7ef0056..5ee3647 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java +++ b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java @@ -6,6 +6,8 @@ import java.util.List; import gov.noaa.messageapi.interfaces.ITransformation; import gov.noaa.messageapi.interfaces.IRecord; +import gov.noaa.messageapi.transformations.BaseTransformation; + /** *

NativeTransformation

This is a wrapper class for transformations that call into * native code held as binary libs through the JNI (Java Native @@ -27,13 +29,14 @@ import gov.noaa.messageapi.interfaces.IRecord; * * @author Ryan Berkheimer */ -public class NativeTransformation implements ITransformation { +public class NativeTransformation extends BaseTransformation implements ITransformation { private native List process(long nativeInstance); private synchronized native long create(Map> recordMap); private synchronized native void release(long instanceId); public NativeTransformation(Map params) { + super(params); this.loadNativeLib((String)params.get("native-library")); } diff --git a/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java b/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java index 2f5d93c..363f563 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java +++ b/src/java/main/gov/noaa/messageapi/transformations/joins/StringFieldJoin.java @@ -11,6 +11,7 @@ import gov.noaa.messageapi.interfaces.ITransformation; import gov.noaa.messageapi.fields.DefaultField; import gov.noaa.messageapi.records.schema.SchemaRecord; +import gov.noaa.messageapi.transformations.BaseTransformation; /** @@ -59,12 +60,13 @@ import gov.noaa.messageapi.records.schema.SchemaRecord; *

* @author Ryan Berkheimer */ -public class StringFieldJoin implements ITransformation { +public class StringFieldJoin extends BaseTransformation implements ITransformation { private IField joinField = null; private IField collectionField = null; public StringFieldJoin(Map params) { + super(params); this.setJoinField((String) params.get("join-field")); this.setCollectionField((String) params.get("collection-field")); } diff --git a/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java index 23e9e88..a45f312 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java +++ b/src/java/main/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.java @@ -6,13 +6,17 @@ import java.util.List; import gov.noaa.messageapi.interfaces.IRecord; import gov.noaa.messageapi.interfaces.ITransformation; +import gov.noaa.messageapi.transformations.BaseTransformation; + /** * @author Ryan Berkheimer */ -public class ReduceTransformation implements ITransformation { +public class ReduceTransformation extends BaseTransformation implements ITransformation { - public ReduceTransformation(Map params) {} + public ReduceTransformation(Map params) { + super(params); + } public List process(Map> transformationMap) { return transformationMap.get("reduce-list"); diff --git a/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java b/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java index 5e0cc67..7803c45 100644 --- a/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java +++ b/src/java/test/gov/noaa/messageapi/test/transformations/FixRelativePathsTransformation.java @@ -10,6 +10,8 @@ import gov.noaa.messageapi.interfaces.ITransformation; import gov.noaa.messageapi.utils.general.ListUtils; import gov.noaa.messageapi.utils.general.PathUtils; +import gov.noaa.messageapi.transformations.BaseTransformation; + /** *

FixRelativePathsTransformation

@@ -25,13 +27,14 @@ import gov.noaa.messageapi.utils.general.PathUtils; * * @author Ryan Berkheimer */ -public class FixRelativePathsTransformation implements ITransformation { +public class FixRelativePathsTransformation extends BaseTransformation implements ITransformation { private List relativePathFields = null; private String transformKey = null; @SuppressWarnings("unchecked") public FixRelativePathsTransformation(Map params) { + super(params); this.setRelativePathFields((List) params.get("fields")); this.setTransformKey((String) params.get("transform-key")); } -- GitLab From 964d788965f24364d53aae883e6321e3014962ce Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 11:41:51 -0400 Subject: [PATCH 08/53] add methods for map item addition/access to the ListUtils class --- src/cpp/main/common/ListUtils.cpp | 14 ++++++++++++++ src/cpp/main/common/ListUtils.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/cpp/main/common/ListUtils.cpp b/src/cpp/main/common/ListUtils.cpp index cf79aa0..06905c8 100644 --- a/src/cpp/main/common/ListUtils.cpp +++ b/src/cpp/main/common/ListUtils.cpp @@ -90,6 +90,14 @@ struct val_list *ListUtils::getListItem(struct val_list *list, int index) return valueList; } +struct val_map *ListUtils::getMapItem(struct val_list *list, int index) +{ + jobject mapItem = this->getObjectItem(list, index); + struct val_map *valMap = (struct val_map *)malloc(sizeof(struct val_map)); + valMap->jmap = mapItem; + return valMap; +} + int ListUtils::getIntItem(struct val_list *list, int index) { jobject list_item = this->getObjectItem(list, index); @@ -236,6 +244,12 @@ void ListUtils::addListItem(struct val_list *list, struct val_list *val) list->count += 1; } +void ListUtils::addMapItem(struct val_list *list, struct val_map *val) +{ + this->jvm->CallVoidMethod(list->jlist, this->addListItemMethod(), val->jmap); + list->count += 1; +} + struct string_list *ListUtils::translateStringList(jobject jList) { int stringCount = this->getListLength(jList); diff --git a/src/cpp/main/common/ListUtils.h b/src/cpp/main/common/ListUtils.h index c04dc7f..6fd62ec 100644 --- a/src/cpp/main/common/ListUtils.h +++ b/src/cpp/main/common/ListUtils.h @@ -43,6 +43,7 @@ public: bool getBoolItem(struct val_list *list, int index); short getShortItem(struct val_list *list, int index); struct val_list *getListItem(struct val_list *list, int index); + struct val_map *getMapItem(struct val_list *list, int index); /*List Item Insertion Methods*/ void addItem(struct val_list *list, struct list_item *item); @@ -56,6 +57,7 @@ public: void addBoolItem(struct val_list *list, bool val); void addShortItem(struct val_list *list, short val); void addListItem(struct val_list *list, struct val_list *val); + void addMapItem(struct val_list *list, struct val_map *map); jmethodID createListMethod(); jmethodID getListSizeMethod(); -- GitLab From 701c8a385cf34616e1ca2fdecf209a6f31ab5669 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 11:50:35 -0400 Subject: [PATCH 09/53] add getConstructor method to EndpointUtils --- src/cpp/main/common/EndpointUtils.cpp | 13 +++++++++++++ src/cpp/main/common/EndpointUtils.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/cpp/main/common/EndpointUtils.cpp b/src/cpp/main/common/EndpointUtils.cpp index 924366a..f408197 100644 --- a/src/cpp/main/common/EndpointUtils.cpp +++ b/src/cpp/main/common/EndpointUtils.cpp @@ -52,6 +52,14 @@ struct field_list *EndpointUtils::getDefaultFields() return field_list; } +struct val_map *EndpointUtils::getConstructor() +{ + jobject jMap = this->jvm->CallObjectMethod(this->endpoint, this->getConstructorMethodId); + struct val_map *map = (struct val_map *)malloc(sizeof(struct val_map)); + map->jmap = jMap; + return map; +} + struct packet *EndpointUtils::createPacket() { jobject jpacket = this->jvm->CallObjectMethod(this->endpoint, this->createPacketMethodId); @@ -93,6 +101,7 @@ void EndpointUtils::loadMethodIds() jclass endpointClass = JniUtils::getObjectClass(this->jvm, this->endpoint); this->getStateContainerMethodId = JniUtils::getMethod(this->jvm, endpointClass, "getStateContainer", this->getMethodSignature("getStateContainer"), false); this->getDefaultFieldsMethodId = JniUtils::getMethod(this->jvm, endpointClass, "getDefaultFields", this->getMethodSignature("getDefaultFields"), false); + this->getConstructorMethodId = JniUtils::getMethod(this->jvm, endpointClass, "getConstructor", this->getMethodSignature("getConstructor"), false); this->createPacketMethodId = JniUtils::getMethod(this->jvm, endpointClass, "createPacket", this->getMethodSignature("createPacket"), false); this->createRecordMethodId = JniUtils::getMethod(this->jvm, endpointClass, "createRecord", this->getMethodSignature("createRecord"), false); this->createRejectionMethodId = JniUtils::getMethod(this->jvm, endpointClass, "createRejection", this->getMethodSignature("createRejection"), false); @@ -109,6 +118,10 @@ const char *EndpointUtils::getMethodSignature(const char *methodName) { return "()Ljava/util/List;"; } + else if (strcmp(methodName, "getConstructor") == 0) + { + return "()Ljava/util/Map;"; + } else if (strcmp(methodName, "createPacket") == 0) { return "()Lgov/noaa/messageapi/interfaces/IPacket;"; diff --git a/src/cpp/main/common/EndpointUtils.h b/src/cpp/main/common/EndpointUtils.h index ed44aa0..4b09f23 100644 --- a/src/cpp/main/common/EndpointUtils.h +++ b/src/cpp/main/common/EndpointUtils.h @@ -36,6 +36,7 @@ public: /*Endpoint Methods*/ struct record *getStateContainer(); struct field_list *getDefaultFields(); + struct val_map *getConstructor(); struct packet *createPacket(); struct record *createRecord(); struct rejection *createRejection(struct record *record, const char *reason); @@ -50,6 +51,7 @@ private: /*Endpoint Methods*/ jmethodID getStateContainerMethodId; jmethodID getDefaultFieldsMethodId; + jmethodID getConstructorMethodId; jmethodID createPacketMethodId; jmethodID createRecordMethodId; jmethodID createRejectionMethodId; -- GitLab From 46072df24b9b718ef63df14f15f5d5eedd96a568 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 12:05:25 -0400 Subject: [PATCH 10/53] completed basic methods for transformation class --- src/cpp/main/common/TransformationUtils.cpp | 22 ++++++++++++++------- src/cpp/main/common/TransformationUtils.h | 10 ++++++++-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/cpp/main/common/TransformationUtils.cpp b/src/cpp/main/common/TransformationUtils.cpp index a8ed67e..392f0d4 100644 --- a/src/cpp/main/common/TransformationUtils.cpp +++ b/src/cpp/main/common/TransformationUtils.cpp @@ -11,9 +11,9 @@ */ /* Default Constructor */ -TransformationUtils::TransformationUtils(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +TransformationUtils::TransformationUtils(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) { - this->loadGlobalRefs(jvm, typeUtils, mapUtils, listUtils); + this->loadGlobalRefs(jvm, transformation, typeUtils, mapUtils, listUtils); this->loadMethodIds(); } @@ -30,12 +30,20 @@ TransformationUtils::~TransformationUtils() /* Public API */ +struct val_map *TransformationUtils::getConstructor() { + jobject jMap = this->jvm->CallObjectMethod(this->transformation, this->getConstructorMethodId); + struct val_map *map = (struct val_map *)malloc(sizeof(struct val_map)); + map->jmap = jMap; + return map; +} + /* Private Methods */ -void TransformationUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +void TransformationUtils::loadGlobalRefs(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) { this->jvm = jvm; + this->transformation = transformation; this->typeUtils = typeUtils; this->mapUtils = mapUtils; this->listUtils = listUtils; @@ -45,16 +53,16 @@ void TransformationUtils::loadMethodIds() { jclass transformationClass = JniUtils::getNamedClass(this->jvm, "gov/noaa/messageapi/interfaces/ITransformation"); - /*this->createRequestMethodId = JniUtils::getMethod(this->jvm, sessionClass, "createRequest", this->getMethodSignature("createRequest"), false);*/ + this->getConstructorMethodId = JniUtils::getMethod(this->jvm, transformationClass, "getConstructor", this->getMethodSignature("getConstructor"), false); jvm->DeleteLocalRef(transformationClass); } const char *TransformationUtils::getMethodSignature(const char *methodName) { - /*if (strcmp(methodName, "createRequest") == 0) + if (strcmp(methodName, "getConstructor") == 0) { - return "()Lgov/noaa/messageapi/interfaces/IRequest;"; - }*/ + return "()Ljava/util/Map;"; + } return NULL; } \ No newline at end of file diff --git a/src/cpp/main/common/TransformationUtils.h b/src/cpp/main/common/TransformationUtils.h index 0dd20d2..bbdb3f8 100644 --- a/src/cpp/main/common/TransformationUtils.h +++ b/src/cpp/main/common/TransformationUtils.h @@ -23,21 +23,27 @@ class TransformationUtils public: /*Default constructor */ - TransformationUtils(JNIEnv *jvm, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + TransformationUtils(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); /*Default Destructor */ ~TransformationUtils(); + /* Transformation API */ + struct val_map *getConstructor(); + private: /*Vars*/ JNIEnv *jvm; + jobject transformation; TypeUtils *typeUtils; MapUtils *mapUtils; ListUtils *listUtils; + jmethodID getConstructorMethodId; + /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ void loadMethodIds(); - void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + void loadGlobalRefs(JNIEnv *env, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); /*Grouped methods for returning the matching method signature string for a given interface*/ const char *getMethodSignature(const char *methodName); -- GitLab From 5c2813c4ce42bebc2f3b0a33c0e7b1c57ed405a4 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 13:59:55 -0400 Subject: [PATCH 11/53] finished adding classes/mesthods for native transformation. ready to build makefile/run test --- .../transformations/TransformationWrapper.c | 20 + ...api_transformations_NativeTransformation.h | 37 ++ src/cpp/main/common/MessageApiEndpointLib.cpp | 153 +++++ src/cpp/main/common/MessageApiEndpointLib.h | 36 ++ .../main/common/MessageApiTransformation.cpp | 100 ++++ .../main/common/MessageApiTransformation.h | 84 +++ .../common/MessageApiTransformationLib.cpp | 532 ++++++++++++++++++ .../main/common/MessageApiTransformationLib.h | 163 ++++++ src/cpp/main/common/TransformationUtils.cpp | 27 +- src/cpp/main/common/TransformationUtils.h | 8 +- 10 files changed, 1150 insertions(+), 10 deletions(-) create mode 100644 src/c/test/transformations/TransformationWrapper.c create mode 100644 src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h create mode 100644 src/cpp/main/common/MessageApiTransformation.cpp create mode 100644 src/cpp/main/common/MessageApiTransformation.h create mode 100644 src/cpp/main/common/MessageApiTransformationLib.cpp create mode 100644 src/cpp/main/common/MessageApiTransformationLib.h diff --git a/src/c/test/transformations/TransformationWrapper.c b/src/c/test/transformations/TransformationWrapper.c new file mode 100644 index 0000000..aa42c7a --- /dev/null +++ b/src/c/test/transformations/TransformationWrapper.c @@ -0,0 +1,20 @@ +#include +#include +#include "messageapi_structs.h" +#include "MessageApiTransformationLib.h" +#include "gov_noaa_messageapi_transformations_NativeTransformation.h" + +/* + * Class: gov_noaa_messageapi_transformations_NativeTransformation + * Method: process + * Signature: (Ljava/lang/Map;)Ljava/lang/List; + * @author Ryan Berkheimer + */ +JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_process(JNIEnv *env, jobject transformation, jlong message) + { + printf("In our transformation test!\n"); + printf("Hello, World\n"); + fflush(stdout); + return; + } + diff --git a/src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h b/src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h new file mode 100644 index 0000000..0b73101 --- /dev/null +++ b/src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h @@ -0,0 +1,37 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class gov_noaa_messageapi_transformations_NativeTransformation */ + +#ifndef _Included_gov_noaa_messageapi_transformations_NativeTransformation +#define _Included_gov_noaa_messageapi_transformations_NativeTransformation +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: gov_noaa_messageapi_transformations_NativeTransformation + * Method: process + * Signature: (J)Ljava/lang/List; + */ +JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_process + (JNIEnv *, jobject, jlong); + +/* + * Class: gov_noaa_messageapi_transformations_NativeTransformation + * Method: create + * Signature: (Ljava/lang/Map;)J + */ +JNIEXPORT jlong JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_create + (JNIEnv *, jobject, jobject); + +/* + * Class: gov_noaa_messageapi_transformations_NativeTransformation + * Method: release + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_release + (JNIEnv *, jobject, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/cpp/main/common/MessageApiEndpointLib.cpp b/src/cpp/main/common/MessageApiEndpointLib.cpp index d684854..22bb3b3 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.cpp +++ b/src/cpp/main/common/MessageApiEndpointLib.cpp @@ -38,6 +38,11 @@ extern "C" return reinterpret_cast(message)->getEndpointUtils()->getDefaultFields(); } + struct val_map *getConstructor(jlong message) + { + return reinterpret_cast(message)->getEndpointUtils()->getConstructor(); + } + struct packet *createPacket(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->createPacket(); @@ -404,6 +409,11 @@ extern "C" return reinterpret_cast(message)->getListUtils()->getListItem(list, index); } + struct val_map *getMapItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getMapItem(list, index); + } + int getIntItem(jlong message, struct val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getIntItem(list, index); @@ -499,6 +509,149 @@ extern "C" return reinterpret_cast(message)->getListUtils()->addListItem(list, val); } + void addMapItem(jlong message, struct val_list *list, struct val_map *val) + { + return reinterpret_cast(message)->getListUtils()->addMapItem(list, val); + } + + /*Map Utility Methods*/ + struct val_map *createMap(jlong message) + { + return reinterpret_cast(message)->getMapUtils()->createMap(); + } + + int getSize(jlong message, struct val_map *map) + { + return reinterpret_cast(message)->getMapUtils()->getSize(map); + } + + bool hasKey(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->hasKey(map, key); + } + + /*Map Value Retrieval Methods*/ + struct map_val *getVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getVal(map, key); + } + + jobject getObjectVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getObjectVal(map, key); + } + + int getIntVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getIntVal(map, key); + } + + long getLongVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getLongVal(map, key); + } + + float getFloatVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getFloatVal(map, key); + } + + double getDoubleVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getDoubleVal(map, key); + } + + signed char getByteVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getByteVal(map, key); + } + + const char *getStringVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getStringVal(map, key); + } + + bool getBoolVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getBoolVal(map, key); + } + + short getShortVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getShortVal(map, key); + } + + struct val_list *getListVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getListVal(map, key); + } + + struct val_map *getMapVal(jlong message, struct val_map *map, const char *key) + { + return reinterpret_cast(message)->getMapUtils()->getMapVal(map, key); + } + + /*Insert or Update Methods*/ + void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val) + { + return reinterpret_cast(message)->getMapUtils()->putVal(map, key, val); + } + + void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val) + { + return reinterpret_cast(message)->getMapUtils()->putObjectVal(map, key, val); + } + + void putIntVal(jlong message, struct val_map *map, const char *key, int val) + { + return reinterpret_cast(message)->getMapUtils()->putIntVal(map, key, val); + } + + void putLongVal(jlong message, struct val_map *map, const char *key, long val) + { + return reinterpret_cast(message)->getMapUtils()->putLongVal(map, key, val); + } + + void putFloatVal(jlong message, struct val_map *map, const char *key, float val) + { + return reinterpret_cast(message)->getMapUtils()->putFloatVal(map, key, val); + } + + void putDoubleVal(jlong message, struct val_map *map, const char *key, double val) + { + return reinterpret_cast(message)->getMapUtils()->putDoubleVal(map, key, val); + } + + void putByteVal(jlong message, struct val_map *map, const char *key, signed char val) + { + return reinterpret_cast(message)->getMapUtils()->putByteVal(map, key, val); + } + + void putStringVal(jlong message, struct val_map *map, const char *key, const char *val) + { + return reinterpret_cast(message)->getMapUtils()->putStringVal(map, key, val); + } + + void putBoolVal(jlong message, struct val_map *map, const char *key, bool val) + { + return reinterpret_cast(message)->getMapUtils()->putBoolVal(map, key, val); + } + + void putShortVal(jlong message, struct val_map *map, const char *key, short val) + { + return reinterpret_cast(message)->getMapUtils()->putShortVal(map, key, val); + } + + void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val) + { + return reinterpret_cast(message)->getMapUtils()->putListVal(map, key, val); + } + + void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val) + { + return reinterpret_cast(message)->getMapUtils()->putMapVal(map, key, val); + } + /*Rejection Utils*/ struct rejection_list *createRejectionList(jlong message) { diff --git a/src/cpp/main/common/MessageApiEndpointLib.h b/src/cpp/main/common/MessageApiEndpointLib.h index f3fb045..7ca79cc 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.h +++ b/src/cpp/main/common/MessageApiEndpointLib.h @@ -11,6 +11,7 @@ extern "C" /*Endpoint Methods*/ struct record *getStateContainer(jlong message); struct field_list *getDefaultFields(jlong message); + struct val_map *getConstructor(jlong message); struct packet *createPacket(jlong message); struct record *createRecord(jlong message); struct rejection *createRejection(jlong message, struct record *record, const char *reason); @@ -112,6 +113,7 @@ extern "C" short getShortItem(jlong message, struct val_list *list, int index); struct list_item *getItem(jlong message, struct val_list *list, int index); struct val_list *getListItem(jlong message, struct val_list *list, int index); + struct val_map *getMapItem(jlong message, struct val_list *list, int index); struct val_list *createList(jlong message); void addItem(jlong message, struct val_list *list, struct list_item *item); void addIntItem(jlong message, struct val_list *list, int val); @@ -123,6 +125,40 @@ extern "C" void addBoolItem(jlong message, struct val_list *list, bool val); void addShortItem(jlong message, struct val_list *list, short val); void addListItem(jlong message, struct val_list *list, struct val_list *val); + void addMapItem(jlong message, struct val_list *list, struct val_map *map); + + /*Map Utility Methods*/ + struct val_map *createMap(jlong message); + int getSize(jlong message, struct val_map *map); + bool hasKey(jlong message, struct val_map *map, const char *key); + + /*Map Value Retrieval Methods*/ + struct map_val *getVal(jlong message, struct val_map *map, const char *key); + jobject getObjectVal(jlong message, struct val_map *map, const char *key); + int getIntVal(jlong message, struct val_map *map, const char *key); + long getLongVal(jlong message, struct val_map *map, const char *key); + float getFloatVal(jlong message, struct val_map *map, const char *key); + double getDoubleVal(jlong message, struct val_map *map, const char *key); + signed char getByteVal(jlong message, struct val_map *map, const char *key); + const char *getStringVal(jlong message, struct val_map *map, const char *key); + bool getBoolVal(jlong message, struct val_map *map, const char *key); + short getShortVal(jlong message, struct val_map *map, const char *key); + struct val_list *getListVal(jlong message, struct val_map *map, const char *key); + struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + + /*Insert or Update Methods*/ + void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); + void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); + void putIntVal(jlong message, struct val_map *map, const char *key, int val); + void putLongVal(jlong message, struct val_map *map, const char *key, long val); + void putFloatVal(jlong message, struct val_map *map, const char *key, float val); + void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); + void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); + void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); + void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); + void putShortVal(jlong message, struct val_map *map, const char *key, short val); + void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); + void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); /*Packet Methods*/ void addPacketRecord(jlong message, struct packet *packet, struct record *record); diff --git a/src/cpp/main/common/MessageApiTransformation.cpp b/src/cpp/main/common/MessageApiTransformation.cpp new file mode 100644 index 0000000..bf0fd35 --- /dev/null +++ b/src/cpp/main/common/MessageApiTransformation.cpp @@ -0,0 +1,100 @@ +#include "MessageApiTransformation.h" + +#include +#include +#include +#include +#include +#include + +/** +Constructor for the MessageApiTransformation object. Takes a JNI environment pointer, a transformation context (this refers to +the transformation class that's instantiating the object), and a transformation record which holds containers of records. +*/ +MessageApiTransformation::MessageApiTransformation(JNIEnv *env, jobject jtransformation, jobject jTransformationMap) +{ + this->jvm = env; + this->transformation = this->jvm->NewGlobalRef(jtransformation); + this->transformationMap = this->jvm->NewGlobalRef(jTransformationMap); + + this->typeUtils = new TypeUtils(this->jvm); + this->listUtils = new ListUtils(this->jvm, typeUtils); + this->mapUtils = new MapUtils(this->jvm, typeUtils); + this->transformationUtils = new TransformationUtils(this->jvm, this->transformation, this->transformationMap, this->typeUtils, this->mapUtils, this->listUtils); + this->recordUtils = new RecordUtils(this->jvm, this->typeUtils, this->listUtils); + this->rejectionUtils = new RejectionUtils(this->jvm, this->typeUtils, this->listUtils); + this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils); + this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils); + this->packetUtils = new PacketUtils(this->jvm, this->listUtils); + +} + +MessageApiTransformation::~MessageApiTransformation() +{ + try + { + delete this->transformationUtils; + delete this->recordUtils; + delete this->rejectionUtils; + delete this->fieldUtils; + delete this->conditionUtils; + delete this->packetUtils; + delete this->listUtils; + delete this->mapUtils; + delete this->typeUtils; + this->jvm->DeleteGlobalRef(this->transformation); + this->jvm->DeleteGlobalRef(this->transformationMap); + } + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +TransformationUtils *MessageApiTransformation::getTransformationUtils() +{ + return this->transformationUtils; +} + +RecordUtils *MessageApiTransformation::getRecordUtils() +{ + return this->recordUtils; +} + +RejectionUtils *MessageApiTransformation::getRejectionUtils() +{ + return this->rejectionUtils; +} + +FieldUtils *MessageApiTransformation::getFieldUtils() +{ + return this->fieldUtils; +} + +ConditionUtils *MessageApiTransformation::getConditionUtils() +{ + return this->conditionUtils; +} + +PacketUtils *MessageApiTransformation::getPacketUtils() +{ + return this->packetUtils; +} + +ListUtils *MessageApiTransformation::getListUtils() +{ + return this->listUtils; +} + +MapUtils *MessageApiTransformation::getMapUtils() +{ + return this->mapUtils; +} + +TypeUtils *MessageApiTransformation::getTypeUtils() +{ + return this->typeUtils; +} + + + diff --git a/src/cpp/main/common/MessageApiTransformation.h b/src/cpp/main/common/MessageApiTransformation.h new file mode 100644 index 0000000..9ccfda8 --- /dev/null +++ b/src/cpp/main/common/MessageApiTransformation.h @@ -0,0 +1,84 @@ +#ifndef _Included_MessageApiTransformation +#define _Included_MessageApiTransformation + +#include +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus +#include +#include + +#include "JniUtils.h" +#include "MapUtils.h" +#include "ListUtils.h" +#include "TransformationUtils.h" +#include "RecordUtils.h" +#include "RejectionUtils.h" +#include "FieldUtils.h" +#include "ConditionUtils.h" +#include "PacketUtils.h" + +/** + * This is the header for the MessageApiTransformation class - this class is the native side facility + * for doing endpoint processing and communicating back with the java side. This class holds + * three private vars - a pointer to the jvm where the call originated from, a pointer to the + * transformation class instance (jobject), and a pointer to the map that holds data for + * this transformation to process as a jobject. + * + * The map contains keys that each hold a list of records. These records are immutable, meaning + * they can be modified however necessary without affecting other transformations or other threads + * within the computation. + * + * To the user of the MessageApiTransformation library in the native side, + * they will see the entire library as a single jlong. This jlong holds a pointer to this class, + * making it easier for implementors to ignore most of the details of implementation. + * @author Ryan Berkheimer + */ +class MessageApiTransformation +{ + +public: + /*Default constructor/destructors*/ + MessageApiTransformation(JNIEnv* javaEnv, jobject jTransformation, jobject jTransformationMap); + ~MessageApiTransformation(); + + /*Utils Accessors*/ + TransformationUtils *getTransformationUtils(); + RecordUtils *getRecordUtils(); + RejectionUtils *getRejectionUtils(); + FieldUtils *getFieldUtils(); + ConditionUtils *getConditionUtils(); + PacketUtils *getPacketUtils(); + ListUtils *getListUtils(); + MapUtils *getMapUtils(); + TypeUtils *getTypeUtils(); + +private : + /*Global References*/ + JNIEnv *jvm; + jobject transformation; + jobject transformationMap; + + TransformationUtils *transformationUtils; + RecordUtils *recordUtils; + RejectionUtils *rejectionUtils; + FieldUtils *fieldUtils; + ConditionUtils *conditionUtils; + PacketUtils *packetUtils; + TypeUtils *typeUtils; + ListUtils *listUtils; + MapUtils *mapUtils; + +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpp/main/common/MessageApiTransformationLib.cpp b/src/cpp/main/common/MessageApiTransformationLib.cpp new file mode 100644 index 0000000..48ed290 --- /dev/null +++ b/src/cpp/main/common/MessageApiTransformationLib.cpp @@ -0,0 +1,532 @@ +#include +#include +#include "MessageApiTransformation.h" +#include "MessageApiTransformationLib.h" +#include "gov_noaa_messageapi_transformations_NativeTransformation.h" + +/** + * Creates a C++ object and returns a pointer to it cast as a long. This allows the NativeEndpoint method + * to hold onto it and manipulate it during the process method while preventing potential conflicts with + * other threads or transformations using the same native library. This is used inside the Java process method. + * The Native process method should be implemented in a separate User class wrapper. + */ +JNIEXPORT jlong JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_create(JNIEnv* env, jobject transformation, jobject transformationMap) +{ + return reinterpret_cast(new MessageApiTransformation(env, transformation, transformationMap)); +} + +/** + * Deletes the C++ pointer (calls C++ destructor)) that references the object created during transformation construction. + * This call is made automatically by the Java process method after native processing has completed. + */ +JNIEXPORT void JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_release(JNIEnv* env, jobject transformation, jlong transformationLib) +{ + delete reinterpret_cast(transformationLib); +} + +extern "C" +{ + + struct val_map *getConstructor(jlong message) + { + return reinterpret_cast(message)->getTransformationUtils()->getConstructor(); + } + + struct record_list *getRecords(jlong message, const char *key) + { + return reinterpret_cast(message)->getTransformationUtils()->getRecords(key); + } + + struct record_list *createRecordList(jlong message) + { + return reinterpret_cast(message)->getRecordUtils()->createRecordList(); + } + + void addRecord(jlong message, struct record_list *record_list, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->addRecord(record_list, record); + } + + struct record *getRecord(jlong message, struct record_list *recordList, int recordIndex) + { + return reinterpret_cast(message)->getRecordUtils()->getRecord(recordList, recordIndex); + } + + struct record *getRecordCopy(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->getCopy(record); + } + + bool getRecordIsValid(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->isValid(record); + } + + struct string_list *getFieldIds(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->getFieldIds(record); + } + + struct field_list *getFields(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->getFields(record); + } + + struct field *getField(jlong message, struct record *record, const char* fieldId) + { + return reinterpret_cast(message)->getRecordUtils()->getField(record, fieldId); + } + + bool hasField(jlong message, struct record *record, const char *fieldId) + { + return reinterpret_cast(message)->getRecordUtils()->hasField(record, fieldId); + } + + struct string_list *getConditionIds(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->getConditionIds(record); + } + + struct condition_list *getConditions(jlong message, struct record *record) + { + return reinterpret_cast(message)->getRecordUtils()->getConditions(record); + } + + struct condition *getCondition(jlong message, struct record *record, const char *conditionId) + { + return reinterpret_cast(message)->getRecordUtils()->getCondition(record, conditionId); + } + + bool hasCondition(jlong message, struct record *record, const char *conditionId) + { + return reinterpret_cast(message)->getRecordUtils()->hasCondition(record, conditionId); + } + + /*Field Methods*/ + + const char *getFieldId(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getId(field); + } + + const char *getFieldType(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getType(field); + } + + bool getFieldIsValid(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->isValid(field); + } + + bool getFieldIsRequired(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->isRequired(field); + } + + bool getFieldIsNull(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->isNull(field); + } + + struct val *getFieldVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getVal(field); + } + + int getFieldIntVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getIntVal(field); + } + + long getFieldLongVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getLongVal(field); + } + + float getFieldFloatVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getFloatVal(field); + } + + double getFieldDoubleVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getDoubleVal(field); + } + + signed char getFieldByteVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getByteVal(field); + } + + const char *getFieldStringVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getStringVal(field); + } + + bool getFieldBoolVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getBoolVal(field); + } + + short getFieldShortVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getShortVal(field); + } + + struct val_list *getFieldListVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getListVal(field); + } + + void setFieldVal(jlong message, struct field *field, struct val *value) + { + return reinterpret_cast(message)->getFieldUtils()->setVal(field, value); + } + + void setFieldIntVal(jlong message, struct field *field, int value) + { + return reinterpret_cast(message)->getFieldUtils()->setIntVal(field, value); + } + + void setFieldLongVal(jlong message, struct field *field, long value) + { + return reinterpret_cast(message)->getFieldUtils()->setLongVal(field, value); + } + + void setFieldFloatVal(jlong message, struct field *field, float value) + { + return reinterpret_cast(message)->getFieldUtils()->setFloatVal(field, value); + } + + void setFieldDoubleVal(jlong message, struct field *field, double value) + { + return reinterpret_cast(message)->getFieldUtils()->setDoubleVal(field, value); + } + + void setFieldByteVal(jlong message, struct field *field, signed char value) + { + return reinterpret_cast(message)->getFieldUtils()->setByteVal(field, value); + } + + void setFieldStringVal(jlong message, struct field *field, const char *value) + { + return reinterpret_cast(message)->getFieldUtils()->setStringVal(field, value); + } + + void setFieldBoolVal(jlong message, struct field *field, bool value) + { + return reinterpret_cast(message)->getFieldUtils()->setBoolVal(field, value); + } + + void setFieldShortVal(jlong message, struct field *field, short value) + { + return reinterpret_cast(message)->getFieldUtils()->setShortVal(field, value); + } + + void setFieldListVal(jlong message, struct field *field, struct val_list *value) + { + return reinterpret_cast(message)->getFieldUtils()->setListVal(field, value); + } + + /*Condition Methods*/ + + const char *getConditionId(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getId(condition); + } + + const char *getConditionType(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getType(condition); + } + + const char *getConditionOperator(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getOperator(condition); + } + + bool getConditionIsNull(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->isNull(condition); + } + + struct val *getConditionVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getVal(condition); + } + + int getConditionIntVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getIntVal(condition); + } + + long getConditionLongVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getLongVal(condition); + } + + float getConditionFloatVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getFloatVal(condition); + } + + double getConditionDoubleVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getDoubleVal(condition); + } + + signed char getConditionByteVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getByteVal(condition); + } + + const char *getConditionStringVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getStringVal(condition); + } + + bool getConditionBoolVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getBoolVal(condition); + } + + short getConditionShortVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getShortVal(condition); + } + + struct val_list *getConditionListVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getListVal(condition); + } + + void setConditionVal(jlong message, struct condition *condition, struct val *value) + { + return reinterpret_cast(message)->getConditionUtils()->setVal(condition, value); + } + + void setConditionIntVal(jlong message, struct condition *condition, int value) + { + return reinterpret_cast(message)->getConditionUtils()->setIntVal(condition, value); + } + + void setConditionLongVal(jlong message, struct condition *condition, long value) + { + return reinterpret_cast(message)->getConditionUtils()->setLongVal(condition, value); + } + + void setConditionFloatVal(jlong message, struct condition *condition, float value) + { + return reinterpret_cast(message)->getConditionUtils()->setFloatVal(condition, value); + } + + void setConditionDoubleVal(jlong message, struct condition *condition, double value) + { + return reinterpret_cast(message)->getConditionUtils()->setDoubleVal(condition, value); + } + + void setConditionByteVal(jlong message, struct condition *condition, signed char value) + { + return reinterpret_cast(message)->getConditionUtils()->setByteVal(condition, value); + } + + void setConditionStringVal(jlong message, struct condition *condition, const char *value) + { + return reinterpret_cast(message)->getConditionUtils()->setStringVal(condition, value); + } + + void setConditionBoolVal(jlong message, struct condition *condition, bool value) + { + return reinterpret_cast(message)->getConditionUtils()->setBoolVal(condition, value); + } + + void setConditionShortVal(jlong message, struct condition *condition, short value) + { + return reinterpret_cast(message)->getConditionUtils()->setShortVal(condition, value); + } + + void setConditionListVal(jlong message, struct condition *condition, struct val_list *value) + { + return reinterpret_cast(message)->getConditionUtils()->setListVal(condition, value); + } + + /*List Utility Methods*/ + + struct list_item *getItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getItem(list, index); + } + + struct val_list *getListItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getListItem(list, index); + } + + int getIntItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getIntItem(list, index); + } + + long getLongItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getLongItem(list, index); + } + + float getFloatItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getFloatItem(list, index); + } + + double getDoubleItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getDoubleItem(list, index); + } + + signed char getByteItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getByteItem(list, index); + } + + const char *getStringItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getStringItem(list, index); + } + + bool getBoolItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getBoolItem(list, index); + } + + short getShortItem(jlong message, struct val_list *list, int index) + { + return reinterpret_cast(message)->getListUtils()->getShortItem(list, index); + } + + struct val_list *createList(jlong message) + { + return reinterpret_cast(message)->getListUtils()->createList(); + } + + void addItem(jlong message, struct val_list *list, struct list_item *item) + { + return reinterpret_cast(message)->getListUtils()->addItem(list, item); + } + + void addIntItem(jlong message, struct val_list *list, int val) + { + return reinterpret_cast(message)->getListUtils()->addIntItem(list, val); + } + + void addLongItem(jlong message, struct val_list *list, long val) + { + return reinterpret_cast(message)->getListUtils()->addLongItem(list, val); + } + + void addFloatItem(jlong message, struct val_list *list, float val) + { + return reinterpret_cast(message)->getListUtils()->addFloatItem(list, val); + } + + void addDoubleItem(jlong message, struct val_list *list, double val) + { + return reinterpret_cast(message)->getListUtils()->addDoubleItem(list, val); + } + + void addByteItem(jlong message, struct val_list *list, signed char val) + { + return reinterpret_cast(message)->getListUtils()->addByteItem(list, val); + } + + void addStringItem(jlong message, struct val_list *list, const char *val) + { + return reinterpret_cast(message)->getListUtils()->addStringItem(list, val); + } + + void addBoolItem(jlong message, struct val_list *list, bool val) + { + return reinterpret_cast(message)->getListUtils()->addBoolItem(list, val); + } + + void addShortItem(jlong message, struct val_list *list, short val) + { + return reinterpret_cast(message)->getListUtils()->addShortItem(list, val); + } + + void addListItem(jlong message, struct val_list *list, struct val_list *val) + { + return reinterpret_cast(message)->getListUtils()->addListItem(list, val); + } + + /*Rejection Utils*/ + struct rejection_list *createRejectionList(jlong message) + { + return reinterpret_cast(message)->getRejectionUtils()->createRejectionList(); + } + + void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection) + { + return reinterpret_cast(message)->getRejectionUtils()->addRejection(rejection_list, rejection); + } + + struct rejection *getRejectionCopy(jlong message, struct rejection *rejection) + { + return reinterpret_cast(message)->getRejectionUtils()->getCopy(rejection); + } + + struct record *getRejectionRecord(jlong message, struct rejection *rejection) + { + return reinterpret_cast(message)->getRejectionUtils()->getRecord(rejection); + } + + struct string_list *getRejectionReasons(jlong message, struct rejection *rejection) + { + return reinterpret_cast(message)->getRejectionUtils()->getReasons(rejection); + } + + void addRejectionReason(jlong message, struct rejection *rejection, const char *reason) + { + return reinterpret_cast(message)->getRejectionUtils()->addReason(rejection, reason); + } + + /*Packet Utils*/ + void addPacketRecord(jlong message, struct packet *packet, struct record *record) + { + return reinterpret_cast(message)->getPacketUtils()->addRecord(packet, record); + } + + void setPacketRecords(jlong message, struct packet *packet, struct record_list *records) + { + return reinterpret_cast(message)->getPacketUtils()->setRecords(packet, records); + } + + void addPacketRecords(jlong message, struct packet *packet, struct record_list *records) + { + return reinterpret_cast(message)->getPacketUtils()->addRecords(packet, records); + } + + void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + { + return reinterpret_cast(message)->getPacketUtils()->setRejections(packet, rejections); + } + + void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection) + { + return reinterpret_cast(message)->getPacketUtils()->addRejection(packet, rejection); + } + + void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + { + return reinterpret_cast(message)->getPacketUtils()->addRejections(packet, rejections); + } + + struct record_list *getPacketRecords(jlong message, struct packet *packet) + { + return reinterpret_cast(message)->getPacketUtils()->getRecords(packet); + } + + struct rejection_list *getPacketRejections(jlong message, struct packet *packet) + { + return reinterpret_cast(message)->getPacketUtils()->getRejections(packet); + } +} \ No newline at end of file diff --git a/src/cpp/main/common/MessageApiTransformationLib.h b/src/cpp/main/common/MessageApiTransformationLib.h new file mode 100644 index 0000000..de26b74 --- /dev/null +++ b/src/cpp/main/common/MessageApiTransformationLib.h @@ -0,0 +1,163 @@ +#include + +/** + * @author Ryan Berkheimer + */ +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Transformation methods */ + struct val_map *getConstructor(jlong message); + struct record_list *getRecords(jlong message, const char *key); + + /*Record Methods*/ + struct record_list *createRecordList(jlong message); + void addRecord(jlong message, struct record_list *record_list, struct record *record); + + struct record *getRecordCopy(jlong message, struct record *record); + bool getRecordIsValid(jlong message, struct record *record); + + struct string_list *getFieldIds(jlong message, struct record *record); + struct field_list *getFields(jlong message, struct record *record); + struct field *getField(jlong message, struct record *record, const char *fieldId); + bool hasField(jlong message, struct record *record, const char *fieldId); + + struct string_list *getConditionIds(jlong message, struct record *record); + struct condition_list *getConditions(jlong message, struct record *record); + struct condition *getCondition(jlong message, struct record *record, const char *conditionId); + bool hasCondition(jlong message, struct record *record, const char *conditionId); + + /*Rejection Methods*/ + struct rejection_list *createRejectionList(jlong message); + void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection); + struct rejection *getRejectionCopy(jlong message, struct rejection *rejection); + struct record *getRejectionRecord(jlong message, struct rejection *rejection); + struct string_list *getRejectionReasons(jlong message, struct rejection *rejection); + void addRejectionReason(jlong message, struct rejection *rejection, const char *reason); + + /*Field Methods*/ + const char *getFieldId(jlong message, struct field *field); + const char *getFieldType(jlong message, struct field *field); + bool getFieldIsValid(jlong message, struct field *field); + bool getFieldIsRequired(jlong message, struct field *field); + bool getFieldIsNull(jlong message, struct field *field); + struct val *getFieldVal(jlong message, struct field *field); + int getFieldIntVal(jlong message, struct field *field); + long getFieldLongVal(jlong message, struct field *field); + float getFieldFloatVal(jlong message, struct field *field); + double getFieldDoubleVal(jlong message, struct field *field); + signed char getFieldByteVal(jlong message, struct field *field); + const char *getFieldStringVal(jlong message, struct field *field); + bool getFieldBoolVal(jlong message, struct field *field); + short getFieldShortVal(jlong message, struct field *field); + struct val_list *getFieldListVal(jlong message, struct field *field); + void setFieldVal(jlong message, struct field *field, struct val *value); + void setFieldIntVal(jlong message, struct field *field, int value); + void setFieldLongVal(jlong message, struct field *field, long value); + void setFieldFloatVal(jlong message, struct field *field, float value); + void setFieldDoubleVal(jlong message, struct field *field, double value); + void setFieldByteVal(jlong message, struct field *field, signed char value); + void setFieldStringVal(jlong message, struct field *field, const char *value); + void setFieldBoolVal(jlong message, struct field *field, bool value); + void setFieldShortVal(jlong message, struct field *field, short value); + void setFieldListVal(jlong message, struct field *field, struct val_list *value); + + /*Condition Methods*/ + const char *getConditionId(jlong message, struct condition *condition); + const char *getConditionType(jlong message, struct condition *condition); + const char *getConditionOperator(jlong message, struct condition *condition); + bool getConditionIsNull(jlong message, struct condition *condition); + struct val *getConditionVal(jlong message, struct condition *condition); + int getConditionIntVal(jlong message, struct condition *condition); + long getConditionLongVal(jlong message, struct condition *condition); + float getConditionFloatVal(jlong message, struct condition *condition); + double getConditionDoubleVal(jlong message, struct condition *condition); + signed char getConditionByteVal(jlong message, struct condition *condition); + const char *getConditionStringVal(jlong message, struct condition *condition); + bool getConditionBoolVal(jlong message, struct condition *condition); + short getConditionShortVal(jlong message, struct condition *condition); + struct val_list *getConditionListVal(jlong message, struct condition *condition); + void setConditionVal(jlong message, struct condition *condition, struct val *value); + void setConditionIntVal(jlong message, struct condition *condition, int value); + void setConditionLongVal(jlong message, struct condition *condition, long value); + void setConditionFloatVal(jlong message, struct condition *condition, float value); + void setConditionDoubleVal(jlong message, struct condition *condition, double value); + void setConditionByteVal(jlong message, struct condition *condition, signed char value); + void setConditionStringVal(jlong message, struct condition *condition, const char *value); + void setConditionBoolVal(jlong message, struct condition *condition, bool value); + void setConditionShortVal(jlong message, struct condition *condition, short value); + void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); + + /*List Utility Methods*/ + int getIntItem(jlong message, struct val_list *list, int index); + long getLongItem(jlong message, struct val_list *list, int index); + float getFloatItem(jlong message, struct val_list *list, int index); + double getDoubleItem(jlong message, struct val_list *list, int index); + signed char getByteItem(jlong message, struct val_list *list, int index); + const char *getStringItem(jlong message, struct val_list *list, int index); + bool getBoolItem(jlong message, struct val_list *list, int index); + short getShortItem(jlong message, struct val_list *list, int index); + struct list_item *getItem(jlong message, struct val_list *list, int index); + struct val_list *getListItem(jlong message, struct val_list *list, int index); + struct val_map *getMapItem(jlong message, struct val_list *list, int index); + struct val_list *createList(jlong message); + void addItem(jlong message, struct val_list *list, struct list_item *item); + void addIntItem(jlong message, struct val_list *list, int val); + void addLongItem(jlong message, struct val_list *list, long val); + void addFloatItem(jlong message, struct val_list *list, float val); + void addDoubleItem(jlong message, struct val_list *list, double val); + void addByteItem(jlong message, struct val_list *list, signed char val); + void addStringItem(jlong message, struct val_list *list, const char *val); + void addBoolItem(jlong message, struct val_list *list, bool val); + void addShortItem(jlong message, struct val_list *list, short val); + void addListItem(jlong message, struct val_list *list, struct val_list *val); + void addMapItem(jlong message, struct val_list *list, struct val_map *map); + + /*Map Utility Methods*/ + struct val_map *createMap(jlong message); + int getSize(jlong message, struct val_map *map); + bool hasKey(jlong message, struct val_map *map, const char *key); + + /*Map Value Retrieval Methods*/ + struct map_val *getVal(jlong message, struct val_map *map, const char *key); + jobject getObjectVal(jlong message, struct val_map *map, const char *key); + int getIntVal(jlong message, struct val_map *map, const char *key); + long getLongVal(jlong message, struct val_map *map, const char *key); + float getFloatVal(jlong message, struct val_map *map, const char *key); + double getDoubleVal(jlong message, struct val_map *map, const char *key); + signed char getByteVal(jlong message, struct val_map *map, const char *key); + const char *getStringVal(jlong message, struct val_map *map, const char *key); + bool getBoolVal(jlong message, struct val_map *map, const char *key); + short getShortVal(jlong message, struct val_map *map, const char *key); + struct val_list *getListVal(jlong message, struct val_map *map, const char *key); + struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + + /*Insert or Update Methods*/ + void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); + void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); + void putIntVal(jlong message, struct val_map *map, const char *key, int val); + void putLongVal(jlong message, struct val_map *map, const char *key, long val); + void putFloatVal(jlong message, struct val_map *map, const char *key, float val); + void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); + void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); + void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); + void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); + void putShortVal(jlong message, struct val_map *map, const char *key, short val); + void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); + void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); + + /*Packet Methods*/ + void addPacketRecord(jlong message, struct packet *packet, struct record *record); + void setPacketRecords(jlong message, struct packet *packet, struct record_list *records); + void addPacketRecords(jlong message, struct packet *packet, struct record_list *records); + void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); + void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection); + void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); + struct record_list *getPacketRecords(jlong message, struct packet *packet); + struct rejection_list *getPacketRejections(jlong message, struct packet *packet); + +#ifdef __cplusplus +} +#endif diff --git a/src/cpp/main/common/TransformationUtils.cpp b/src/cpp/main/common/TransformationUtils.cpp index 392f0d4..755e83f 100644 --- a/src/cpp/main/common/TransformationUtils.cpp +++ b/src/cpp/main/common/TransformationUtils.cpp @@ -3,17 +3,13 @@ #include /** - * Sessions are the top level API container of any given computation. Sessions - * bootstrap from a specification map and 'lock-in' a computation environment, - * allowing requests to be created. - * * @author Ryan Berkheimer */ /* Default Constructor */ -TransformationUtils::TransformationUtils(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +TransformationUtils::TransformationUtils(JNIEnv *jvm, jobject transformation, jobject transformationMap, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) { - this->loadGlobalRefs(jvm, transformation, typeUtils, mapUtils, listUtils); + this->loadGlobalRefs(jvm, transformation, transformationMap, typeUtils, mapUtils, listUtils); this->loadMethodIds(); } @@ -30,23 +26,38 @@ TransformationUtils::~TransformationUtils() /* Public API */ -struct val_map *TransformationUtils::getConstructor() { +struct val_map *TransformationUtils::getConstructor() +{ jobject jMap = this->jvm->CallObjectMethod(this->transformation, this->getConstructorMethodId); struct val_map *map = (struct val_map *)malloc(sizeof(struct val_map)); map->jmap = jMap; return map; } +struct record_list *TransformationUtils::getRecords(const char *key) +{ + jobject jList = this->mapUtils->getObjectVal(this->tMap, key); + int count = this->listUtils->getListLength(jList); + struct record_list *records = (struct record_list *)malloc(sizeof(struct record_list)); + records->count = count; + records->jrecords = jList; + return records; +} /* Private Methods */ -void TransformationUtils::loadGlobalRefs(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) +void TransformationUtils::loadGlobalRefs(JNIEnv *jvm, jobject transformation, jobject transformationMap, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils) { this->jvm = jvm; this->transformation = transformation; + this->transformationMap = transformationMap; this->typeUtils = typeUtils; this->mapUtils = mapUtils; this->listUtils = listUtils; + + struct val_map *map = (struct val_map *)malloc(sizeof(struct val_map)); + map->jmap = transformationMap; + this->tMap = map; } void TransformationUtils::loadMethodIds() diff --git a/src/cpp/main/common/TransformationUtils.h b/src/cpp/main/common/TransformationUtils.h index bbdb3f8..03e3599 100644 --- a/src/cpp/main/common/TransformationUtils.h +++ b/src/cpp/main/common/TransformationUtils.h @@ -23,27 +23,31 @@ class TransformationUtils public: /*Default constructor */ - TransformationUtils(JNIEnv *jvm, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + TransformationUtils(JNIEnv *jvm, jobject transformation, jobject transformationMap, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); /*Default Destructor */ ~TransformationUtils(); /* Transformation API */ struct val_map *getConstructor(); + struct record_list *getRecords(const char *key); private: /*Vars*/ JNIEnv *jvm; jobject transformation; + jobject transformationMap; TypeUtils *typeUtils; MapUtils *mapUtils; ListUtils *listUtils; + struct val_map *tMap; + jmethodID getConstructorMethodId; /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ void loadMethodIds(); - void loadGlobalRefs(JNIEnv *env, jobject transformation, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); + void loadGlobalRefs(JNIEnv *env, jobject transformation, jobject transformationMap, TypeUtils *typeUtils, MapUtils *mapUtils, ListUtils *listUtils); /*Grouped methods for returning the matching method signature string for a given interface*/ const char *getMethodSignature(const char *methodName); -- GitLab From f036e933babed9685126a6f8719149a635bc182e Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 31 May 2020 15:01:35 -0400 Subject: [PATCH 12/53] bugfixes in MapUtils, tests working in Endpoint as before. Added Transformation Demo Makefile and build succeeds --- .../demotransformationlibrary/.gitignore | 0 scripts/test/jni/demoendpointlibrary/Makefile | 2 +- .../jni/demotransformationlibrary/Makefile | 152 ++++++++++++++++++ .../TransformationWrapper.c | 2 +- ...api_transformations_NativeTransformation.h | 4 +- src/cpp/main/common/MapUtils.cpp | 2 +- 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 lib/test/native/demotransformationlibrary/.gitignore create mode 100644 scripts/test/jni/demotransformationlibrary/Makefile rename src/c/test/transformations/{ => demotransformationlibrary}/TransformationWrapper.c (91%) rename src/c/test/transformations/{ => demotransformationlibrary}/gov_noaa_messageapi_transformations_NativeTransformation.h (94%) diff --git a/lib/test/native/demotransformationlibrary/.gitignore b/lib/test/native/demotransformationlibrary/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/scripts/test/jni/demoendpointlibrary/Makefile b/scripts/test/jni/demoendpointlibrary/Makefile index a3bada2..e00161c 100644 --- a/scripts/test/jni/demoendpointlibrary/Makefile +++ b/scripts/test/jni/demoendpointlibrary/Makefile @@ -63,7 +63,7 @@ FF=gfortran #The following vars contain strings representing common libraries used by all code #at a project level. These should generally not be touched by users. COMMONC= -COMMONCPP=JniUtils.cpp TypeUtils.cpp ListUtils.cpp ConditionUtils.cpp FieldUtils.cpp \ +COMMONCPP=JniUtils.cpp TypeUtils.cpp MapUtils.cpp ListUtils.cpp ConditionUtils.cpp FieldUtils.cpp \ EndpointUtils.cpp ProtocolRecordUtils.cpp RecordUtils.cpp RejectionUtils.cpp PacketUtils.cpp \ MessageApiEndpoint.cpp MessageApiEndpointLib.cpp COMMONFORTRAN= diff --git a/scripts/test/jni/demotransformationlibrary/Makefile b/scripts/test/jni/demotransformationlibrary/Makefile new file mode 100644 index 0000000..1fd7108 --- /dev/null +++ b/scripts/test/jni/demotransformationlibrary/Makefile @@ -0,0 +1,152 @@ +### This is a Makefile for MessageAPI Native Endpoints. +# The majority of this Makefile is standard, with very few user specified things. +# There are a few specific requirements and other notable things to keep in mind when using this Makefile: +## 1. You must have a JDK installed (not JRE). This library requires the jni.h header included in your jdk. +## 2. JAVA_HOME must be set to your JDK home directory. This Makefile references JAVA_HOME in looking for jni.h +## 3. This Makefile assumes a specific project layout when setting the PROJECTPATH. If the Makefile is not working, +## you should look at how it uses PROJECTPATH, ENDPOINT_NAME, and ENDPOINT_TYPE to find required files. +## if your project is set up differently, i.e. custom project layout, then path dependent vars will need to be +## looked at and possibly changed. + +#The following represents the root project path. DO NOT EDIT +SCRIPTDIR=$(PWD) +PROJECTPATH=$(firstword $(subst /scripts/$(ENDPOINT_TYPE)/, ,$(SCRIPTDIR))) + +#The following is used to determine how native resources are compiled. DO NOT EDIT. +UNAME := $(shell uname) + +###################################################### USER SPECIFIED SECTION - PLEASE EDIT ########################### +#USER SPECIFIED +#The following vars are used to route source code and scripts (from the scripts and src dirs) +#to the library dir as compiled files (the job name should match the name of the directory/job map.) +#the job type is simply a test job or a main job and should either be test or main. +ENDPOINT_NAME=demotransformationlibrary +ENDPOINT_TYPE=test + +#USER SPECIFIED +#The following var represents the output name of the JniLib that will be created and referenced in the job map. +#Do not specify the extension (.so/.dll/.jnilib) - these are determined automatically on build. +#The full path to the created library must be referenced in the endpoint config. +LIBNAME=DemoTransformationLibrary + +#USER SPECIFIED +#The following vars should contain strings representing the C, Fortran, and CPP libraries that glue the fortran code to java code. +#These strings should contain the user libraries in the order they need to be compiled (ex, "First.c Second.c Third.c") +#These vars do not need to specify libraries they depend on that are found in the common variables (those are automatically compiled first). +USERC=TransformationWrapper.c +USERCPP= +USERFORTRAN= + +###################################################### END USER SPECIFIED SECTION ########################### + +#The following represent directories for JNI Libraries that must be included during C and CPP compilation. +#These are platform dependent. If you have a default setup, these probably will not have to be modified. +#However, if you have nonstandard include paths, or you are getting errors, this may need to be altered. +ifeq ($(UNAME), Linux) +#The following represent a standard RHEL 7 system. +JNIDIR="$(JAVA_HOME)/include" +JNIMDDIR="$(JAVA_HOME)/include/linux" +JVMHEADERS="$(JAVA_HOME)/include/linux" +endif +ifeq ($(UNAME), Darwin) +#The following represent a standard OSX system. +JNIDIR="$(JAVA_HOME)/include" +JNIMDDIR="$(JAVA_HOME)/include/darwin" +JVMHEADERS="$(JAVA_HOME)/include" +endif + +#compilers +CXX=g++ +CC=gcc +FF=gfortran + +#The following vars contain strings representing common libraries used by all code +#at a project level. These should generally not be touched by users. +COMMONC= +COMMONCPP=JniUtils.cpp TypeUtils.cpp ListUtils.cpp MapUtils.cpp ConditionUtils.cpp FieldUtils.cpp \ +TransformationUtils.cpp RecordUtils.cpp RejectionUtils.cpp PacketUtils.cpp \ +MessageApiTransformation.cpp MessageApiTransformationLib.cpp +COMMONFORTRAN= +JAVACLASSES:=$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java +JAVAPATH=$(PROJECTPATH)/src/java/main:$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/transformations + + +#The following contains source code paths derived from the ENDPOINT_NAME and ENDPOINT_TYPE supplied by the user. +COMMONCPATH=$(PROJECTPATH)/src/c/main/common/structs/ +USERCPATH=$(PROJECTPATH)/src/c/$(ENDPOINT_TYPE)/transformations/$(ENDPOINT_NAME)/ +COMMONCPPPATH=$(PROJECTPATH)/src/cpp/main/common/ +USERCPPPATH=$(PROJECTPATH)/src/cpp/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ +COMMONFORTRANPATH=$(PROJECTPATH)/src/fortran/main/common/ +USERFORTRANPATH=$(PROJECTPATH)/src/fortran/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ + +#The following var contains the target path for the project code. +TARGETPATH="$(PROJECTPATH)/lib/$(ENDPOINT_TYPE)/native/$(ENDPOINT_NAME)/" + +#The following is the target library for the native jni library. +ifeq ($(UNAME), Linux) +#The following represents a standard RHEL 7 system. +LNFLAGS=-dynamiclib -shared -lgfortran -I$(JVMHEADERS) +endif +ifeq ($(UNAME), Darwin) +#The following represents a standard OSX system. +LNFLAGS=-dynamiclib -shared -lgfortran -I$(JVMHEADERS) -framework JavaVM +endif + +CFLAGS=-I$(JVMHEADERS) -I$(COMMONCPPPATH) -I$(COMMONCPATH) -I$(USERCPPPATH) -I$(USERCPATH) -I$(JNIDIR) -I$(JNIMDDIR) -fpic -std=c99 +FFLAGS=-I$(COMMONFORTRANPATH) -I$(USERFORTRANPATH) -fPIC -fopenmp + +#The following is the target library for the native jni library. +ifeq ($(UNAME), Linux) +#The following represents a standard RHEL 7 system. +DYLIB=lib$(LIBNAME).so +endif +ifeq ($(UNAME), Darwin) +#The following represents a standard OSX system. +DYLIB=lib$(LIBNAME).jnilib +endif + +#COMMONFORTRAN1=$(addprefix $(COMMONFORTRANPATH), $(COMMONFORTRAN)) +#USERFORTRAN1=$(addprefix $(USERFORTRANPATH), $(USERFORTRAN)) +COMMONC1=$(addprefix $(COMMONCPATH), $(COMMONC)) +USERC1=$(addprefix $(USERCPATH), $(USERC)) +COMMONCPP1=$(addprefix $(COMMONCPPPATH), $(COMMONCPP)) +USERCPP1=$(addprefix $(USERCPPPATH), $(USERCPP)) + +all: clean gen-headers build + +.PHONY : clean gen-headers build + +gen-headers: + echo "Generating headers. " + echo "" + $(foreach header,$(JAVACLASSES),javac -h $(USERCPATH) -classpath $(JAVAPATH) $(header);) + echo "" + +build: + echo "Building " $(ENDPOINT_NAME) " in " $(PROJECTPATH) + #echo "Compiling Fortran" + #echo "" + #cd $(TARGETPATH) && $(FF) $(FFLAGS) -c $(COMMONFORTRAN1) $(USERFORTRAN1) + #echo "" + echo "Compiling CPP" + echo "" + cd $(TARGETPATH) && $(CXX) $(CFLAGS) -c $(COMMONCPP1) $(USERCPP1) + echo "" + echo "Compiling C" + echo "" + cd $(TARGETPATH) && $(CC) $(CFLAGS) -c $(COMMONC1) $(USERC1) + echo "" + echo "Creating JNI Library" + echo "" + cd $(TARGETPATH) && $(CXX) $(LNFLAGS) *.o -o $(DYLIB) + echo "Build success for " $(ENDPOINT_NAME) + +clean: + echo "Cleaning up." + echo "" + -cd $(TARGETPATH) && rm *.h + -cd $(TARGETPATH) && rm *.o + -cd $(TARGETPATH) && rm *.mod + -cd $(TARGETPATH) && rm *.jnilib + -cd $(TARGETPATH) && rm *.so + echo "" diff --git a/src/c/test/transformations/TransformationWrapper.c b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c similarity index 91% rename from src/c/test/transformations/TransformationWrapper.c rename to src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c index aa42c7a..4a7e457 100644 --- a/src/c/test/transformations/TransformationWrapper.c +++ b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c @@ -15,6 +15,6 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransfo printf("In our transformation test!\n"); printf("Hello, World\n"); fflush(stdout); - return; + return getRecords(message, "test_key")->jrecords; } diff --git a/src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h b/src/c/test/transformations/demotransformationlibrary/gov_noaa_messageapi_transformations_NativeTransformation.h similarity index 94% rename from src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h rename to src/c/test/transformations/demotransformationlibrary/gov_noaa_messageapi_transformations_NativeTransformation.h index 0b73101..f4294a2 100644 --- a/src/c/test/transformations/gov_noaa_messageapi_transformations_NativeTransformation.h +++ b/src/c/test/transformations/demotransformationlibrary/gov_noaa_messageapi_transformations_NativeTransformation.h @@ -10,7 +10,7 @@ extern "C" { /* * Class: gov_noaa_messageapi_transformations_NativeTransformation * Method: process - * Signature: (J)Ljava/lang/List; + * Signature: (J)Ljava/util/List; */ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_process (JNIEnv *, jobject, jlong); @@ -18,7 +18,7 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransfo /* * Class: gov_noaa_messageapi_transformations_NativeTransformation * Method: create - * Signature: (Ljava/lang/Map;)J + * Signature: (Ljava/util/Map;)J */ JNIEXPORT jlong JNICALL Java_gov_noaa_messageapi_transformations_NativeTransformation_create (JNIEnv *, jobject, jobject); diff --git a/src/cpp/main/common/MapUtils.cpp b/src/cpp/main/common/MapUtils.cpp index 99d9f8b..bec29e2 100644 --- a/src/cpp/main/common/MapUtils.cpp +++ b/src/cpp/main/common/MapUtils.cpp @@ -32,7 +32,7 @@ void MapUtils::loadMethodIds() this->getSizeMethodId = this->jvm->GetMethodID(mapClass, "size", "()I"); this->hasKeyMethodId = this->jvm->GetMethodID(mapClass, "containsKey", "(Ljava/lang/Object;)Z"); this->getValueMethodId = this->jvm->GetMethodID(mapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); - this->putValueMethodId = this->jvm->GetMethodID(mapClass, "put", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;"); + this->putValueMethodId = this->jvm->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); this->jvm->DeleteLocalRef(mapClass); -- GitLab From efac8d601c433b3524db717f22a946bdbf0132ef Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Mon, 1 Jun 2020 11:39:14 -0400 Subject: [PATCH 13/53] added successful test for native transformation --- resources/test/file-reader/manifest.json | 3 +- .../test/native-transformation/manifest.json | 27 ++++++++++ .../native-transformation/parameters.json | 38 ++++++++++++++ .../jni/demotransformationlibrary/Makefile | 26 +++++----- .../TransformationWrapper.c | 5 +- .../main/common/MessageApiTransformation.h | 2 +- .../common/MessageApiTransformationLib.cpp | 2 +- .../MessageApiTransformation.cpp | 0 .../transformation/MessageApiTransformation.h | 0 .../MessageApiTransformationLib.cpp | 0 .../MessageApiTransformationLib.h | 0 .../endtoend/NativeTransformationTests.groovy | 49 +++++++++++++++++++ .../endpoints/EvaluationEndpoint.java | 3 +- 13 files changed, 136 insertions(+), 19 deletions(-) create mode 100644 resources/test/native-transformation/manifest.json create mode 100644 resources/test/native-transformation/parameters.json delete mode 100644 src/cpp/main/common/transformation/MessageApiTransformation.cpp delete mode 100644 src/cpp/main/common/transformation/MessageApiTransformation.h delete mode 100644 src/cpp/main/common/transformation/MessageApiTransformationLib.cpp delete mode 100644 src/cpp/main/common/transformation/MessageApiTransformationLib.h create mode 100644 src/groovy/test/endtoend/NativeTransformationTests.groovy diff --git a/resources/test/file-reader/manifest.json b/resources/test/file-reader/manifest.json index 66a710f..c834247 100644 --- a/resources/test/file-reader/manifest.json +++ b/resources/test/file-reader/manifest.json @@ -18,8 +18,7 @@ "metadata": "{}/resources/test/metadata/file-reader/container.json", "collections": "{}/resources/test/file-reader/parameters.json", "transformations": { - "map": "{}/resources/test/file-reader/parameters.json", - "factory": "gov.noaa.messageapi.test.factories.transformations.FileReaderFactory" + "map": "{}/resources/test/file-reader/parameters.json" } } }, diff --git a/resources/test/native-transformation/manifest.json b/resources/test/native-transformation/manifest.json new file mode 100644 index 0000000..3d86b46 --- /dev/null +++ b/resources/test/native-transformation/manifest.json @@ -0,0 +1,27 @@ +{ + "plugin": "gov.noaa.messageapi.sessions.DefaultSession", + "constructor": { + "schema": { + "plugin": "gov.noaa.messageapi.schemas.DefaultSchema", + "constructor": { + "fields": "{}/resources/test/native-transformation/parameters.json" + } + }, + "container": { + "plugin": "gov.noaa.messageapi.containers.DefaultContainer", + "constructor": { + "collections": "{}/resources/test/native-transformation/parameters.json", + "transformations": {"map": "{}/resources/test/native-transformation/parameters.json"} + } + }, + "protocol": { + "plugin": "gov.noaa.messageapi.protocols.DefaultProtocol", + "constructor": { + "endpoints": [{ + "plugin": "gov.noaa.messageapi.endpoints.EvaluationEndpoint", + "connections": "{}/resources/test/native-transformation/parameters.json" + }] + } + } + } +} \ No newline at end of file diff --git a/resources/test/native-transformation/parameters.json b/resources/test/native-transformation/parameters.json new file mode 100644 index 0000000..5b2f276 --- /dev/null +++ b/resources/test/native-transformation/parameters.json @@ -0,0 +1,38 @@ +{ + "fields": [ + { + "id": "initial-value", + "type": "integer", + "required": true + }, + { + "id": "string-test", + "type": "string", + "required": false + }, + { + "id": "null-test", + "type": "string", + "required": false + }, + { + "id": "int-list-test", + "type": "list(int)", + "required": true, + "value": [0,1,2,3,4,5,6] + }], + "collections": [{"id": "collection-1", + "fields": ["initial-value", "string-test", "int-list-test", "null-test"]}], + "transformations": [ + { + "id": "transform-1", + "operator": "gov.noaa.messageapi.transformations.NativeTransformation", + "constructor": { + "native-library": "/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/lib/test/native/demotransformationlibrary/libDemoTransformationLibrary.jnilib" + }, + "records": {"test_key": {"COLLECTION": "collection-1"}}} + ], + "connections": [{"id": "connection-1", + "transformations": ["transform-1"], + "constructor": {}}] +} diff --git a/scripts/test/jni/demotransformationlibrary/Makefile b/scripts/test/jni/demotransformationlibrary/Makefile index 1fd7108..89c2c91 100644 --- a/scripts/test/jni/demotransformationlibrary/Makefile +++ b/scripts/test/jni/demotransformationlibrary/Makefile @@ -1,16 +1,16 @@ -### This is a Makefile for MessageAPI Native Endpoints. +### This is a Makefile for MessageAPI Native Transformations. # The majority of this Makefile is standard, with very few user specified things. # There are a few specific requirements and other notable things to keep in mind when using this Makefile: ## 1. You must have a JDK installed (not JRE). This library requires the jni.h header included in your jdk. ## 2. JAVA_HOME must be set to your JDK home directory. This Makefile references JAVA_HOME in looking for jni.h ## 3. This Makefile assumes a specific project layout when setting the PROJECTPATH. If the Makefile is not working, -## you should look at how it uses PROJECTPATH, ENDPOINT_NAME, and ENDPOINT_TYPE to find required files. +## you should look at how it uses PROJECTPATH, TRANSFORMATION_NAME, and TRANSFORMATION_TYPE to find required files. ## if your project is set up differently, i.e. custom project layout, then path dependent vars will need to be ## looked at and possibly changed. #The following represents the root project path. DO NOT EDIT SCRIPTDIR=$(PWD) -PROJECTPATH=$(firstword $(subst /scripts/$(ENDPOINT_TYPE)/, ,$(SCRIPTDIR))) +PROJECTPATH=$(firstword $(subst /scripts/$(TRANSFORMATION_TYPE)/, ,$(SCRIPTDIR))) #The following is used to determine how native resources are compiled. DO NOT EDIT. UNAME := $(shell uname) @@ -20,13 +20,13 @@ UNAME := $(shell uname) #The following vars are used to route source code and scripts (from the scripts and src dirs) #to the library dir as compiled files (the job name should match the name of the directory/job map.) #the job type is simply a test job or a main job and should either be test or main. -ENDPOINT_NAME=demotransformationlibrary -ENDPOINT_TYPE=test +TRANSFORMATION_NAME=demotransformationlibrary +TRANSFORMATION_TYPE=test #USER SPECIFIED #The following var represents the output name of the JniLib that will be created and referenced in the job map. #Do not specify the extension (.so/.dll/.jnilib) - these are determined automatically on build. -#The full path to the created library must be referenced in the endpoint config. +#The full path to the created library must be referenced in the transformation config. LIBNAME=DemoTransformationLibrary #USER SPECIFIED @@ -71,16 +71,16 @@ JAVACLASSES:=$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/transformations/Na JAVAPATH=$(PROJECTPATH)/src/java/main:$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/transformations -#The following contains source code paths derived from the ENDPOINT_NAME and ENDPOINT_TYPE supplied by the user. +#The following contains source code paths derived from the TRANSFORMATION_NAME and TRANSFORMATION_TYPE supplied by the user. COMMONCPATH=$(PROJECTPATH)/src/c/main/common/structs/ -USERCPATH=$(PROJECTPATH)/src/c/$(ENDPOINT_TYPE)/transformations/$(ENDPOINT_NAME)/ +USERCPATH=$(PROJECTPATH)/src/c/$(TRANSFORMATION_TYPE)/transformations/$(TRANSFORMATION_NAME)/ COMMONCPPPATH=$(PROJECTPATH)/src/cpp/main/common/ -USERCPPPATH=$(PROJECTPATH)/src/cpp/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ +USERCPPPATH=$(PROJECTPATH)/src/cpp/$(TRANSFORMATION_TYPE)/$(TRANSFORMATION_NAME)/ COMMONFORTRANPATH=$(PROJECTPATH)/src/fortran/main/common/ -USERFORTRANPATH=$(PROJECTPATH)/src/fortran/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ +USERFORTRANPATH=$(PROJECTPATH)/src/fortran/$(TRANSFORMATION_TYPE)/$(TRANSFORMATION_NAME)/ #The following var contains the target path for the project code. -TARGETPATH="$(PROJECTPATH)/lib/$(ENDPOINT_TYPE)/native/$(ENDPOINT_NAME)/" +TARGETPATH="$(PROJECTPATH)/lib/$(TRANSFORMATION_TYPE)/native/$(TRANSFORMATION_NAME)/" #The following is the target library for the native jni library. ifeq ($(UNAME), Linux) @@ -123,7 +123,7 @@ gen-headers: echo "" build: - echo "Building " $(ENDPOINT_NAME) " in " $(PROJECTPATH) + echo "Building " $(TRANSFORMATION_NAME) " in " $(PROJECTPATH) #echo "Compiling Fortran" #echo "" #cd $(TARGETPATH) && $(FF) $(FFLAGS) -c $(COMMONFORTRAN1) $(USERFORTRAN1) @@ -139,7 +139,7 @@ build: echo "Creating JNI Library" echo "" cd $(TARGETPATH) && $(CXX) $(LNFLAGS) *.o -o $(DYLIB) - echo "Build success for " $(ENDPOINT_NAME) + echo "Build success for " $(TRANSFORMATION_NAME) clean: echo "Cleaning up." diff --git a/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c index 4a7e457..235f2d1 100644 --- a/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c +++ b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c @@ -15,6 +15,9 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransfo printf("In our transformation test!\n"); printf("Hello, World\n"); fflush(stdout); - return getRecords(message, "test_key")->jrecords; + struct record_list *records = getRecords(message, "test_key"); + printf("Record count: %d\n", records->count); + fflush(stdout); + return records->jrecords; } diff --git a/src/cpp/main/common/MessageApiTransformation.h b/src/cpp/main/common/MessageApiTransformation.h index 9ccfda8..dc1a0ea 100644 --- a/src/cpp/main/common/MessageApiTransformation.h +++ b/src/cpp/main/common/MessageApiTransformation.h @@ -21,7 +21,7 @@ /** * This is the header for the MessageApiTransformation class - this class is the native side facility - * for doing endpoint processing and communicating back with the java side. This class holds + * for doing transformation processing and communicating back with the java side. This class holds * three private vars - a pointer to the jvm where the call originated from, a pointer to the * transformation class instance (jobject), and a pointer to the map that holds data for * this transformation to process as a jobject. diff --git a/src/cpp/main/common/MessageApiTransformationLib.cpp b/src/cpp/main/common/MessageApiTransformationLib.cpp index 48ed290..1d62353 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.cpp +++ b/src/cpp/main/common/MessageApiTransformationLib.cpp @@ -5,7 +5,7 @@ #include "gov_noaa_messageapi_transformations_NativeTransformation.h" /** - * Creates a C++ object and returns a pointer to it cast as a long. This allows the NativeEndpoint method + * Creates a C++ object and returns a pointer to it cast as a long. This allows the NativeTransformation method * to hold onto it and manipulate it during the process method while preventing potential conflicts with * other threads or transformations using the same native library. This is used inside the Java process method. * The Native process method should be implemented in a separate User class wrapper. diff --git a/src/cpp/main/common/transformation/MessageApiTransformation.cpp b/src/cpp/main/common/transformation/MessageApiTransformation.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/transformation/MessageApiTransformation.h b/src/cpp/main/common/transformation/MessageApiTransformation.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/transformation/MessageApiTransformationLib.cpp b/src/cpp/main/common/transformation/MessageApiTransformationLib.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/transformation/MessageApiTransformationLib.h b/src/cpp/main/common/transformation/MessageApiTransformationLib.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/groovy/test/endtoend/NativeTransformationTests.groovy b/src/groovy/test/endtoend/NativeTransformationTests.groovy new file mode 100644 index 0000000..263d794 --- /dev/null +++ b/src/groovy/test/endtoend/NativeTransformationTests.groovy @@ -0,0 +1,49 @@ +/** + * Tests sessions that use the native transformation. This is an end to end type testing module. + * @author Ryan Berkheimer + */ + +import java.util.List + +import gov.noaa.messageapi.interfaces.ISession +import gov.noaa.messageapi.interfaces.IRequest +import gov.noaa.messageapi.interfaces.IResponse +import gov.noaa.messageapi.interfaces.IRejection +import gov.noaa.messageapi.interfaces.IRecord +import gov.noaa.messageapi.interfaces.IField + +import gov.noaa.messageapi.sessions.DefaultSession + +class NativeTransformationTests extends spock.lang.Specification { + +def 'Session with one endpoint that calls into C, populates a return record, and checks vals.'() { + given: 'A session created based on a native counter' + ISession session = new DefaultSession('{}/resources/test/native-transformation/manifest.json') + IRequest request = session.createRequest() + IRecord record1 = request.createRecord() + IRecord record2 = request.createRecord() + + record1.setField('initial-value', 1000) + record1.setField('string-test', 'hi there!') + record1.setField('null-test', 'null') + record2.setField('string-test', 'cool!') + record2.setField('initial-value', 5000) + //record2.setField('null-test', 'null') + /*for (int i=0; i<500; i++) { + IRecord r = request.createRecord(); + r.setField("initial-value", i); + r.setField("string-test", Integer.toString(i)); + }*/ + + when: 'Submit the request, call a transformation in the evaluation endpoint, return all records' + IResponse response = request.submit() + while (!response.isComplete()) { } + then: 'No rejections, two return records, field values match..' + response.getRejections().size() == 0 + response.getRecords().size() == 2 + //response.getRecords().get(0).getField('test-integer').getValue() == 5 + //response.getRecords().get(0).getField('return-list').getValue().get(0) == "first element of our string!" + //response.getRecords().get(0).getField('return-list').getValue().get(1) == "second element of our string!!" + } + +} diff --git a/src/java/main/gov/noaa/messageapi/endpoints/EvaluationEndpoint.java b/src/java/main/gov/noaa/messageapi/endpoints/EvaluationEndpoint.java index a4ff91a..d959d00 100644 --- a/src/java/main/gov/noaa/messageapi/endpoints/EvaluationEndpoint.java +++ b/src/java/main/gov/noaa/messageapi/endpoints/EvaluationEndpoint.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.ArrayList; import java.util.stream.Collectors; +import gov.noaa.messageapi.interfaces.IEndpoint; import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.IPacket; import gov.noaa.messageapi.interfaces.IRecord; @@ -29,7 +30,7 @@ import gov.noaa.messageapi.utils.general.ListUtils; * * @author Ryan Berkheimer */ -public class EvaluationEndpoint extends BaseEndpoint { +public class EvaluationEndpoint extends BaseEndpoint implements IEndpoint { public EvaluationEndpoint(Map parameters) { super(parameters); -- GitLab From 07d1a8ba5021b44339d26581262240bc0c97e797 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Mon, 1 Jun 2020 12:11:56 -0400 Subject: [PATCH 14/53] remove unused imports in C lib headers, begin work on native session --- src/cpp/main/common/MessageApiEndpointLib.cpp | 5 +- src/cpp/main/common/MessageApiEndpointLib.h | 3 + src/cpp/main/common/MessageApiSessionLib.h | 165 ++++++++++++++++++ .../common/MessageApiTransformationLib.cpp | 4 +- .../main/common/MessageApiTransformationLib.h | 3 + .../main/common/session/MessageApiSession.cpp | 0 .../main/common/session/MessageApiSession.h | 0 .../common/session/MessageApiSessionLib.cpp | 0 .../common/session/MessageApiSessionLib.h | 0 9 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 src/cpp/main/common/MessageApiSessionLib.h delete mode 100644 src/cpp/main/common/session/MessageApiSession.cpp delete mode 100644 src/cpp/main/common/session/MessageApiSession.h delete mode 100644 src/cpp/main/common/session/MessageApiSessionLib.cpp delete mode 100644 src/cpp/main/common/session/MessageApiSessionLib.h diff --git a/src/cpp/main/common/MessageApiEndpointLib.cpp b/src/cpp/main/common/MessageApiEndpointLib.cpp index 22bb3b3..dba141c 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.cpp +++ b/src/cpp/main/common/MessageApiEndpointLib.cpp @@ -1,8 +1,5 @@ -#include -#include -#include -#include "MessageApiEndpoint.h" #include "MessageApiEndpointLib.h" +#include "MessageApiEndpoint.h" #include "gov_noaa_messageapi_endpoints_NativeEndpoint.h" /** diff --git a/src/cpp/main/common/MessageApiEndpointLib.h b/src/cpp/main/common/MessageApiEndpointLib.h index 7ca79cc..54fd36c 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.h +++ b/src/cpp/main/common/MessageApiEndpointLib.h @@ -1,5 +1,8 @@ +#include #include +#include "messageapi_structs.h" + /** * @author Ryan Berkheimer */ diff --git a/src/cpp/main/common/MessageApiSessionLib.h b/src/cpp/main/common/MessageApiSessionLib.h new file mode 100644 index 0000000..0b92002 --- /dev/null +++ b/src/cpp/main/common/MessageApiSessionLib.h @@ -0,0 +1,165 @@ +#include +#include + +#include "messageapi_structs.h" +/** + * @author Ryan Berkheimer + */ +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Transformation methods */ + struct val_map *getConstructor(jlong message); + struct record_list *getRecords(jlong message, const char *key); + + /*Record Methods*/ + struct record_list *createRecordList(jlong message); + void addRecord(jlong message, struct record_list *record_list, struct record *record); + + struct record *getRecordCopy(jlong message, struct record *record); + bool getRecordIsValid(jlong message, struct record *record); + + struct string_list *getFieldIds(jlong message, struct record *record); + struct field_list *getFields(jlong message, struct record *record); + struct field *getField(jlong message, struct record *record, const char *fieldId); + bool hasField(jlong message, struct record *record, const char *fieldId); + + struct string_list *getConditionIds(jlong message, struct record *record); + struct condition_list *getConditions(jlong message, struct record *record); + struct condition *getCondition(jlong message, struct record *record, const char *conditionId); + bool hasCondition(jlong message, struct record *record, const char *conditionId); + + /*Rejection Methods*/ + struct rejection_list *createRejectionList(jlong message); + void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection); + struct rejection *getRejectionCopy(jlong message, struct rejection *rejection); + struct record *getRejectionRecord(jlong message, struct rejection *rejection); + struct string_list *getRejectionReasons(jlong message, struct rejection *rejection); + void addRejectionReason(jlong message, struct rejection *rejection, const char *reason); + + /*Field Methods*/ + const char *getFieldId(jlong message, struct field *field); + const char *getFieldType(jlong message, struct field *field); + bool getFieldIsValid(jlong message, struct field *field); + bool getFieldIsRequired(jlong message, struct field *field); + bool getFieldIsNull(jlong message, struct field *field); + struct val *getFieldVal(jlong message, struct field *field); + int getFieldIntVal(jlong message, struct field *field); + long getFieldLongVal(jlong message, struct field *field); + float getFieldFloatVal(jlong message, struct field *field); + double getFieldDoubleVal(jlong message, struct field *field); + signed char getFieldByteVal(jlong message, struct field *field); + const char *getFieldStringVal(jlong message, struct field *field); + bool getFieldBoolVal(jlong message, struct field *field); + short getFieldShortVal(jlong message, struct field *field); + struct val_list *getFieldListVal(jlong message, struct field *field); + void setFieldVal(jlong message, struct field *field, struct val *value); + void setFieldIntVal(jlong message, struct field *field, int value); + void setFieldLongVal(jlong message, struct field *field, long value); + void setFieldFloatVal(jlong message, struct field *field, float value); + void setFieldDoubleVal(jlong message, struct field *field, double value); + void setFieldByteVal(jlong message, struct field *field, signed char value); + void setFieldStringVal(jlong message, struct field *field, const char *value); + void setFieldBoolVal(jlong message, struct field *field, bool value); + void setFieldShortVal(jlong message, struct field *field, short value); + void setFieldListVal(jlong message, struct field *field, struct val_list *value); + + /*Condition Methods*/ + const char *getConditionId(jlong message, struct condition *condition); + const char *getConditionType(jlong message, struct condition *condition); + const char *getConditionOperator(jlong message, struct condition *condition); + bool getConditionIsNull(jlong message, struct condition *condition); + struct val *getConditionVal(jlong message, struct condition *condition); + int getConditionIntVal(jlong message, struct condition *condition); + long getConditionLongVal(jlong message, struct condition *condition); + float getConditionFloatVal(jlong message, struct condition *condition); + double getConditionDoubleVal(jlong message, struct condition *condition); + signed char getConditionByteVal(jlong message, struct condition *condition); + const char *getConditionStringVal(jlong message, struct condition *condition); + bool getConditionBoolVal(jlong message, struct condition *condition); + short getConditionShortVal(jlong message, struct condition *condition); + struct val_list *getConditionListVal(jlong message, struct condition *condition); + void setConditionVal(jlong message, struct condition *condition, struct val *value); + void setConditionIntVal(jlong message, struct condition *condition, int value); + void setConditionLongVal(jlong message, struct condition *condition, long value); + void setConditionFloatVal(jlong message, struct condition *condition, float value); + void setConditionDoubleVal(jlong message, struct condition *condition, double value); + void setConditionByteVal(jlong message, struct condition *condition, signed char value); + void setConditionStringVal(jlong message, struct condition *condition, const char *value); + void setConditionBoolVal(jlong message, struct condition *condition, bool value); + void setConditionShortVal(jlong message, struct condition *condition, short value); + void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); + + /*List Utility Methods*/ + int getIntItem(jlong message, struct val_list *list, int index); + long getLongItem(jlong message, struct val_list *list, int index); + float getFloatItem(jlong message, struct val_list *list, int index); + double getDoubleItem(jlong message, struct val_list *list, int index); + signed char getByteItem(jlong message, struct val_list *list, int index); + const char *getStringItem(jlong message, struct val_list *list, int index); + bool getBoolItem(jlong message, struct val_list *list, int index); + short getShortItem(jlong message, struct val_list *list, int index); + struct list_item *getItem(jlong message, struct val_list *list, int index); + struct val_list *getListItem(jlong message, struct val_list *list, int index); + struct val_map *getMapItem(jlong message, struct val_list *list, int index); + struct val_list *createList(jlong message); + void addItem(jlong message, struct val_list *list, struct list_item *item); + void addIntItem(jlong message, struct val_list *list, int val); + void addLongItem(jlong message, struct val_list *list, long val); + void addFloatItem(jlong message, struct val_list *list, float val); + void addDoubleItem(jlong message, struct val_list *list, double val); + void addByteItem(jlong message, struct val_list *list, signed char val); + void addStringItem(jlong message, struct val_list *list, const char *val); + void addBoolItem(jlong message, struct val_list *list, bool val); + void addShortItem(jlong message, struct val_list *list, short val); + void addListItem(jlong message, struct val_list *list, struct val_list *val); + void addMapItem(jlong message, struct val_list *list, struct val_map *map); + + /*Map Utility Methods*/ + struct val_map *createMap(jlong message); + int getSize(jlong message, struct val_map *map); + bool hasKey(jlong message, struct val_map *map, const char *key); + + /*Map Value Retrieval Methods*/ + struct map_val *getVal(jlong message, struct val_map *map, const char *key); + jobject getObjectVal(jlong message, struct val_map *map, const char *key); + int getIntVal(jlong message, struct val_map *map, const char *key); + long getLongVal(jlong message, struct val_map *map, const char *key); + float getFloatVal(jlong message, struct val_map *map, const char *key); + double getDoubleVal(jlong message, struct val_map *map, const char *key); + signed char getByteVal(jlong message, struct val_map *map, const char *key); + const char *getStringVal(jlong message, struct val_map *map, const char *key); + bool getBoolVal(jlong message, struct val_map *map, const char *key); + short getShortVal(jlong message, struct val_map *map, const char *key); + struct val_list *getListVal(jlong message, struct val_map *map, const char *key); + struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + + /*Insert or Update Methods*/ + void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); + void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); + void putIntVal(jlong message, struct val_map *map, const char *key, int val); + void putLongVal(jlong message, struct val_map *map, const char *key, long val); + void putFloatVal(jlong message, struct val_map *map, const char *key, float val); + void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); + void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); + void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); + void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); + void putShortVal(jlong message, struct val_map *map, const char *key, short val); + void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); + void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); + + /*Packet Methods*/ + void addPacketRecord(jlong message, struct packet *packet, struct record *record); + void setPacketRecords(jlong message, struct packet *packet, struct record_list *records); + void addPacketRecords(jlong message, struct packet *packet, struct record_list *records); + void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); + void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection); + void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); + struct record_list *getPacketRecords(jlong message, struct packet *packet); + struct rejection_list *getPacketRejections(jlong message, struct packet *packet); + +#ifdef __cplusplus +} +#endif diff --git a/src/cpp/main/common/MessageApiTransformationLib.cpp b/src/cpp/main/common/MessageApiTransformationLib.cpp index 1d62353..8a95d6a 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.cpp +++ b/src/cpp/main/common/MessageApiTransformationLib.cpp @@ -1,7 +1,5 @@ -#include -#include -#include "MessageApiTransformation.h" #include "MessageApiTransformationLib.h" +#include "MessageApiTransformation.h" #include "gov_noaa_messageapi_transformations_NativeTransformation.h" /** diff --git a/src/cpp/main/common/MessageApiTransformationLib.h b/src/cpp/main/common/MessageApiTransformationLib.h index de26b74..4e2b65a 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.h +++ b/src/cpp/main/common/MessageApiTransformationLib.h @@ -1,5 +1,8 @@ +#include #include +#include "messageapi_structs.h" + /** * @author Ryan Berkheimer */ diff --git a/src/cpp/main/common/session/MessageApiSession.cpp b/src/cpp/main/common/session/MessageApiSession.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/session/MessageApiSession.h b/src/cpp/main/common/session/MessageApiSession.h deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/session/MessageApiSessionLib.cpp b/src/cpp/main/common/session/MessageApiSessionLib.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/cpp/main/common/session/MessageApiSessionLib.h b/src/cpp/main/common/session/MessageApiSessionLib.h deleted file mode 100644 index e69de29..0000000 -- GitLab From 87e54b6a7dbb44481559eb1a86342f428663a4e2 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Mon, 1 Jun 2020 12:44:10 -0400 Subject: [PATCH 15/53] add methods for getting/setting values as maps from fields and conditions --- src/cpp/main/common/ConditionUtils.cpp | 20 +++++++++++--- src/cpp/main/common/ConditionUtils.h | 10 +++++-- src/cpp/main/common/FieldUtils.cpp | 20 +++++++++++--- src/cpp/main/common/FieldUtils.h | 10 +++++-- src/cpp/main/common/MessageApiEndpoint.cpp | 4 +-- src/cpp/main/common/MessageApiSessionLib.h | 27 ++++++++++++++++--- .../main/common/MessageApiTransformation.cpp | 4 +-- 7 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/cpp/main/common/ConditionUtils.cpp b/src/cpp/main/common/ConditionUtils.cpp index 9077a32..821488b 100644 --- a/src/cpp/main/common/ConditionUtils.cpp +++ b/src/cpp/main/common/ConditionUtils.cpp @@ -4,9 +4,9 @@ /* Default Constructor */ -ConditionUtils::ConditionUtils(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +ConditionUtils::ConditionUtils(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils) { - this->loadGlobalRefs(jvm, typeUtils, listUtils); + this->loadGlobalRefs(jvm, typeUtils, listUtils, mapUtils); this->loadMethodIds(); } @@ -134,6 +134,14 @@ struct val_list *ConditionUtils::getListVal(struct condition *condition) return valueList; } +struct val_map *ConditionUtils::getMapVal(struct condition *condition) +{ + struct val *value = this->getVal(condition); + struct val_map *valueMap = (struct val_map *)malloc(sizeof(struct val_map)); + valueMap->jmap = value->jvalue; + return valueMap; +} + void ConditionUtils::setVal(struct condition *condition, struct val *value) { this->jvm->CallVoidMethod(condition->jcondition, this->setValueMethodId, value->jvalue); @@ -200,12 +208,18 @@ void ConditionUtils::setListVal(struct condition *condition, struct val_list *va this->jvm->CallVoidMethod(condition->jcondition, this->setValueMethodId, value->jlist); } +void ConditionUtils::setMapVal(struct condition *condition, struct val_map *value) +{ + this->jvm->CallVoidMethod(condition->jcondition, this->setValueMethodId, value->jmap); +} + /* Private Methods */ -void ConditionUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +void ConditionUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils) { this->jvm = jvm; this->typeUtils = typeUtils; this->listUtils = listUtils; + this->mapUtils = mapUtils; } void ConditionUtils::loadMethodIds() diff --git a/src/cpp/main/common/ConditionUtils.h b/src/cpp/main/common/ConditionUtils.h index f947d11..d916e8a 100644 --- a/src/cpp/main/common/ConditionUtils.h +++ b/src/cpp/main/common/ConditionUtils.h @@ -11,6 +11,7 @@ #include "JniUtils.h" #include "ListUtils.h" +#include "MapUtils.h" /** * This is the header for the ConditionUtils class. @@ -21,7 +22,7 @@ class ConditionUtils public: /*Default constructor/destructors*/ - ConditionUtils(JNIEnv *javaEnv, TypeUtils *typeUtils, ListUtils *listUtils); + ConditionUtils(JNIEnv *javaEnv, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils); ~ConditionUtils(); /*API Methods*/ @@ -29,6 +30,7 @@ public: const char *getType(struct condition *condition); const char *getOperator(struct condition *condition); bool isNull(struct condition *condition); + struct val *getVal(struct condition *condition); int getIntVal(struct condition *condition); long getLongVal(struct condition *condition); @@ -39,6 +41,8 @@ public: bool getBoolVal(struct condition *condition); short getShortVal(struct condition *condition); struct val_list *getListVal(struct condition *condition); + struct val_map *getMapVal(struct condition *condition); + void setVal(struct condition *condition, struct val *value); void setIntVal(struct condition *condition, int value); void setLongVal(struct condition *condition, long value); @@ -49,12 +53,14 @@ public: void setBoolVal(struct condition *condition, bool value); void setShortVal(struct condition *condition, short value); void setListVal(struct condition *condition, struct val_list *value); + void setMapVal(struct condition *condition, struct val_map *value); private: /*Vars*/ JNIEnv *jvm; ListUtils *listUtils; TypeUtils *typeUtils; + MapUtils *mapUtils; /*Condition Methods*/ jmethodID getIdMethodId; @@ -65,7 +71,7 @@ private: /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ void loadMethodIds(); - void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, ListUtils *listUtils); + void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils); /*Grouped methods for returning the matching method signature string for a given interface*/ const char *getMethodSignature(const char *methodName); diff --git a/src/cpp/main/common/FieldUtils.cpp b/src/cpp/main/common/FieldUtils.cpp index e5bc3a3..28b6508 100644 --- a/src/cpp/main/common/FieldUtils.cpp +++ b/src/cpp/main/common/FieldUtils.cpp @@ -4,9 +4,9 @@ /** Constructor */ -FieldUtils::FieldUtils(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +FieldUtils::FieldUtils(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils) { - this->loadGlobalRefs(jvm, typeUtils, listUtils); + this->loadGlobalRefs(jvm, typeUtils, listUtils, mapUtils); this->loadMethodIds(); } @@ -138,6 +138,14 @@ struct val_list *FieldUtils::getListVal(struct field *field) return valueList; } +struct val_map *FieldUtils::getMapVal(struct field *field) +{ + struct val *value = this->getVal(field); + struct val_map *valueMap = (struct val_map *)malloc(sizeof(struct val_map)); + valueMap->jmap = value->jvalue; + return valueMap; +} + void FieldUtils::setVal(struct field *field, struct val *value) { this->jvm->CallVoidMethod(field->jfield, this->setValueMethodId, value->jvalue); @@ -204,12 +212,18 @@ void FieldUtils::setListVal(struct field *field, struct val_list *value) this->jvm->CallVoidMethod(field->jfield, this->setValueMethodId, value->jlist); } +void FieldUtils::setMapVal(struct field *field, struct val_map *value) +{ + this->jvm->CallVoidMethod(field->jfield, this->setValueMethodId, value->jmap); +} + /* Private Methods */ -void FieldUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils) +void FieldUtils::loadGlobalRefs(JNIEnv *jvm, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils) { this->jvm = jvm; this->typeUtils = typeUtils; this->listUtils = listUtils; + this->mapUtils = mapUtils; } void FieldUtils::loadMethodIds() diff --git a/src/cpp/main/common/FieldUtils.h b/src/cpp/main/common/FieldUtils.h index 2fcb08a..34a8ff6 100644 --- a/src/cpp/main/common/FieldUtils.h +++ b/src/cpp/main/common/FieldUtils.h @@ -12,6 +12,7 @@ #include "JniUtils.h" #include "TypeUtils.h" #include "ListUtils.h" +#include "MapUtils.h" /** * This is the header for the FieldUtils class. @@ -22,7 +23,7 @@ class FieldUtils public: /*Default constructor/destructors*/ - FieldUtils(JNIEnv *javaEnv, TypeUtils *typeUtils, ListUtils *listUtils); + FieldUtils(JNIEnv *javaEnv, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils); ~FieldUtils(); /*Field Methods*/ @@ -31,6 +32,7 @@ public: bool isValid(struct field *field); bool isRequired(struct field *field); bool isNull(struct field *field); + struct val *getVal(struct field *field); int getIntVal(struct field *field); long getLongVal(struct field *field); @@ -41,6 +43,8 @@ public: bool getBoolVal(struct field *field); short getShortVal(struct field *field); struct val_list *getListVal(struct field *field); + struct val_map *getMapVal(struct field *field); + void setVal(struct field *field, struct val *value); void setIntVal(struct field *field, int value); void setLongVal(struct field *field, long value); @@ -51,6 +55,7 @@ public: void setBoolVal(struct field *field, bool value); void setShortVal(struct field *field, short value); void setListVal(struct field *field, struct val_list *value); + void setMapVal(struct field *field, struct val_map *value); private: @@ -58,6 +63,7 @@ private: JNIEnv *jvm; TypeUtils *typeUtils; ListUtils *listUtils; + MapUtils *mapUtils; /*Field Methods*/ jmethodID getIdMethodId; @@ -69,7 +75,7 @@ private: /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ void loadMethodIds(); - void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, ListUtils *listUtils); + void loadGlobalRefs(JNIEnv *env, TypeUtils *typeUtils, ListUtils *listUtils, MapUtils *mapUtils); /*Grouped methods for returning the matching method signature string for a given interface*/ const char *getMethodSignature(const char *methodName); diff --git a/src/cpp/main/common/MessageApiEndpoint.cpp b/src/cpp/main/common/MessageApiEndpoint.cpp index 64ea8e1..d83d0f6 100644 --- a/src/cpp/main/common/MessageApiEndpoint.cpp +++ b/src/cpp/main/common/MessageApiEndpoint.cpp @@ -24,8 +24,8 @@ MessageApiEndpoint::MessageApiEndpoint(JNIEnv *env, jobject jendpoint, jobject j this->protocolRecordUtils = new ProtocolRecordUtils(this->jvm, this->protocolRecord, this->typeUtils, this->listUtils); this->recordUtils = new RecordUtils(this->jvm, this->typeUtils, this->listUtils); this->rejectionUtils = new RejectionUtils(this->jvm, this->typeUtils, this->listUtils); - this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils); - this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils); + this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); + this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); this->packetUtils = new PacketUtils(this->jvm, this->listUtils); } diff --git a/src/cpp/main/common/MessageApiSessionLib.h b/src/cpp/main/common/MessageApiSessionLib.h index 0b92002..ebd8e67 100644 --- a/src/cpp/main/common/MessageApiSessionLib.h +++ b/src/cpp/main/common/MessageApiSessionLib.h @@ -10,9 +10,22 @@ extern "C" { #endif - /* Transformation methods */ - struct val_map *getConstructor(jlong message); - struct record_list *getRecords(jlong message, const char *key); + /* Session methods */ + struct session *createSession(const char* message); + struct request *createRequest(struct session *session); + + /* Request methods */ + struct record *createRecord(struct request *request); + struct request *getCopy(struct request *request); + struct request *getCopy(struct request *request, struct val_list *copy_components); + const char *getType(struct request *request); + struct record_list *getRecords(struct request *request); + struct record *getRequestRecord(struct request *request); + void setRecords(struct request *request, struct record_list *records); + struct response *submitRequest(struct request *request); + + /* Response methods */ + /*Record Methods*/ struct record_list *createRecordList(jlong message); @@ -45,6 +58,8 @@ extern "C" bool getFieldIsValid(jlong message, struct field *field); bool getFieldIsRequired(jlong message, struct field *field); bool getFieldIsNull(jlong message, struct field *field); + + /* Field Value Retrieval */ struct val *getFieldVal(jlong message, struct field *field); int getFieldIntVal(jlong message, struct field *field); long getFieldLongVal(jlong message, struct field *field); @@ -55,6 +70,8 @@ extern "C" bool getFieldBoolVal(jlong message, struct field *field); short getFieldShortVal(jlong message, struct field *field); struct val_list *getFieldListVal(jlong message, struct field *field); + + /*Field Value Puts */ void setFieldVal(jlong message, struct field *field, struct val *value); void setFieldIntVal(jlong message, struct field *field, int value); void setFieldLongVal(jlong message, struct field *field, long value); @@ -71,6 +88,8 @@ extern "C" const char *getConditionType(jlong message, struct condition *condition); const char *getConditionOperator(jlong message, struct condition *condition); bool getConditionIsNull(jlong message, struct condition *condition); + + /* Condition value retrieval */ struct val *getConditionVal(jlong message, struct condition *condition); int getConditionIntVal(jlong message, struct condition *condition); long getConditionLongVal(jlong message, struct condition *condition); @@ -81,6 +100,8 @@ extern "C" bool getConditionBoolVal(jlong message, struct condition *condition); short getConditionShortVal(jlong message, struct condition *condition); struct val_list *getConditionListVal(jlong message, struct condition *condition); + + /* Condition value puts */ void setConditionVal(jlong message, struct condition *condition, struct val *value); void setConditionIntVal(jlong message, struct condition *condition, int value); void setConditionLongVal(jlong message, struct condition *condition, long value); diff --git a/src/cpp/main/common/MessageApiTransformation.cpp b/src/cpp/main/common/MessageApiTransformation.cpp index bf0fd35..87d8c3d 100644 --- a/src/cpp/main/common/MessageApiTransformation.cpp +++ b/src/cpp/main/common/MessageApiTransformation.cpp @@ -23,8 +23,8 @@ MessageApiTransformation::MessageApiTransformation(JNIEnv *env, jobject jtransfo this->transformationUtils = new TransformationUtils(this->jvm, this->transformation, this->transformationMap, this->typeUtils, this->mapUtils, this->listUtils); this->recordUtils = new RecordUtils(this->jvm, this->typeUtils, this->listUtils); this->rejectionUtils = new RejectionUtils(this->jvm, this->typeUtils, this->listUtils); - this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils); - this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils); + this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); + this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); this->packetUtils = new PacketUtils(this->jvm, this->listUtils); } -- GitLab From d28f60281c74036cfda34aa892b7c87d7efdfc21 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Mon, 1 Jun 2020 12:55:45 -0400 Subject: [PATCH 16/53] add accessors to Endpoint and Transformation Libs for new condition/field map methods --- src/cpp/main/common/MessageApiEndpointLib.cpp | 20 +++++++++++++++++++ src/cpp/main/common/MessageApiEndpointLib.h | 8 ++++++++ .../common/MessageApiTransformationLib.cpp | 20 +++++++++++++++++++ .../main/common/MessageApiTransformationLib.h | 12 ++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/cpp/main/common/MessageApiEndpointLib.cpp b/src/cpp/main/common/MessageApiEndpointLib.cpp index dba141c..f3e9cb8 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.cpp +++ b/src/cpp/main/common/MessageApiEndpointLib.cpp @@ -222,6 +222,11 @@ extern "C" return reinterpret_cast(message)->getFieldUtils()->getListVal(field); } + struct val_map *getFieldMapVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getMapVal(field); + } + void setFieldVal(jlong message, struct field *field, struct val *value) { return reinterpret_cast(message)->getFieldUtils()->setVal(field, value); @@ -272,6 +277,11 @@ extern "C" return reinterpret_cast(message)->getFieldUtils()->setListVal(field, value); } + void setFieldMapVal(jlong message, struct field *field, struct val_map *value) + { + return reinterpret_cast(message)->getFieldUtils()->setMapVal(field, value); + } + /*Condition Methods*/ const char *getConditionId(jlong message, struct condition *condition) @@ -344,6 +354,11 @@ extern "C" return reinterpret_cast(message)->getConditionUtils()->getListVal(condition); } + struct val_map *getConditionMapVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getMapVal(condition); + } + void setConditionVal(jlong message, struct condition *condition, struct val *value) { return reinterpret_cast(message)->getConditionUtils()->setVal(condition, value); @@ -394,6 +409,11 @@ extern "C" return reinterpret_cast(message)->getConditionUtils()->setListVal(condition, value); } + void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value) + { + return reinterpret_cast(message)->getConditionUtils()->setMapVal(condition, value); + } + /*List Utility Methods*/ struct list_item *getItem(jlong message, struct val_list *list, int index) diff --git a/src/cpp/main/common/MessageApiEndpointLib.h b/src/cpp/main/common/MessageApiEndpointLib.h index 54fd36c..5111a9a 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.h +++ b/src/cpp/main/common/MessageApiEndpointLib.h @@ -58,6 +58,7 @@ extern "C" bool getFieldIsValid(jlong message, struct field *field); bool getFieldIsRequired(jlong message, struct field *field); bool getFieldIsNull(jlong message, struct field *field); + struct val *getFieldVal(jlong message, struct field *field); int getFieldIntVal(jlong message, struct field *field); long getFieldLongVal(jlong message, struct field *field); @@ -68,6 +69,8 @@ extern "C" bool getFieldBoolVal(jlong message, struct field *field); short getFieldShortVal(jlong message, struct field *field); struct val_list *getFieldListVal(jlong message, struct field *field); + struct val_map *getFieldMapVal(jlong message, struct field *field); + void setFieldVal(jlong message, struct field *field, struct val *value); void setFieldIntVal(jlong message, struct field *field, int value); void setFieldLongVal(jlong message, struct field *field, long value); @@ -78,12 +81,14 @@ extern "C" void setFieldBoolVal(jlong message, struct field *field, bool value); void setFieldShortVal(jlong message, struct field *field, short value); void setFieldListVal(jlong message, struct field *field, struct val_list *value); + void setFieldMapVal(jlong message, struct field *field, struct val_map *value); /*Condition Methods*/ const char *getConditionId(jlong message, struct condition *condition); const char *getConditionType(jlong message, struct condition *condition); const char *getConditionOperator(jlong message, struct condition *condition); bool getConditionIsNull(jlong message, struct condition *condition); + struct val *getConditionVal(jlong message, struct condition *condition); int getConditionIntVal(jlong message, struct condition *condition); long getConditionLongVal(jlong message, struct condition *condition); @@ -94,6 +99,8 @@ extern "C" bool getConditionBoolVal(jlong message, struct condition *condition); short getConditionShortVal(jlong message, struct condition *condition); struct val_list *getConditionListVal(jlong message, struct condition *condition); + struct val_map *getConditionMapVal(jlong message, struct condition *condition); + void setConditionVal(jlong message, struct condition *condition, struct val *value); void setConditionIntVal(jlong message, struct condition *condition, int value); void setConditionLongVal(jlong message, struct condition *condition, long value); @@ -104,6 +111,7 @@ extern "C" void setConditionBoolVal(jlong message, struct condition *condition, bool value); void setConditionShortVal(jlong message, struct condition *condition, short value); void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); + void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value); /*List Utility Methods*/ int getIntItem(jlong message, struct val_list *list, int index); diff --git a/src/cpp/main/common/MessageApiTransformationLib.cpp b/src/cpp/main/common/MessageApiTransformationLib.cpp index 8a95d6a..96e56c2 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.cpp +++ b/src/cpp/main/common/MessageApiTransformationLib.cpp @@ -177,6 +177,11 @@ extern "C" return reinterpret_cast(message)->getFieldUtils()->getListVal(field); } + struct val_map *getFieldMapVal(jlong message, struct field *field) + { + return reinterpret_cast(message)->getFieldUtils()->getMapVal(field); + } + void setFieldVal(jlong message, struct field *field, struct val *value) { return reinterpret_cast(message)->getFieldUtils()->setVal(field, value); @@ -227,6 +232,11 @@ extern "C" return reinterpret_cast(message)->getFieldUtils()->setListVal(field, value); } + void setFieldMapVal(jlong message, struct field *field, struct val_map *value) + { + return reinterpret_cast(message)->getFieldUtils()->setMapVal(field, value); + } + /*Condition Methods*/ const char *getConditionId(jlong message, struct condition *condition) @@ -299,6 +309,11 @@ extern "C" return reinterpret_cast(message)->getConditionUtils()->getListVal(condition); } + struct val_map *getConditionMapVal(jlong message, struct condition *condition) + { + return reinterpret_cast(message)->getConditionUtils()->getMapVal(condition); + } + void setConditionVal(jlong message, struct condition *condition, struct val *value) { return reinterpret_cast(message)->getConditionUtils()->setVal(condition, value); @@ -349,6 +364,11 @@ extern "C" return reinterpret_cast(message)->getConditionUtils()->setListVal(condition, value); } + void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value) + { + return reinterpret_cast(message)->getConditionUtils()->setMapVal(condition, value); + } + /*List Utility Methods*/ struct list_item *getItem(jlong message, struct val_list *list, int index) diff --git a/src/cpp/main/common/MessageApiTransformationLib.h b/src/cpp/main/common/MessageApiTransformationLib.h index 4e2b65a..510105e 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.h +++ b/src/cpp/main/common/MessageApiTransformationLib.h @@ -46,6 +46,7 @@ extern "C" bool getFieldIsValid(jlong message, struct field *field); bool getFieldIsRequired(jlong message, struct field *field); bool getFieldIsNull(jlong message, struct field *field); + struct val *getFieldVal(jlong message, struct field *field); int getFieldIntVal(jlong message, struct field *field); long getFieldLongVal(jlong message, struct field *field); @@ -56,6 +57,8 @@ extern "C" bool getFieldBoolVal(jlong message, struct field *field); short getFieldShortVal(jlong message, struct field *field); struct val_list *getFieldListVal(jlong message, struct field *field); + struct val_map *getFieldMapVal(jlong message, struct field *field); + void setFieldVal(jlong message, struct field *field, struct val *value); void setFieldIntVal(jlong message, struct field *field, int value); void setFieldLongVal(jlong message, struct field *field, long value); @@ -66,12 +69,14 @@ extern "C" void setFieldBoolVal(jlong message, struct field *field, bool value); void setFieldShortVal(jlong message, struct field *field, short value); void setFieldListVal(jlong message, struct field *field, struct val_list *value); + void setFieldMapVal(jlong message, struct field *field, struct val_map *value); /*Condition Methods*/ const char *getConditionId(jlong message, struct condition *condition); const char *getConditionType(jlong message, struct condition *condition); const char *getConditionOperator(jlong message, struct condition *condition); bool getConditionIsNull(jlong message, struct condition *condition); + struct val *getConditionVal(jlong message, struct condition *condition); int getConditionIntVal(jlong message, struct condition *condition); long getConditionLongVal(jlong message, struct condition *condition); @@ -82,6 +87,8 @@ extern "C" bool getConditionBoolVal(jlong message, struct condition *condition); short getConditionShortVal(jlong message, struct condition *condition); struct val_list *getConditionListVal(jlong message, struct condition *condition); + struct val_map *getConditionMapVal(jlong message, struct condition *condition); + void setConditionVal(jlong message, struct condition *condition, struct val *value); void setConditionIntVal(jlong message, struct condition *condition, int value); void setConditionLongVal(jlong message, struct condition *condition, long value); @@ -92,8 +99,11 @@ extern "C" void setConditionBoolVal(jlong message, struct condition *condition, bool value); void setConditionShortVal(jlong message, struct condition *condition, short value); void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); + void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value); /*List Utility Methods*/ + struct val_list *createList(jlong message); + int getIntItem(jlong message, struct val_list *list, int index); long getLongItem(jlong message, struct val_list *list, int index); float getFloatItem(jlong message, struct val_list *list, int index); @@ -105,7 +115,7 @@ extern "C" struct list_item *getItem(jlong message, struct val_list *list, int index); struct val_list *getListItem(jlong message, struct val_list *list, int index); struct val_map *getMapItem(jlong message, struct val_list *list, int index); - struct val_list *createList(jlong message); + void addItem(jlong message, struct val_list *list, struct list_item *item); void addIntItem(jlong message, struct val_list *list, int val); void addLongItem(jlong message, struct val_list *list, long val); -- GitLab From ab3c74b374e9945f55578bfb42d1bb1a98b7f85c Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Tue, 2 Jun 2020 14:41:28 -0400 Subject: [PATCH 17/53] completed adding code for native session. now needs wrapper, build process, and tests before feature is complete --- .../main/common/structs/messageapi_structs.h | 86 +- .../demoendpointlibrary/EndpointWrapper.c | 41 +- src/c/test/sessions/demosession/DemoSession.c | 4 +- .../sessions/demosession/NativeSessionDemo.c | 13 + src/c/test/sessions/demosession/compile.sh | 3 + .../TransformationWrapper.c | 2 +- src/cpp/main/common/MessageApiEndpointLib.cpp | 282 +++---- src/cpp/main/common/MessageApiEndpointLib.h | 288 +++---- src/cpp/main/common/MessageApiSession.cpp | 111 +++ src/cpp/main/common/MessageApiSession.h | 77 ++ src/cpp/main/common/MessageApiSessionLib.cpp | 788 ++++++++++++++++++ src/cpp/main/common/MessageApiSessionLib.h | 282 ++++--- .../common/MessageApiTransformationLib.cpp | 206 ++--- .../main/common/MessageApiTransformationLib.h | 272 +++--- src/cpp/main/common/SessionUtils.cpp | 11 +- src/cpp/main/common/SessionUtils.h | 7 +- 16 files changed, 1739 insertions(+), 734 deletions(-) create mode 100644 src/c/test/sessions/demosession/NativeSessionDemo.c create mode 100755 src/c/test/sessions/demosession/compile.sh create mode 100644 src/cpp/main/common/MessageApiSession.cpp create mode 100644 src/cpp/main/common/MessageApiSession.h create mode 100644 src/cpp/main/common/MessageApiSessionLib.cpp diff --git a/src/c/main/common/structs/messageapi_structs.h b/src/c/main/common/structs/messageapi_structs.h index 089b969..f05ff1b 100644 --- a/src/c/main/common/structs/messageapi_structs.h +++ b/src/c/main/common/structs/messageapi_structs.h @@ -8,116 +8,116 @@ * @author Ryan Berkheimer */ -struct map_val +typedef struct map_val { jobject jval; -}; +} map_val; -struct val_map +typedef struct val_map { jobject jmap; -}; +} val_map; -struct list_item +typedef struct list_item { jobject jitem; -}; +} list_item; -struct val_list +typedef struct val_list { int count; jobject jlist; -}; +} val_list; -struct session +typedef struct session { - jobject jsession; -}; + jlong sessionLib; +} session; -struct transformation +typedef struct transformation { jobject jtransformation; -}; +} transformation; -struct transformation_map +typedef struct transformation_map { jobject jtransformation_map; -}; +} transformation_map; -struct response +typedef struct response { jobject jresponse; -}; +} response; -struct request +typedef struct request { jobject jrequest; -}; +} request; -struct condition +typedef struct condition { jobject jcondition; -}; +} condition; -struct condition_list +typedef struct condition_list { int count; struct condition **conditions; -}; -struct val +} condition_list; +typedef struct val { jobject jvalue; -}; +} val; -struct field +typedef struct field { jobject jfield; -}; +} field; -struct field_list +typedef struct field_list { int count; struct field **fields; -}; +} field_list; -struct packet +typedef struct packet { jobject jpacket; -}; +} packet; -struct record +typedef struct record { jobject jrecord; -}; +} record; -struct rejection_list +typedef struct rejection_list { int count; jobject jrejections; -}; -struct rejection +} rejection_list; +typedef struct rejection { jobject jrejection; -}; +} rejection; -struct record_list +typedef struct record_list { int count; jobject jrecords; -}; +} record_list; -struct string_list +typedef struct string_list { int count; int max_length; char **strings; -}; +} string_list; -struct classifier +typedef struct classifier { char* key; char* val; -}; +} classifier; #endif \ No newline at end of file diff --git a/src/c/test/endpoints/demoendpointlibrary/EndpointWrapper.c b/src/c/test/endpoints/demoendpointlibrary/EndpointWrapper.c index c3b655b..136b1a3 100644 --- a/src/c/test/endpoints/demoendpointlibrary/EndpointWrapper.c +++ b/src/c/test/endpoints/demoendpointlibrary/EndpointWrapper.c @@ -14,22 +14,22 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_endpoints_NativeEndpoint_proc { printf("In our test!\n"); printf("Hello, World\n"); - struct record_list* default_record_list = getRecords(message); + record_list* default_record_list = getRecords(message); //struct record_list* classifier_record_list = getRecordsByClassifier(message, "color", "blue"); //struct record_list* collection_record_list = getRecordsByCollection(message, "gold"); //struct record_list* transformation_record_list = getRecordsByTransformation(message, "combine-colors"); printf("Record count: %d\n", default_record_list->count); - struct string_list* default_field_name_list = getFieldIds(message, getRecord(message, default_record_list, 0)); + string_list* default_field_name_list = getFieldIds(message, getRecord(message, default_record_list, 0)); printf("Field name count: %d\n", default_field_name_list->count); printf("Length of longest field name: %d\n", default_field_name_list->max_length); for (int i = 0; i < default_field_name_list->count; i++) { printf("Field name: %s\n", default_field_name_list->strings[i]); } fflush(stdout); - struct field *testField = getField(message, getRecord(message, default_record_list, 0), "initial-value"); - struct field *testField2 = getField(message, getRecord(message, default_record_list, 0), "string-test"); - struct field *testField3 = getField(message, getRecord(message, default_record_list, 0), "int-list-test"); - struct field *testField4 = getField(message, getRecord(message, default_record_list, 0), "null-test"); + field *testField = getField(message, getRecord(message, default_record_list, 0), "initial-value"); + field *testField2 = getField(message, getRecord(message, default_record_list, 0), "string-test"); + field *testField3 = getField(message, getRecord(message, default_record_list, 0), "int-list-test"); + field *testField4 = getField(message, getRecord(message, default_record_list, 0), "null-test"); const char *testFieldId = getFieldId(message, testField); const char *testFieldId2 = getFieldId(message, testField2); const char *testFieldId3 = getFieldId(message, testField3); @@ -53,10 +53,11 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_endpoints_NativeEndpoint_proc printf("Field integer value is %d\n", integerFieldValue); const char *stringFieldValue = getFieldStringVal(message, testField2); printf("Field string value 2 is: %s\n", stringFieldValue); - struct val_list *val_list = getFieldListVal(message, testField3); - printf("Field value 3 (list) length is: %d\n", val_list->count); - for (int i = 0; i < val_list->count; i++) { - printf("Field value 3, element %d, is: %d\n", i, getIntItem(message, val_list, i)); + val_list *fieldList = getFieldListVal(message, testField3); + printf("Field value 3 (list) length is: %d\n", fieldList->count); + for (int i = 0; i < fieldList->count; i++) + { + printf("Field value 3, element %d, is: %d\n", i, getIntItem(message, fieldList, i)); } fflush(stdout); if (getFieldIsNull(message, testField4)) { @@ -65,8 +66,8 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_endpoints_NativeEndpoint_proc printf("Field val 4 has a value!\n"); } fflush(stdout); - struct record *returnRecord = createRecord(message); - struct string_list *fieldIds = getFieldIds(message, returnRecord); + record *returnRecord = createRecord(message); + string_list *fieldIds = getFieldIds(message, returnRecord); printf("field ids for return field follow. \n"); for (int i=0; i < fieldIds->count; i++) { printf("Field name: %s\n", fieldIds->strings[i]); @@ -81,17 +82,17 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_endpoints_NativeEndpoint_proc } } fflush(stdout); - printf("Creating a string list..\n"); - struct val_list *return_val_list = createList(message); - addStringItem(message, return_val_list, "first element of our string!"); - addStringItem(message, return_val_list, "second element of our string!!"); + printf("Creating a value list to hold strings..\n"); + val_list *returnList = createList(message); + addStringItem(message, returnList, "first element of our string!"); + addStringItem(message, returnList, "second element of our string!!"); printf("Created a string list.\n"); - setFieldListVal(message, getField(message, returnRecord, "return-list"), return_val_list); - printf("First value added to the return-list field: %s\n", getStringItem(message, return_val_list, 0)); - printf("Second value added to the return-list field: %s\n", getStringItem(message, return_val_list, 1)); + setFieldListVal(message, getField(message, returnRecord, "return-list"), returnList); + printf("First value added to the return-list field: %s\n", getStringItem(message, returnList, 0)); + printf("Second value added to the return-list field: %s\n", getStringItem(message, returnList, 1)); printf("Added the string list to the return record. Should have two elements, see above.\n"); fflush(stdout); - struct packet* packet = createPacket(message); + packet* packet = createPacket(message); addPacketRecord(message, packet, returnRecord); printf("Leaving our C test!"); fflush(stdout); diff --git a/src/c/test/sessions/demosession/DemoSession.c b/src/c/test/sessions/demosession/DemoSession.c index 07fdb95..904c745 100644 --- a/src/c/test/sessions/demosession/DemoSession.c +++ b/src/c/test/sessions/demosession/DemoSession.c @@ -11,7 +11,7 @@ int main(int argc, char **argv) jint res; jclass cls; jmethodID mid; - jstring jstr; + //jstring jstr; jobjectArray main_args; //vm_args.version = JNI_V @@ -37,7 +37,7 @@ int main(int argc, char **argv) return 1; } - jstr = (*env)->NewStringUTF(env, ""); + jstring jstr = (*env)->NewStringUTF(env, ""); main_args = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), jstr); (*env)->CallStaticVoidMethod(env, cls, mid, main_args); diff --git a/src/c/test/sessions/demosession/NativeSessionDemo.c b/src/c/test/sessions/demosession/NativeSessionDemo.c new file mode 100644 index 0000000..d530a07 --- /dev/null +++ b/src/c/test/sessions/demosession/NativeSessionDemo.c @@ -0,0 +1,13 @@ +#include +#include +//#include "messageapi_structs.h" +//#include "MessageApiSessionLib.h" + +int main(int argc, char **argv) +{ + printf("In our native session demo test!\n"); + printf("Hello, World\n"); + fflush(stdout); + + return 0; +} \ No newline at end of file diff --git a/src/c/test/sessions/demosession/compile.sh b/src/c/test/sessions/demosession/compile.sh new file mode 100755 index 0000000..8a314c2 --- /dev/null +++ b/src/c/test/sessions/demosession/compile.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +gcc NativeSessionDemo.c -I$(/usr/libexec/java_home)/include/ -I$(/usr/libexec/java_home)/include/darwin -L$(/usr/libexec/java_home)/jre/lib/jli -L$(/usr/libexec/java_home)/jre/lib/server/ -ljli -ljvm diff --git a/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c index 235f2d1..ad8319f 100644 --- a/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c +++ b/src/c/test/transformations/demotransformationlibrary/TransformationWrapper.c @@ -15,7 +15,7 @@ JNIEXPORT jobject JNICALL Java_gov_noaa_messageapi_transformations_NativeTransfo printf("In our transformation test!\n"); printf("Hello, World\n"); fflush(stdout); - struct record_list *records = getRecords(message, "test_key"); + record_list *records = getRecords(message, "test_key"); printf("Record count: %d\n", records->count); fflush(stdout); return records->jrecords; diff --git a/src/cpp/main/common/MessageApiEndpointLib.cpp b/src/cpp/main/common/MessageApiEndpointLib.cpp index f3e9cb8..8eceb33 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.cpp +++ b/src/cpp/main/common/MessageApiEndpointLib.cpp @@ -25,718 +25,718 @@ JNIEXPORT void JNICALL Java_gov_noaa_messageapi_endpoints_NativeEndpoint_release extern "C" { - struct record *getStateContainer(jlong message) + record *getStateContainer(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->getStateContainer(); } - struct field_list *getDefaultFields(jlong message) + field_list *getDefaultFields(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->getDefaultFields(); } - struct val_map *getConstructor(jlong message) + val_map *getConstructor(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->getConstructor(); } - struct packet *createPacket(jlong message) + packet *createPacket(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->createPacket(); } - struct record *createRecord(jlong message) + record *createRecord(jlong message) { return reinterpret_cast(message)->getEndpointUtils()->createRecord(); } - struct rejection *createRejection(jlong message, struct record *record, const char *reason) + rejection *createRejection(jlong message, record *record, const char *reason) { return reinterpret_cast(message)->getEndpointUtils()->createRejection(record, reason); } - struct record_list *getRecords(jlong message) + record_list *getRecords(jlong message) { return reinterpret_cast(message)->getProtocolRecordUtils()->getRecords("getRecords"); } - struct record_list *getRecordsByCollection(jlong message, const char *collectionId) + record_list *getRecordsByCollection(jlong message, const char *collectionId) { return reinterpret_cast(message)->getProtocolRecordUtils()->getRecords("getRecordsByCollection", collectionId); } - struct record_list *getRecordsByTransformation(jlong message, const char *transformationId) + record_list *getRecordsByTransformation(jlong message, const char *transformationId) { return reinterpret_cast(message)->getProtocolRecordUtils()->getRecords("getRecordsByTransformation", transformationId); } - struct record_list *getRecordsByUUID(jlong message, const char *uuid) + record_list *getRecordsByUUID(jlong message, const char *uuid) { return reinterpret_cast(message)->getProtocolRecordUtils()->getRecords("getRecordsByUUID", uuid); } - struct record_list *getRecordsByClassifier(jlong message, const char *classifierKey, const char *classifierValue) + record_list *getRecordsByClassifier(jlong message, const char *classifierKey, const char *classifierValue) { return reinterpret_cast(message)->getProtocolRecordUtils()->getRecords("getRecordsByClassifier", classifierKey, classifierValue); } - struct record_list *createRecordList(jlong message) + record_list *createRecordList(jlong message) { return reinterpret_cast(message)->getRecordUtils()->createRecordList(); } - void addRecord(jlong message, struct record_list *record_list, struct record *record) + void addRecord(jlong message, record_list *record_list, record *record) { return reinterpret_cast(message)->getRecordUtils()->addRecord(record_list, record); } - struct record *getRecord(jlong message, struct record_list *recordList, int recordIndex) + record *getRecord(jlong message, record_list *recordList, int recordIndex) { return reinterpret_cast(message)->getRecordUtils()->getRecord(recordList, recordIndex); } - struct record *getRecordCopy(jlong message, struct record *record) + record *getRecordCopy(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getCopy(record); } - bool getRecordIsValid(jlong message, struct record *record) + bool getRecordIsValid(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->isValid(record); } - struct string_list *getFieldIds(jlong message, struct record *record) + string_list *getFieldIds(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getFieldIds(record); } - struct field_list *getFields(jlong message, struct record *record) + field_list *getFields(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getFields(record); } - struct field *getField(jlong message, struct record *record, const char* fieldId) + field *getField(jlong message, record *record, const char* fieldId) { return reinterpret_cast(message)->getRecordUtils()->getField(record, fieldId); } - bool hasField(jlong message, struct record *record, const char *fieldId) + bool hasField(jlong message, record *record, const char *fieldId) { return reinterpret_cast(message)->getRecordUtils()->hasField(record, fieldId); } - struct string_list *getConditionIds(jlong message, struct record *record) + string_list *getConditionIds(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getConditionIds(record); } - struct condition_list *getConditions(jlong message, struct record *record) + condition_list *getConditions(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getConditions(record); } - struct condition *getCondition(jlong message, struct record *record, const char *conditionId) + condition *getCondition(jlong message, record *record, const char *conditionId) { return reinterpret_cast(message)->getRecordUtils()->getCondition(record, conditionId); } - bool hasCondition(jlong message, struct record *record, const char *conditionId) + bool hasCondition(jlong message, record *record, const char *conditionId) { return reinterpret_cast(message)->getRecordUtils()->hasCondition(record, conditionId); } /*Field Methods*/ - const char *getFieldId(jlong message, struct field *field) + const char *getFieldId(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getId(field); } - const char *getFieldType(jlong message, struct field *field) + const char *getFieldType(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getType(field); } - bool getFieldIsValid(jlong message, struct field *field) + bool getFieldIsValid(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isValid(field); } - bool getFieldIsRequired(jlong message, struct field *field) + bool getFieldIsRequired(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isRequired(field); } - bool getFieldIsNull(jlong message, struct field *field) + bool getFieldIsNull(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isNull(field); } - struct val *getFieldVal(jlong message, struct field *field) + val *getFieldVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getVal(field); } - int getFieldIntVal(jlong message, struct field *field) + int getFieldIntVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getIntVal(field); } - long getFieldLongVal(jlong message, struct field *field) + long getFieldLongVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getLongVal(field); } - float getFieldFloatVal(jlong message, struct field *field) + float getFieldFloatVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getFloatVal(field); } - double getFieldDoubleVal(jlong message, struct field *field) + double getFieldDoubleVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getDoubleVal(field); } - signed char getFieldByteVal(jlong message, struct field *field) + signed char getFieldByteVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getByteVal(field); } - const char *getFieldStringVal(jlong message, struct field *field) + const char *getFieldStringVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getStringVal(field); } - bool getFieldBoolVal(jlong message, struct field *field) + bool getFieldBoolVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getBoolVal(field); } - short getFieldShortVal(jlong message, struct field *field) + short getFieldShortVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getShortVal(field); } - struct val_list *getFieldListVal(jlong message, struct field *field) + val_list *getFieldListVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getListVal(field); } - struct val_map *getFieldMapVal(jlong message, struct field *field) + val_map *getFieldMapVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getMapVal(field); } - void setFieldVal(jlong message, struct field *field, struct val *value) + void setFieldVal(jlong message, field *field, val *value) { return reinterpret_cast(message)->getFieldUtils()->setVal(field, value); } - void setFieldIntVal(jlong message, struct field *field, int value) + void setFieldIntVal(jlong message, field *field, int value) { return reinterpret_cast(message)->getFieldUtils()->setIntVal(field, value); } - void setFieldLongVal(jlong message, struct field *field, long value) + void setFieldLongVal(jlong message, field *field, long value) { return reinterpret_cast(message)->getFieldUtils()->setLongVal(field, value); } - void setFieldFloatVal(jlong message, struct field *field, float value) + void setFieldFloatVal(jlong message, field *field, float value) { return reinterpret_cast(message)->getFieldUtils()->setFloatVal(field, value); } - void setFieldDoubleVal(jlong message, struct field *field, double value) + void setFieldDoubleVal(jlong message, field *field, double value) { return reinterpret_cast(message)->getFieldUtils()->setDoubleVal(field, value); } - void setFieldByteVal(jlong message, struct field *field, signed char value) + void setFieldByteVal(jlong message, field *field, signed char value) { return reinterpret_cast(message)->getFieldUtils()->setByteVal(field, value); } - void setFieldStringVal(jlong message, struct field *field, const char *value) + void setFieldStringVal(jlong message, field *field, const char *value) { return reinterpret_cast(message)->getFieldUtils()->setStringVal(field, value); } - void setFieldBoolVal(jlong message, struct field *field, bool value) + void setFieldBoolVal(jlong message, field *field, bool value) { return reinterpret_cast(message)->getFieldUtils()->setBoolVal(field, value); } - void setFieldShortVal(jlong message, struct field *field, short value) + void setFieldShortVal(jlong message, field *field, short value) { return reinterpret_cast(message)->getFieldUtils()->setShortVal(field, value); } - void setFieldListVal(jlong message, struct field *field, struct val_list *value) + void setFieldListVal(jlong message, field *field, val_list *value) { return reinterpret_cast(message)->getFieldUtils()->setListVal(field, value); } - void setFieldMapVal(jlong message, struct field *field, struct val_map *value) + void setFieldMapVal(jlong message, field *field, val_map *value) { return reinterpret_cast(message)->getFieldUtils()->setMapVal(field, value); } /*Condition Methods*/ - const char *getConditionId(jlong message, struct condition *condition) + const char *getConditionId(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getId(condition); } - const char *getConditionType(jlong message, struct condition *condition) + const char *getConditionType(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getType(condition); } - const char *getConditionOperator(jlong message, struct condition *condition) + const char *getConditionOperator(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getOperator(condition); } - bool getConditionIsNull(jlong message, struct condition *condition) + bool getConditionIsNull(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->isNull(condition); } - struct val *getConditionVal(jlong message, struct condition *condition) + val *getConditionVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getVal(condition); } - int getConditionIntVal(jlong message, struct condition *condition) + int getConditionIntVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getIntVal(condition); } - long getConditionLongVal(jlong message, struct condition *condition) + long getConditionLongVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getLongVal(condition); } - float getConditionFloatVal(jlong message, struct condition *condition) + float getConditionFloatVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getFloatVal(condition); } - double getConditionDoubleVal(jlong message, struct condition *condition) + double getConditionDoubleVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getDoubleVal(condition); } - signed char getConditionByteVal(jlong message, struct condition *condition) + signed char getConditionByteVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getByteVal(condition); } - const char *getConditionStringVal(jlong message, struct condition *condition) + const char *getConditionStringVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getStringVal(condition); } - bool getConditionBoolVal(jlong message, struct condition *condition) + bool getConditionBoolVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getBoolVal(condition); } - short getConditionShortVal(jlong message, struct condition *condition) + short getConditionShortVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getShortVal(condition); } - struct val_list *getConditionListVal(jlong message, struct condition *condition) + val_list *getConditionListVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getListVal(condition); } - struct val_map *getConditionMapVal(jlong message, struct condition *condition) + val_map *getConditionMapVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getMapVal(condition); } - void setConditionVal(jlong message, struct condition *condition, struct val *value) + void setConditionVal(jlong message, condition *condition, val *value) { return reinterpret_cast(message)->getConditionUtils()->setVal(condition, value); } - void setConditionIntVal(jlong message, struct condition *condition, int value) + void setConditionIntVal(jlong message, condition *condition, int value) { return reinterpret_cast(message)->getConditionUtils()->setIntVal(condition, value); } - void setConditionLongVal(jlong message, struct condition *condition, long value) + void setConditionLongVal(jlong message, condition *condition, long value) { return reinterpret_cast(message)->getConditionUtils()->setLongVal(condition, value); } - void setConditionFloatVal(jlong message, struct condition *condition, float value) + void setConditionFloatVal(jlong message, condition *condition, float value) { return reinterpret_cast(message)->getConditionUtils()->setFloatVal(condition, value); } - void setConditionDoubleVal(jlong message, struct condition *condition, double value) + void setConditionDoubleVal(jlong message, condition *condition, double value) { return reinterpret_cast(message)->getConditionUtils()->setDoubleVal(condition, value); } - void setConditionByteVal(jlong message, struct condition *condition, signed char value) + void setConditionByteVal(jlong message, condition *condition, signed char value) { return reinterpret_cast(message)->getConditionUtils()->setByteVal(condition, value); } - void setConditionStringVal(jlong message, struct condition *condition, const char *value) + void setConditionStringVal(jlong message, condition *condition, const char *value) { return reinterpret_cast(message)->getConditionUtils()->setStringVal(condition, value); } - void setConditionBoolVal(jlong message, struct condition *condition, bool value) + void setConditionBoolVal(jlong message, condition *condition, bool value) { return reinterpret_cast(message)->getConditionUtils()->setBoolVal(condition, value); } - void setConditionShortVal(jlong message, struct condition *condition, short value) + void setConditionShortVal(jlong message, condition *condition, short value) { return reinterpret_cast(message)->getConditionUtils()->setShortVal(condition, value); } - void setConditionListVal(jlong message, struct condition *condition, struct val_list *value) + void setConditionListVal(jlong message, condition *condition, val_list *value) { return reinterpret_cast(message)->getConditionUtils()->setListVal(condition, value); } - void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value) + void setConditionMapVal(jlong message, condition *condition, val_map *value) { return reinterpret_cast(message)->getConditionUtils()->setMapVal(condition, value); } /*List Utility Methods*/ - struct list_item *getItem(jlong message, struct val_list *list, int index) + list_item *getItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getItem(list, index); } - struct val_list *getListItem(jlong message, struct val_list *list, int index) + val_list *getListItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getListItem(list, index); } - struct val_map *getMapItem(jlong message, struct val_list *list, int index) + val_map *getMapItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getMapItem(list, index); } - int getIntItem(jlong message, struct val_list *list, int index) + int getIntItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getIntItem(list, index); } - long getLongItem(jlong message, struct val_list *list, int index) + long getLongItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getLongItem(list, index); } - float getFloatItem(jlong message, struct val_list *list, int index) + float getFloatItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getFloatItem(list, index); } - double getDoubleItem(jlong message, struct val_list *list, int index) + double getDoubleItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getDoubleItem(list, index); } - signed char getByteItem(jlong message, struct val_list *list, int index) + signed char getByteItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getByteItem(list, index); } - const char *getStringItem(jlong message, struct val_list *list, int index) + const char *getStringItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getStringItem(list, index); } - bool getBoolItem(jlong message, struct val_list *list, int index) + bool getBoolItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getBoolItem(list, index); } - short getShortItem(jlong message, struct val_list *list, int index) + short getShortItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getShortItem(list, index); } - struct val_list *createList(jlong message) + val_list *createList(jlong message) { return reinterpret_cast(message)->getListUtils()->createList(); } - void addItem(jlong message, struct val_list *list, struct list_item *item) + void addItem(jlong message, val_list *list, list_item *item) { return reinterpret_cast(message)->getListUtils()->addItem(list, item); } - void addIntItem(jlong message, struct val_list *list, int val) + void addIntItem(jlong message, val_list *list, int val) { return reinterpret_cast(message)->getListUtils()->addIntItem(list, val); } - void addLongItem(jlong message, struct val_list *list, long val) + void addLongItem(jlong message, val_list *list, long val) { return reinterpret_cast(message)->getListUtils()->addLongItem(list, val); } - void addFloatItem(jlong message, struct val_list *list, float val) + void addFloatItem(jlong message, val_list *list, float val) { return reinterpret_cast(message)->getListUtils()->addFloatItem(list, val); } - void addDoubleItem(jlong message, struct val_list *list, double val) + void addDoubleItem(jlong message, val_list *list, double val) { return reinterpret_cast(message)->getListUtils()->addDoubleItem(list, val); } - void addByteItem(jlong message, struct val_list *list, signed char val) + void addByteItem(jlong message, val_list *list, signed char val) { return reinterpret_cast(message)->getListUtils()->addByteItem(list, val); } - void addStringItem(jlong message, struct val_list *list, const char *val) + void addStringItem(jlong message, val_list *list, const char *val) { return reinterpret_cast(message)->getListUtils()->addStringItem(list, val); } - void addBoolItem(jlong message, struct val_list *list, bool val) + void addBoolItem(jlong message, val_list *list, bool val) { return reinterpret_cast(message)->getListUtils()->addBoolItem(list, val); } - void addShortItem(jlong message, struct val_list *list, short val) + void addShortItem(jlong message, val_list *list, short val) { return reinterpret_cast(message)->getListUtils()->addShortItem(list, val); } - void addListItem(jlong message, struct val_list *list, struct val_list *val) + void addListItem(jlong message, val_list *list, val_list *val) { return reinterpret_cast(message)->getListUtils()->addListItem(list, val); } - void addMapItem(jlong message, struct val_list *list, struct val_map *val) + void addMapItem(jlong message, val_list *list, val_map *val) { return reinterpret_cast(message)->getListUtils()->addMapItem(list, val); } /*Map Utility Methods*/ - struct val_map *createMap(jlong message) + val_map *createMap(jlong message) { return reinterpret_cast(message)->getMapUtils()->createMap(); } - int getSize(jlong message, struct val_map *map) + int getSize(jlong message, val_map *map) { return reinterpret_cast(message)->getMapUtils()->getSize(map); } - bool hasKey(jlong message, struct val_map *map, const char *key) + bool hasKey(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->hasKey(map, key); } /*Map Value Retrieval Methods*/ - struct map_val *getVal(jlong message, struct val_map *map, const char *key) + map_val *getVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getVal(map, key); } - jobject getObjectVal(jlong message, struct val_map *map, const char *key) + jobject getObjectVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getObjectVal(map, key); } - int getIntVal(jlong message, struct val_map *map, const char *key) + int getIntVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getIntVal(map, key); } - long getLongVal(jlong message, struct val_map *map, const char *key) + long getLongVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getLongVal(map, key); } - float getFloatVal(jlong message, struct val_map *map, const char *key) + float getFloatVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getFloatVal(map, key); } - double getDoubleVal(jlong message, struct val_map *map, const char *key) + double getDoubleVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getDoubleVal(map, key); } - signed char getByteVal(jlong message, struct val_map *map, const char *key) + signed char getByteVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getByteVal(map, key); } - const char *getStringVal(jlong message, struct val_map *map, const char *key) + const char *getStringVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getStringVal(map, key); } - bool getBoolVal(jlong message, struct val_map *map, const char *key) + bool getBoolVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getBoolVal(map, key); } - short getShortVal(jlong message, struct val_map *map, const char *key) + short getShortVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getShortVal(map, key); } - struct val_list *getListVal(jlong message, struct val_map *map, const char *key) + val_list *getListVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getListVal(map, key); } - struct val_map *getMapVal(jlong message, struct val_map *map, const char *key) + val_map *getMapVal(jlong message, val_map *map, const char *key) { return reinterpret_cast(message)->getMapUtils()->getMapVal(map, key); } /*Insert or Update Methods*/ - void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val) + void putVal(jlong message, val_map *map, const char *key, map_val *val) { return reinterpret_cast(message)->getMapUtils()->putVal(map, key, val); } - void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val) + void putObjectVal(jlong message, val_map *map, const char *key, jobject val) { return reinterpret_cast(message)->getMapUtils()->putObjectVal(map, key, val); } - void putIntVal(jlong message, struct val_map *map, const char *key, int val) + void putIntVal(jlong message, val_map *map, const char *key, int val) { return reinterpret_cast(message)->getMapUtils()->putIntVal(map, key, val); } - void putLongVal(jlong message, struct val_map *map, const char *key, long val) + void putLongVal(jlong message, val_map *map, const char *key, long val) { return reinterpret_cast(message)->getMapUtils()->putLongVal(map, key, val); } - void putFloatVal(jlong message, struct val_map *map, const char *key, float val) + void putFloatVal(jlong message, val_map *map, const char *key, float val) { return reinterpret_cast(message)->getMapUtils()->putFloatVal(map, key, val); } - void putDoubleVal(jlong message, struct val_map *map, const char *key, double val) + void putDoubleVal(jlong message, val_map *map, const char *key, double val) { return reinterpret_cast(message)->getMapUtils()->putDoubleVal(map, key, val); } - void putByteVal(jlong message, struct val_map *map, const char *key, signed char val) + void putByteVal(jlong message, val_map *map, const char *key, signed char val) { return reinterpret_cast(message)->getMapUtils()->putByteVal(map, key, val); } - void putStringVal(jlong message, struct val_map *map, const char *key, const char *val) + void putStringVal(jlong message, val_map *map, const char *key, const char *val) { return reinterpret_cast(message)->getMapUtils()->putStringVal(map, key, val); } - void putBoolVal(jlong message, struct val_map *map, const char *key, bool val) + void putBoolVal(jlong message, val_map *map, const char *key, bool val) { return reinterpret_cast(message)->getMapUtils()->putBoolVal(map, key, val); } - void putShortVal(jlong message, struct val_map *map, const char *key, short val) + void putShortVal(jlong message, val_map *map, const char *key, short val) { return reinterpret_cast(message)->getMapUtils()->putShortVal(map, key, val); } - void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val) + void putListVal(jlong message, val_map *map, const char *key, val_list *val) { return reinterpret_cast(message)->getMapUtils()->putListVal(map, key, val); } - void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val) + void putMapVal(jlong message, val_map *map, const char *key, val_map *val) { return reinterpret_cast(message)->getMapUtils()->putMapVal(map, key, val); } /*Rejection Utils*/ - struct rejection_list *createRejectionList(jlong message) + rejection_list *createRejectionList(jlong message) { return reinterpret_cast(message)->getRejectionUtils()->createRejectionList(); } - void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection) + void addRejection(jlong message, rejection_list *rejection_list, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->addRejection(rejection_list, rejection); } - struct rejection *getRejectionCopy(jlong message, struct rejection *rejection) + rejection *getRejectionCopy(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getCopy(rejection); } - struct record *getRejectionRecord(jlong message, struct rejection *rejection) + record *getRejectionRecord(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getRecord(rejection); } - struct string_list *getRejectionReasons(jlong message, struct rejection *rejection) + string_list *getRejectionReasons(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getReasons(rejection); } - void addRejectionReason(jlong message, struct rejection *rejection, const char *reason) + void addRejectionReason(jlong message, rejection *rejection, const char *reason) { return reinterpret_cast(message)->getRejectionUtils()->addReason(rejection, reason); } /*Packet Utils*/ - void addPacketRecord(jlong message, struct packet *packet, struct record *record) + void addPacketRecord(jlong message, packet *packet, record *record) { return reinterpret_cast(message)->getPacketUtils()->addRecord(packet, record); } - void setPacketRecords(jlong message, struct packet *packet, struct record_list *records) + void setPacketRecords(jlong message, packet *packet, record_list *records) { return reinterpret_cast(message)->getPacketUtils()->setRecords(packet, records); } - void addPacketRecords(jlong message, struct packet *packet, struct record_list *records) + void addPacketRecords(jlong message, packet *packet, record_list *records) { return reinterpret_cast(message)->getPacketUtils()->addRecords(packet, records); } - void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + void setPacketRejections(jlong message, packet *packet, rejection_list *rejections) { return reinterpret_cast(message)->getPacketUtils()->setRejections(packet, rejections); } - void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection) + void addPacketRejection(jlong message, packet *packet, rejection *rejection) { return reinterpret_cast(message)->getPacketUtils()->addRejection(packet, rejection); } - void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + void addPacketRejections(jlong message, packet *packet, rejection_list *rejections) { return reinterpret_cast(message)->getPacketUtils()->addRejections(packet, rejections); } - struct record_list *getPacketRecords(jlong message, struct packet *packet) + record_list *getPacketRecords(jlong message, packet *packet) { return reinterpret_cast(message)->getPacketUtils()->getRecords(packet); } - struct rejection_list *getPacketRejections(jlong message, struct packet *packet) + rejection_list *getPacketRejections(jlong message, packet *packet) { return reinterpret_cast(message)->getPacketUtils()->getRejections(packet); } diff --git a/src/cpp/main/common/MessageApiEndpointLib.h b/src/cpp/main/common/MessageApiEndpointLib.h index 5111a9a..7cc713f 100644 --- a/src/cpp/main/common/MessageApiEndpointLib.h +++ b/src/cpp/main/common/MessageApiEndpointLib.h @@ -12,174 +12,174 @@ extern "C" #endif /*Endpoint Methods*/ - struct record *getStateContainer(jlong message); - struct field_list *getDefaultFields(jlong message); - struct val_map *getConstructor(jlong message); - struct packet *createPacket(jlong message); - struct record *createRecord(jlong message); - struct rejection *createRejection(jlong message, struct record *record, const char *reason); + record *getStateContainer(jlong message); + field_list *getDefaultFields(jlong message); + val_map *getConstructor(jlong message); + packet *createPacket(jlong message); + record *createRecord(jlong message); + rejection *createRejection(jlong message, record *record, const char *reason); /*Protocol Record Methods*/ - struct record_list *getRecords(jlong message); - struct record_list *getRecordsByCollection(jlong message, const char *collection); - struct record_list *getRecordsByTransformation(jlong message, const char *transformation); - struct record_list *getRecordsByUUID(jlong message, const char *uuid); - struct record_list *getRecordsByClassifier(jlong message, const char *key, const char *value); - struct record *getRecord(jlong message, struct record_list *recordList, int recordIndex); + record_list *getRecords(jlong message); + record_list *getRecordsByCollection(jlong message, const char *collection); + record_list *getRecordsByTransformation(jlong message, const char *transformation); + record_list *getRecordsByUUID(jlong message, const char *uuid); + record_list *getRecordsByClassifier(jlong message, const char *key, const char *value); + record *getRecord(jlong message, record_list *recordList, int recordIndex); /*Record Methods*/ - struct record_list *createRecordList(jlong message); - void addRecord(jlong message, struct record_list *record_list, struct record *record); + record_list *createRecordList(jlong message); + void addRecord(jlong message, record_list *record_list, record *record); - struct record *getRecordCopy(jlong message, struct record *record); - bool getRecordIsValid(jlong message, struct record *record); + record *getRecordCopy(jlong message, record *record); + bool getRecordIsValid(jlong message, record *record); - struct string_list *getFieldIds(jlong message, struct record *record); - struct field_list * getFields(jlong message, struct record *record); - struct field * getField(jlong message, struct record *record, const char *fieldId); - bool hasField(jlong message, struct record *record, const char *fieldId); + string_list *getFieldIds(jlong message, record *record); + field_list * getFields(jlong message, record *record); + field * getField(jlong message, record *record, const char *fieldId); + bool hasField(jlong message, record *record, const char *fieldId); - struct string_list *getConditionIds(jlong message, struct record *record); - struct condition_list *getConditions(jlong message, struct record *record); - struct condition *getCondition(jlong message, struct record *record, const char *conditionId); - bool hasCondition(jlong message, struct record *record, const char *conditionId); + string_list *getConditionIds(jlong message, record *record); + condition_list *getConditions(jlong message, record *record); + condition *getCondition(jlong message, record *record, const char *conditionId); + bool hasCondition(jlong message, record *record, const char *conditionId); /*Rejection Methods*/ - struct rejection_list *createRejectionList(jlong message); - void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection); - struct rejection *getRejectionCopy(jlong message, struct rejection *rejection); - struct record *getRejectionRecord(jlong message, struct rejection *rejection); - struct string_list *getRejectionReasons(jlong message, struct rejection *rejection); - void addRejectionReason(jlong message, struct rejection *rejection, const char *reason); + rejection_list *createRejectionList(jlong message); + void addRejection(jlong message, rejection_list *rejection_list, rejection *rejection); + rejection *getRejectionCopy(jlong message, rejection *rejection); + record *getRejectionRecord(jlong message, rejection *rejection); + string_list *getRejectionReasons(jlong message, rejection *rejection); + void addRejectionReason(jlong message, rejection *rejection, const char *reason); /*Field Methods*/ - const char *getFieldId(jlong message, struct field *field); - const char * getFieldType(jlong message, struct field *field); - bool getFieldIsValid(jlong message, struct field *field); - bool getFieldIsRequired(jlong message, struct field *field); - bool getFieldIsNull(jlong message, struct field *field); + const char *getFieldId(jlong message, field *field); + const char * getFieldType(jlong message, field *field); + bool getFieldIsValid(jlong message, field *field); + bool getFieldIsRequired(jlong message, field *field); + bool getFieldIsNull(jlong message, field *field); - struct val *getFieldVal(jlong message, struct field *field); - int getFieldIntVal(jlong message, struct field *field); - long getFieldLongVal(jlong message, struct field *field); - float getFieldFloatVal(jlong message, struct field *field); - double getFieldDoubleVal(jlong message, struct field *field); - signed char getFieldByteVal(jlong message, struct field *field); - const char *getFieldStringVal(jlong message, struct field *field); - bool getFieldBoolVal(jlong message, struct field *field); - short getFieldShortVal(jlong message, struct field *field); - struct val_list *getFieldListVal(jlong message, struct field *field); - struct val_map *getFieldMapVal(jlong message, struct field *field); - - void setFieldVal(jlong message, struct field *field, struct val *value); - void setFieldIntVal(jlong message, struct field *field, int value); - void setFieldLongVal(jlong message, struct field *field, long value); - void setFieldFloatVal(jlong message, struct field *field, float value); - void setFieldDoubleVal(jlong message, struct field *field, double value); - void setFieldByteVal(jlong message, struct field *field, signed char value); - void setFieldStringVal(jlong message, struct field *field, const char *value); - void setFieldBoolVal(jlong message, struct field *field, bool value); - void setFieldShortVal(jlong message, struct field *field, short value); - void setFieldListVal(jlong message, struct field *field, struct val_list *value); - void setFieldMapVal(jlong message, struct field *field, struct val_map *value); + val *getFieldVal(jlong message, field *field); + int getFieldIntVal(jlong message, field *field); + long getFieldLongVal(jlong message, field *field); + float getFieldFloatVal(jlong message, field *field); + double getFieldDoubleVal(jlong message, field *field); + signed char getFieldByteVal(jlong message, field *field); + const char *getFieldStringVal(jlong message, field *field); + bool getFieldBoolVal(jlong message, field *field); + short getFieldShortVal(jlong message, field *field); + val_list *getFieldListVal(jlong message, field *field); + val_map *getFieldMapVal(jlong message, field *field); + + void setFieldVal(jlong message, field *field, val *value); + void setFieldIntVal(jlong message, field *field, int value); + void setFieldLongVal(jlong message, field *field, long value); + void setFieldFloatVal(jlong message, field *field, float value); + void setFieldDoubleVal(jlong message, field *field, double value); + void setFieldByteVal(jlong message, field *field, signed char value); + void setFieldStringVal(jlong message, field *field, const char *value); + void setFieldBoolVal(jlong message, field *field, bool value); + void setFieldShortVal(jlong message, field *field, short value); + void setFieldListVal(jlong message, field *field, val_list *value); + void setFieldMapVal(jlong message, field *field, val_map *value); /*Condition Methods*/ - const char *getConditionId(jlong message, struct condition *condition); - const char *getConditionType(jlong message, struct condition *condition); - const char *getConditionOperator(jlong message, struct condition *condition); - bool getConditionIsNull(jlong message, struct condition *condition); - - struct val *getConditionVal(jlong message, struct condition *condition); - int getConditionIntVal(jlong message, struct condition *condition); - long getConditionLongVal(jlong message, struct condition *condition); - float getConditionFloatVal(jlong message, struct condition *condition); - double getConditionDoubleVal(jlong message, struct condition *condition); - signed char getConditionByteVal(jlong message, struct condition *condition); - const char *getConditionStringVal(jlong message, struct condition *condition); - bool getConditionBoolVal(jlong message, struct condition *condition); - short getConditionShortVal(jlong message, struct condition *condition); - struct val_list *getConditionListVal(jlong message, struct condition *condition); - struct val_map *getConditionMapVal(jlong message, struct condition *condition); - - void setConditionVal(jlong message, struct condition *condition, struct val *value); - void setConditionIntVal(jlong message, struct condition *condition, int value); - void setConditionLongVal(jlong message, struct condition *condition, long value); - void setConditionFloatVal(jlong message, struct condition *condition, float value); - void setConditionDoubleVal(jlong message, struct condition *condition, double value); - void setConditionByteVal(jlong message, struct condition *condition, signed char value); - void setConditionStringVal(jlong message, struct condition *condition, const char *value); - void setConditionBoolVal(jlong message, struct condition *condition, bool value); - void setConditionShortVal(jlong message, struct condition *condition, short value); - void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); - void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value); + const char *getConditionId(jlong message, condition *condition); + const char *getConditionType(jlong message, condition *condition); + const char *getConditionOperator(jlong message, condition *condition); + bool getConditionIsNull(jlong message, condition *condition); + + val *getConditionVal(jlong message, condition *condition); + int getConditionIntVal(jlong message, condition *condition); + long getConditionLongVal(jlong message, condition *condition); + float getConditionFloatVal(jlong message, condition *condition); + double getConditionDoubleVal(jlong message, condition *condition); + signed char getConditionByteVal(jlong message, condition *condition); + const char *getConditionStringVal(jlong message, condition *condition); + bool getConditionBoolVal(jlong message, condition *condition); + short getConditionShortVal(jlong message, condition *condition); + val_list *getConditionListVal(jlong message, condition *condition); + val_map *getConditionMapVal(jlong message, condition *condition); + + void setConditionVal(jlong message, condition *condition, val *value); + void setConditionIntVal(jlong message, condition *condition, int value); + void setConditionLongVal(jlong message, condition *condition, long value); + void setConditionFloatVal(jlong message, condition *condition, float value); + void setConditionDoubleVal(jlong message, condition *condition, double value); + void setConditionByteVal(jlong message, condition *condition, signed char value); + void setConditionStringVal(jlong message, condition *condition, const char *value); + void setConditionBoolVal(jlong message, condition *condition, bool value); + void setConditionShortVal(jlong message, condition *condition, short value); + void setConditionListVal(jlong message, condition *condition, val_list *value); + void setConditionMapVal(jlong message, condition *condition, val_map *value); /*List Utility Methods*/ - int getIntItem(jlong message, struct val_list *list, int index); - long getLongItem(jlong message, struct val_list *list, int index); - float getFloatItem(jlong message, struct val_list *list, int index); - double getDoubleItem(jlong message, struct val_list *list, int index); - signed char getByteItem(jlong message, struct val_list *list, int index); - const char *getStringItem(jlong message, struct val_list *list, int index); - bool getBoolItem(jlong message, struct val_list *list, int index); - short getShortItem(jlong message, struct val_list *list, int index); - struct list_item *getItem(jlong message, struct val_list *list, int index); - struct val_list *getListItem(jlong message, struct val_list *list, int index); - struct val_map *getMapItem(jlong message, struct val_list *list, int index); - struct val_list *createList(jlong message); - void addItem(jlong message, struct val_list *list, struct list_item *item); - void addIntItem(jlong message, struct val_list *list, int val); - void addLongItem(jlong message, struct val_list *list, long val); - void addFloatItem(jlong message, struct val_list *list, float val); - void addDoubleItem(jlong message, struct val_list *list, double val); - void addByteItem(jlong message, struct val_list *list, signed char val); - void addStringItem(jlong message, struct val_list *list, const char *val); - void addBoolItem(jlong message, struct val_list *list, bool val); - void addShortItem(jlong message, struct val_list *list, short val); - void addListItem(jlong message, struct val_list *list, struct val_list *val); - void addMapItem(jlong message, struct val_list *list, struct val_map *map); + int getIntItem(jlong message, val_list *list, int index); + long getLongItem(jlong message, val_list *list, int index); + float getFloatItem(jlong message, val_list *list, int index); + double getDoubleItem(jlong message, val_list *list, int index); + signed char getByteItem(jlong message, val_list *list, int index); + const char *getStringItem(jlong message, val_list *list, int index); + bool getBoolItem(jlong message, val_list *list, int index); + short getShortItem(jlong message, val_list *list, int index); + list_item *getItem(jlong message, val_list *list, int index); + val_list *getListItem(jlong message, val_list *list, int index); + val_map *getMapItem(jlong message, val_list *list, int index); + val_list *createList(jlong message); + void addItem(jlong message, val_list *list, list_item *item); + void addIntItem(jlong message, val_list *list, int val); + void addLongItem(jlong message, val_list *list, long val); + void addFloatItem(jlong message, val_list *list, float val); + void addDoubleItem(jlong message, val_list *list, double val); + void addByteItem(jlong message, val_list *list, signed char val); + void addStringItem(jlong message, val_list *list, const char *val); + void addBoolItem(jlong message, val_list *list, bool val); + void addShortItem(jlong message, val_list *list, short val); + void addListItem(jlong message, val_list *list, val_list *val); + void addMapItem(jlong message, val_list *list, val_map *map); /*Map Utility Methods*/ - struct val_map *createMap(jlong message); - int getSize(jlong message, struct val_map *map); - bool hasKey(jlong message, struct val_map *map, const char *key); + val_map *createMap(jlong message); + int getSize(jlong message, val_map *map); + bool hasKey(jlong message, val_map *map, const char *key); /*Map Value Retrieval Methods*/ - struct map_val *getVal(jlong message, struct val_map *map, const char *key); - jobject getObjectVal(jlong message, struct val_map *map, const char *key); - int getIntVal(jlong message, struct val_map *map, const char *key); - long getLongVal(jlong message, struct val_map *map, const char *key); - float getFloatVal(jlong message, struct val_map *map, const char *key); - double getDoubleVal(jlong message, struct val_map *map, const char *key); - signed char getByteVal(jlong message, struct val_map *map, const char *key); - const char *getStringVal(jlong message, struct val_map *map, const char *key); - bool getBoolVal(jlong message, struct val_map *map, const char *key); - short getShortVal(jlong message, struct val_map *map, const char *key); - struct val_list *getListVal(jlong message, struct val_map *map, const char *key); - struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + map_val *getVal(jlong message, val_map *map, const char *key); + jobject getObjectVal(jlong message, val_map *map, const char *key); + int getIntVal(jlong message, val_map *map, const char *key); + long getLongVal(jlong message, val_map *map, const char *key); + float getFloatVal(jlong message, val_map *map, const char *key); + double getDoubleVal(jlong message, val_map *map, const char *key); + signed char getByteVal(jlong message, val_map *map, const char *key); + const char *getStringVal(jlong message, val_map *map, const char *key); + bool getBoolVal(jlong message, val_map *map, const char *key); + short getShortVal(jlong message, val_map *map, const char *key); + val_list *getListVal(jlong message, val_map *map, const char *key); + val_map *getMapVal(jlong message, val_map *map, const char *key); /*Insert or Update Methods*/ - void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); - void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); - void putIntVal(jlong message, struct val_map *map, const char *key, int val); - void putLongVal(jlong message, struct val_map *map, const char *key, long val); - void putFloatVal(jlong message, struct val_map *map, const char *key, float val); - void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); - void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); - void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); - void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); - void putShortVal(jlong message, struct val_map *map, const char *key, short val); - void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); - void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); + void putVal(jlong message, val_map *map, const char *key, map_val *val); + void putObjectVal(jlong message, val_map *map, const char *key, jobject val); + void putIntVal(jlong message, val_map *map, const char *key, int val); + void putLongVal(jlong message, val_map *map, const char *key, long val); + void putFloatVal(jlong message, val_map *map, const char *key, float val); + void putDoubleVal(jlong message, val_map *map, const char *key, double val); + void putByteVal(jlong message, val_map *map, const char *key, signed char val); + void putStringVal(jlong message, val_map *map, const char *key, const char *val); + void putBoolVal(jlong message, val_map *map, const char *key, bool val); + void putShortVal(jlong message, val_map *map, const char *key, short val); + void putListVal(jlong message, val_map *map, const char *key, val_list *val); + void putMapVal(jlong message, val_map *map, const char *key, val_map *val); /*Packet Methods*/ - void addPacketRecord(jlong message, struct packet *packet, struct record *record); - void setPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void addPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection); - void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - struct record_list *getPacketRecords(jlong message, struct packet *packet); - struct rejection_list *getPacketRejections(jlong message, struct packet *packet); + void addPacketRecord(jlong message, packet *packet, record *record); + void setPacketRecords(jlong message, packet *packet, record_list *records); + void addPacketRecords(jlong message, packet *packet, record_list *records); + void setPacketRejections(jlong message, packet *packet, rejection_list *rejections); + void addPacketRejection(jlong message, packet *packet, rejection *rejection); + void addPacketRejections(jlong message, packet *packet, rejection_list *rejections); + record_list *getPacketRecords(jlong message, packet *packet); + rejection_list *getPacketRejections(jlong message, packet *packet); #ifdef __cplusplus } diff --git a/src/cpp/main/common/MessageApiSession.cpp b/src/cpp/main/common/MessageApiSession.cpp new file mode 100644 index 0000000..fba52ec --- /dev/null +++ b/src/cpp/main/common/MessageApiSession.cpp @@ -0,0 +1,111 @@ +#include "MessageApiSession.h" + +#include +#include +#include +#include +#include +#include + +/** +Constructor for the MessageApiEndpoint object. Takes a JNI environment pointer, an endpoint context (this refers to +the endpoint class that's instantiating the object), and a protocol record which holds containers of records. +*/ +MessageApiSession::MessageApiSession(JNIEnv *env, jobject session) +{ + this->jvm = env; + this->session = this->jvm->NewGlobalRef(session); + + this->typeUtils = new TypeUtils(this->jvm); + this->listUtils = new ListUtils(this->jvm, typeUtils); + this->mapUtils = new MapUtils(this->jvm, typeUtils); + this->sessionUtils = new SessionUtils(this->jvm, this->session); + this->requestUtils = new RequestUtils(this->jvm, this->typeUtils, this->listUtils); + this->responseUtils = new ResponseUtils(this->jvm, this->typeUtils, this->listUtils); + this->recordUtils = new RecordUtils(this->jvm, this->typeUtils, this->listUtils); + this->rejectionUtils = new RejectionUtils(this->jvm, this->typeUtils, this->listUtils); + this->fieldUtils = new FieldUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); + this->conditionUtils = new ConditionUtils(this->jvm, this->typeUtils, this->listUtils, this->mapUtils); + this->packetUtils = new PacketUtils(this->jvm, this->listUtils); +} + +MessageApiSession::~MessageApiSession() +{ + try + { + delete this->sessionUtils; + delete this->requestUtils; + delete this->responseUtils; + delete this->recordUtils; + delete this->rejectionUtils; + delete this->fieldUtils; + delete this->conditionUtils; + delete this->packetUtils; + delete this->listUtils; + delete this->mapUtils; + delete this->typeUtils; + this->jvm->DeleteGlobalRef(this->session); + } + catch (const std::exception &e) + { + std::cout << e.what(); + } +} + +SessionUtils *MessageApiSession::getSessionUtils() +{ + return this->sessionUtils; +} + +RequestUtils *MessageApiSession::getRequestUtils() +{ + return this->requestUtils; +} + +ResponseUtils *MessageApiSession::getResponseUtils() +{ + return this->responseUtils; +} + +RecordUtils *MessageApiSession::getRecordUtils() +{ + return this->recordUtils; +} + +RejectionUtils *MessageApiSession::getRejectionUtils() +{ + return this->rejectionUtils; +} + +FieldUtils *MessageApiSession::getFieldUtils() +{ + return this->fieldUtils; +} + +ConditionUtils *MessageApiSession::getConditionUtils() +{ + return this->conditionUtils; +} + +PacketUtils *MessageApiSession::getPacketUtils() +{ + return this->packetUtils; +} + +ListUtils *MessageApiSession::getListUtils() +{ + return this->listUtils; +} + +MapUtils *MessageApiSession::getMapUtils() +{ + return this->mapUtils; +} + +TypeUtils *MessageApiSession::getTypeUtils() +{ + return this->typeUtils; +} + + + diff --git a/src/cpp/main/common/MessageApiSession.h b/src/cpp/main/common/MessageApiSession.h new file mode 100644 index 0000000..719371a --- /dev/null +++ b/src/cpp/main/common/MessageApiSession.h @@ -0,0 +1,77 @@ +#ifndef _Included_MessageApiSession +#define _Included_MessageApiSession + +#include +#include +#include "messageapi_structs.h" + +#ifdef __cplusplus +#include +#include + +#include "JniUtils.h" +#include "MapUtils.h" +#include "ListUtils.h" +#include "SessionUtils.h" +#include "RequestUtils.h" +#include "ResponseUtils.h" +#include "RecordUtils.h" +#include "RejectionUtils.h" +#include "FieldUtils.h" +#include "ConditionUtils.h" +#include "PacketUtils.h" + +/** + * @author Ryan Berkheimer + */ +class MessageApiSession +{ + +public: + /*Default constructor*/ + MessageApiSession(JNIEnv *javaEnv, jobject jSession); + /*Default destructor*/ + ~MessageApiSession(); + + /*Utils Accessors*/ + SessionUtils *getSessionUtils(); + RequestUtils *getRequestUtils(); + ResponseUtils *getResponseUtils(); + RecordUtils *getRecordUtils(); + RejectionUtils *getRejectionUtils(); + FieldUtils *getFieldUtils(); + ConditionUtils *getConditionUtils(); + PacketUtils *getPacketUtils(); + ListUtils *getListUtils(); + MapUtils *getMapUtils(); + TypeUtils *getTypeUtils(); + +private : + /*Global References*/ + JNIEnv *jvm; + jobject session; + + SessionUtils *sessionUtils; + RequestUtils *requestUtils; + ResponseUtils *responseUtils; + RecordUtils *recordUtils; + RejectionUtils *rejectionUtils; + FieldUtils *fieldUtils; + ConditionUtils *conditionUtils; + PacketUtils *packetUtils; + TypeUtils *typeUtils; + ListUtils *listUtils; + MapUtils *mapUtils; + +}; + +extern "C" +{ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpp/main/common/MessageApiSessionLib.cpp b/src/cpp/main/common/MessageApiSessionLib.cpp new file mode 100644 index 0000000..bcdacc7 --- /dev/null +++ b/src/cpp/main/common/MessageApiSessionLib.cpp @@ -0,0 +1,788 @@ +#include "MessageApiSessionLib.h" + +extern "C" +{ + /** + * Creates the default session. + */ + session *createSession(const char *spec) + { + session *session; + JavaVM *vm; + JNIEnv *env; + JavaVMInitArgs vm_args; + + jint jvmCreationStatus = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); + if (jvmCreationStatus != JNI_OK) + { + printf("Failed to create Java VM\n"); + fflush(stdout); + return NULL; + } + + jclass sessionClass = JniUtils::getNamedClass(env, "gov/noaa/messageapi/sessions/DefaultSession"); + jmethodID createSessionMethodId = JniUtils::getMethod(env, sessionClass, "", "(Ljava/lang/String;)V", false); + jstring jSpec = env->NewStringUTF(spec); + jobject jSession = env->NewObject(sessionClass, createSessionMethodId); + jlong sessionLib = reinterpret_cast(new MessageApiSession(env, jSession)); + struct session *session = (struct session *)malloc(sizeof(session) + sizeof(sessionLib)); + session->sessionLib = sessionLib; + env->DeleteLocalRef(jSession); + env->DeleteLocalRef(jSpec); + env->DeleteLocalRef(sessionClass); + return session; + } + + /** + * Deletes the C++ pointer (calls C++ destructor)) that references the object created during session construction. + * This call is NOT made automatically, as the session is created Natively, so this should be called manually. + */ + void releaseSession(session *session) + { + delete reinterpret_cast(session->sessionLib); + free(session); + } + + request *createRequest(session *session) + { + return reinterpret_cast(session->sessionLib)->getSessionUtils()->createRequest(); + } + + /* Request methods */ + record *createRequestRecord(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->createRecord(request); + } + + request *getRequestCopy(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->getCopy(request); + } + + request *getRequestCopyComponents(session *session, request *request, val_list *copy_components) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->getCopy(request, copy_components); + } + + const char *getRequestType(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->getType(request); + } + + record_list *getRequestRecords(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->getRecords(request); + } + + record *getRequestRecord(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->getRequestRecord(request); + } + + void setRequestRecords(session *session, request *request, record_list *records) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->setRecords(request, records); + } + + response *submitRequest(session *session, request *request) + { + return reinterpret_cast(session->sessionLib)->getRequestUtils()->submitRequest(request); + } + + /* Response methods */ + bool isComplete(session *session, response *response) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->isComplete(response); + } + + request *getResponseRequest(session *session, response *response) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->getRequest(response); + } + + rejection_list *getResponseRejections(session *session, response *response) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->getRejections(response); + } + + record_list *getResponseRecords(session *session, response *response) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->getRecords(response); + } + + void setResponseRejections(session *session, response *response, rejection_list *rejections) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->setRejections(response, rejections); + } + + void setResponseRecords(session *session, response *response, record_list *records) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->setRecords(response, records); + } + + void setComplete(session *session, response *response, bool isComplete) + { + return reinterpret_cast(session->sessionLib)->getResponseUtils()->setComplete(response, isComplete); + } + + record_list *createRecordList(session *session) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->createRecordList(); + } + + void addRecord(session *session, record_list *record_list, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->addRecord(record_list, record); + } + + record *getRecord(session *session, record_list *recordList, int recordIndex) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getRecord(recordList, recordIndex); + } + + record *getRecordCopy(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getCopy(record); + } + + bool getRecordIsValid(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->isValid(record); + } + + string_list *getFieldIds(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getFieldIds(record); + } + + field_list *getFields(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getFields(record); + } + + field *getField(session *session, record *record, const char* fieldId) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getField(record, fieldId); + } + + bool hasField(session *session, record *record, const char *fieldId) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->hasField(record, fieldId); + } + + string_list *getConditionIds(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getConditionIds(record); + } + + condition_list *getConditions(session *session, record *record) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getConditions(record); + } + + condition *getCondition(session *session, record *record, const char *conditionId) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->getCondition(record, conditionId); + } + + bool hasCondition(session *session, record *record, const char *conditionId) + { + return reinterpret_cast(session->sessionLib)->getRecordUtils()->hasCondition(record, conditionId); + } + + /*Field Methods*/ + + const char *getFieldId(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getId(field); + } + + const char *getFieldType(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getType(field); + } + + bool getFieldIsValid(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->isValid(field); + } + + bool getFieldIsRequired(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->isRequired(field); + } + + bool getFieldIsNull(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->isNull(field); + } + + val *getFieldVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getVal(field); + } + + int getFieldIntVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getIntVal(field); + } + + long getFieldLongVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getLongVal(field); + } + + float getFieldFloatVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getFloatVal(field); + } + + double getFieldDoubleVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getDoubleVal(field); + } + + signed char getFieldByteVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getByteVal(field); + } + + const char *getFieldStringVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getStringVal(field); + } + + bool getFieldBoolVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getBoolVal(field); + } + + short getFieldShortVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getShortVal(field); + } + + val_list *getFieldListVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getListVal(field); + } + + val_map *getFieldMapVal(session *session, field *field) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->getMapVal(field); + } + + void setFieldVal(session *session, field *field, val *value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setVal(field, value); + } + + void setFieldIntVal(session *session, field *field, int value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setIntVal(field, value); + } + + void setFieldLongVal(session *session, field *field, long value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setLongVal(field, value); + } + + void setFieldFloatVal(session *session, field *field, float value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setFloatVal(field, value); + } + + void setFieldDoubleVal(session *session, field *field, double value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setDoubleVal(field, value); + } + + void setFieldByteVal(session *session, field *field, signed char value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setByteVal(field, value); + } + + void setFieldStringVal(session *session, field *field, const char *value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setStringVal(field, value); + } + + void setFieldBoolVal(session *session, field *field, bool value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setBoolVal(field, value); + } + + void setFieldShortVal(session *session, field *field, short value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setShortVal(field, value); + } + + void setFieldListVal(session *session, field *field, val_list *value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setListVal(field, value); + } + + void setFieldMapVal(session *session, field *field, val_map *value) + { + return reinterpret_cast(session->sessionLib)->getFieldUtils()->setMapVal(field, value); + } + + /*Condition Methods*/ + + const char *getConditionId(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getId(condition); + } + + const char *getConditionType(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getType(condition); + } + + const char *getConditionOperator(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getOperator(condition); + } + + bool getConditionIsNull(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->isNull(condition); + } + + val *getConditionVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getVal(condition); + } + + int getConditionIntVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getIntVal(condition); + } + + long getConditionLongVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getLongVal(condition); + } + + float getConditionFloatVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getFloatVal(condition); + } + + double getConditionDoubleVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getDoubleVal(condition); + } + + signed char getConditionByteVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getByteVal(condition); + } + + const char *getConditionStringVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getStringVal(condition); + } + + bool getConditionBoolVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getBoolVal(condition); + } + + short getConditionShortVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getShortVal(condition); + } + + val_list *getConditionListVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getListVal(condition); + } + + val_map *getConditionMapVal(session *session, condition *condition) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->getMapVal(condition); + } + + void setConditionVal(session *session, condition *condition, val *value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setVal(condition, value); + } + + void setConditionIntVal(session *session, condition *condition, int value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setIntVal(condition, value); + } + + void setConditionLongVal(session *session, condition *condition, long value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setLongVal(condition, value); + } + + void setConditionFloatVal(session *session, condition *condition, float value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setFloatVal(condition, value); + } + + void setConditionDoubleVal(session *session, condition *condition, double value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setDoubleVal(condition, value); + } + + void setConditionByteVal(session *session, condition *condition, signed char value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setByteVal(condition, value); + } + + void setConditionStringVal(session *session, condition *condition, const char *value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setStringVal(condition, value); + } + + void setConditionBoolVal(session *session, condition *condition, bool value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setBoolVal(condition, value); + } + + void setConditionShortVal(session *session, condition *condition, short value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setShortVal(condition, value); + } + + void setConditionListVal(session *session, condition *condition, val_list *value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setListVal(condition, value); + } + + void setConditionMapVal(session *session, condition *condition, val_map *value) + { + return reinterpret_cast(session->sessionLib)->getConditionUtils()->setMapVal(condition, value); + } + + /*List Utility Methods*/ + + list_item *getItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getItem(list, index); + } + + val_list *getListItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getListItem(list, index); + } + + val_map *getMapItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getMapItem(list, index); + } + + int getIntItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getIntItem(list, index); + } + + long getLongItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getLongItem(list, index); + } + + float getFloatItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getFloatItem(list, index); + } + + double getDoubleItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getDoubleItem(list, index); + } + + signed char getByteItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getByteItem(list, index); + } + + const char *getStringItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getStringItem(list, index); + } + + bool getBoolItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getBoolItem(list, index); + } + + short getShortItem(session *session, val_list *list, int index) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->getShortItem(list, index); + } + + val_list *createList(session *session) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->createList(); + } + + void addItem(session *session, val_list *list, list_item *item) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addItem(list, item); + } + + void addIntItem(session *session, val_list *list, int val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addIntItem(list, val); + } + + void addLongItem(session *session, val_list *list, long val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addLongItem(list, val); + } + + void addFloatItem(session *session, val_list *list, float val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addFloatItem(list, val); + } + + void addDoubleItem(session *session, val_list *list, double val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addDoubleItem(list, val); + } + + void addByteItem(session *session, val_list *list, signed char val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addByteItem(list, val); + } + + void addStringItem(session *session, val_list *list, const char *val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addStringItem(list, val); + } + + void addBoolItem(session *session, val_list *list, bool val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addBoolItem(list, val); + } + + void addShortItem(session *session, val_list *list, short val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addShortItem(list, val); + } + + void addListItem(session *session, val_list *list, val_list *val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addListItem(list, val); + } + + void addMapItem(session *session, val_list *list, val_map *val) + { + return reinterpret_cast(session->sessionLib)->getListUtils()->addMapItem(list, val); + } + + /*Map Utility Methods*/ + val_map *createMap(session *session) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->createMap(); + } + + int getSize(session *session, val_map *map) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getSize(map); + } + + bool hasKey(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->hasKey(map, key); + } + + /*Map Value Retrieval Methods*/ + map_val *getVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getVal(map, key); + } + + jobject getObjectVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getObjectVal(map, key); + } + + int getIntVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getIntVal(map, key); + } + + long getLongVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getLongVal(map, key); + } + + float getFloatVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getFloatVal(map, key); + } + + double getDoubleVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getDoubleVal(map, key); + } + + signed char getByteVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getByteVal(map, key); + } + + const char *getStringVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getStringVal(map, key); + } + + bool getBoolVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getBoolVal(map, key); + } + + short getShortVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getShortVal(map, key); + } + + val_list *getListVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getListVal(map, key); + } + + val_map *getMapVal(session *session, val_map *map, const char *key) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->getMapVal(map, key); + } + + /*Insert or Update Methods*/ + void putVal(session *session, val_map *map, const char *key, map_val *val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putVal(map, key, val); + } + + void putObjectVal(session *session, val_map *map, const char *key, jobject val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putObjectVal(map, key, val); + } + + void putIntVal(session *session, val_map *map, const char *key, int val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putIntVal(map, key, val); + } + + void putLongVal(session *session, val_map *map, const char *key, long val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putLongVal(map, key, val); + } + + void putFloatVal(session *session, val_map *map, const char *key, float val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putFloatVal(map, key, val); + } + + void putDoubleVal(session *session, val_map *map, const char *key, double val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putDoubleVal(map, key, val); + } + + void putByteVal(session *session, val_map *map, const char *key, signed char val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putByteVal(map, key, val); + } + + void putStringVal(session *session, val_map *map, const char *key, const char *val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putStringVal(map, key, val); + } + + void putBoolVal(session *session, val_map *map, const char *key, bool val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putBoolVal(map, key, val); + } + + void putShortVal(session *session, val_map *map, const char *key, short val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putShortVal(map, key, val); + } + + void putListVal(session *session, val_map *map, const char *key, val_list *val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putListVal(map, key, val); + } + + void putMapVal(session *session, val_map *map, const char *key, val_map *val) + { + return reinterpret_cast(session->sessionLib)->getMapUtils()->putMapVal(map, key, val); + } + + /*Rejection Utils*/ + rejection_list *createRejectionList(session *session) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->createRejectionList(); + } + + void addRejection(session *session, rejection_list *rejection_list, rejection *rejection) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->addRejection(rejection_list, rejection); + } + + rejection *getRejectionCopy(session *session, rejection *rejection) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->getCopy(rejection); + } + + record *getRejectionRecord(session *session, rejection *rejection) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->getRecord(rejection); + } + + string_list *getRejectionReasons(session *session, rejection *rejection) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->getReasons(rejection); + } + + void addRejectionReason(session *session, rejection *rejection, const char *reason) + { + return reinterpret_cast(session->sessionLib)->getRejectionUtils()->addReason(rejection, reason); + } + + /*Packet Utils*/ + void addPacketRecord(session *session, packet *packet, record *record) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->addRecord(packet, record); + } + + void setPacketRecords(session *session, packet *packet, record_list *records) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->setRecords(packet, records); + } + + void addPacketRecords(session *session, packet *packet, record_list *records) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->addRecords(packet, records); + } + + void setPacketRejections(session *session, packet *packet, rejection_list *rejections) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->setRejections(packet, rejections); + } + + void addPacketRejection(session *session, packet *packet, rejection *rejection) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->addRejection(packet, rejection); + } + + void addPacketRejections(session *session, packet *packet, rejection_list *rejections) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->addRejections(packet, rejections); + } + + record_list *getPacketRecords(session *session, packet *packet) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->getRecords(packet); + } + + rejection_list *getPacketRejections(session *session, packet *packet) + { + return reinterpret_cast(session->sessionLib)->getPacketUtils()->getRejections(packet); + } +} \ No newline at end of file diff --git a/src/cpp/main/common/MessageApiSessionLib.h b/src/cpp/main/common/MessageApiSessionLib.h index ebd8e67..c7ff772 100644 --- a/src/cpp/main/common/MessageApiSessionLib.h +++ b/src/cpp/main/common/MessageApiSessionLib.h @@ -2,6 +2,9 @@ #include #include "messageapi_structs.h" + +#include "JniUtils.h" +#include "MessageApiSession.h" /** * @author Ryan Berkheimer */ @@ -11,175 +14,182 @@ extern "C" #endif /* Session methods */ - struct session *createSession(const char* message); - struct request *createRequest(struct session *session); + session *createSession(const char* specPath); + void releaseSession(session *session); + request *createRequest(session *session); /* Request methods */ - struct record *createRecord(struct request *request); - struct request *getCopy(struct request *request); - struct request *getCopy(struct request *request, struct val_list *copy_components); - const char *getType(struct request *request); - struct record_list *getRecords(struct request *request); - struct record *getRequestRecord(struct request *request); - void setRecords(struct request *request, struct record_list *records); - struct response *submitRequest(struct request *request); + record *createRequestRecord(request *request); + request *getRequestCopy(request *request); + request *getRequestCopyComponents(request *request, val_list *copy_components); + const char *getRequestType(request *request); + record_list *getRequestRecords(request *request); + record *getRequestRecord(request *request); + void setRequestRecords(request *request, record_list *records); + response *submitRequest(request *request); /* Response methods */ - + bool isComplete(response *response); + request *getResponseRequest(response *response); + rejection_list *getResponseRejections(response *response); + record_list *getResponseRecords(response *response); + void setResponseRejections(response *response, rejection_list *rejections); + void setResponseRecords(response *response, record_list *records); + void setComplete(response *response, bool isComplete); /*Record Methods*/ - struct record_list *createRecordList(jlong message); - void addRecord(jlong message, struct record_list *record_list, struct record *record); + record_list *createRecordList(session *session); + void addRecord(session *session, record_list *record_list, record *record); - struct record *getRecordCopy(jlong message, struct record *record); - bool getRecordIsValid(jlong message, struct record *record); + record *getRecordCopy(session *session, record *record); + bool getRecordIsValid(session *session, record *record); - struct string_list *getFieldIds(jlong message, struct record *record); - struct field_list *getFields(jlong message, struct record *record); - struct field *getField(jlong message, struct record *record, const char *fieldId); - bool hasField(jlong message, struct record *record, const char *fieldId); + string_list *getFieldIds(session *session, record *record); + field_list *getFields(session *session, record *record); + field *getField(session *session, record *record, const char *fieldId); + bool hasField(session *session, record *record, const char *fieldId); - struct string_list *getConditionIds(jlong message, struct record *record); - struct condition_list *getConditions(jlong message, struct record *record); - struct condition *getCondition(jlong message, struct record *record, const char *conditionId); - bool hasCondition(jlong message, struct record *record, const char *conditionId); + string_list *getConditionIds(session *session, record *record); + condition_list *getConditions(session *session, record *record); + condition *getCondition(session *session, record *record, const char *conditionId); + bool hasCondition(session *session, record *record, const char *conditionId); /*Rejection Methods*/ - struct rejection_list *createRejectionList(jlong message); - void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection); - struct rejection *getRejectionCopy(jlong message, struct rejection *rejection); - struct record *getRejectionRecord(jlong message, struct rejection *rejection); - struct string_list *getRejectionReasons(jlong message, struct rejection *rejection); - void addRejectionReason(jlong message, struct rejection *rejection, const char *reason); + rejection_list *createRejectionList(session *session); + void addRejection(session *session, rejection_list *rejection_list, rejection *rejection); + rejection *getRejectionCopy(session *session, rejection *rejection); + record *getRejectionRecord(session *session, rejection *rejection); + string_list *getRejectionReasons(session *session, rejection *rejection); + void addRejectionReason(session *session, rejection *rejection, const char *reason); /*Field Methods*/ - const char *getFieldId(jlong message, struct field *field); - const char *getFieldType(jlong message, struct field *field); - bool getFieldIsValid(jlong message, struct field *field); - bool getFieldIsRequired(jlong message, struct field *field); - bool getFieldIsNull(jlong message, struct field *field); + const char *getFieldId(session *session, field *field); + const char *getFieldType(session *session, field *field); + bool getFieldIsValid(session *session, field *field); + bool getFieldIsRequired(session *session, field *field); + bool getFieldIsNull(session *session, field *field); /* Field Value Retrieval */ - struct val *getFieldVal(jlong message, struct field *field); - int getFieldIntVal(jlong message, struct field *field); - long getFieldLongVal(jlong message, struct field *field); - float getFieldFloatVal(jlong message, struct field *field); - double getFieldDoubleVal(jlong message, struct field *field); - signed char getFieldByteVal(jlong message, struct field *field); - const char *getFieldStringVal(jlong message, struct field *field); - bool getFieldBoolVal(jlong message, struct field *field); - short getFieldShortVal(jlong message, struct field *field); - struct val_list *getFieldListVal(jlong message, struct field *field); + val *getFieldVal(session *session, field *field); + int getFieldIntVal(session *session, field *field); + long getFieldLongVal(session *session, field *field); + float getFieldFloatVal(session *session, field *field); + double getFieldDoubleVal(session *session, field *field); + signed char getFieldByteVal(session *session, field *field); + const char *getFieldStringVal(session *session, field *field); + bool getFieldBoolVal(session *session, field *field); + short getFieldShortVal(session *session, field *field); + val_list *getFieldListVal(session *session, field *field); /*Field Value Puts */ - void setFieldVal(jlong message, struct field *field, struct val *value); - void setFieldIntVal(jlong message, struct field *field, int value); - void setFieldLongVal(jlong message, struct field *field, long value); - void setFieldFloatVal(jlong message, struct field *field, float value); - void setFieldDoubleVal(jlong message, struct field *field, double value); - void setFieldByteVal(jlong message, struct field *field, signed char value); - void setFieldStringVal(jlong message, struct field *field, const char *value); - void setFieldBoolVal(jlong message, struct field *field, bool value); - void setFieldShortVal(jlong message, struct field *field, short value); - void setFieldListVal(jlong message, struct field *field, struct val_list *value); + void setFieldVal(session *session, field *field, val *value); + void setFieldIntVal(session *session, field *field, int value); + void setFieldLongVal(session *session, field *field, long value); + void setFieldFloatVal(session *session, field *field, float value); + void setFieldDoubleVal(session *session, field *field, double value); + void setFieldByteVal(session *session, field *field, signed char value); + void setFieldStringVal(session *session, field *field, const char *value); + void setFieldBoolVal(session *session, field *field, bool value); + void setFieldShortVal(session *session, field *field, short value); + void setFieldListVal(session *session, field *field, val_list *value); /*Condition Methods*/ - const char *getConditionId(jlong message, struct condition *condition); - const char *getConditionType(jlong message, struct condition *condition); - const char *getConditionOperator(jlong message, struct condition *condition); - bool getConditionIsNull(jlong message, struct condition *condition); + const char *getConditionId(session *session, condition *condition); + const char *getConditionType(session *session, condition *condition); + const char *getConditionOperator(session *session, condition *condition); + bool getConditionIsNull(session *session, condition *condition); /* Condition value retrieval */ - struct val *getConditionVal(jlong message, struct condition *condition); - int getConditionIntVal(jlong message, struct condition *condition); - long getConditionLongVal(jlong message, struct condition *condition); - float getConditionFloatVal(jlong message, struct condition *condition); - double getConditionDoubleVal(jlong message, struct condition *condition); - signed char getConditionByteVal(jlong message, struct condition *condition); - const char *getConditionStringVal(jlong message, struct condition *condition); - bool getConditionBoolVal(jlong message, struct condition *condition); - short getConditionShortVal(jlong message, struct condition *condition); - struct val_list *getConditionListVal(jlong message, struct condition *condition); + val *getConditionVal(session *session, condition *condition); + int getConditionIntVal(session *session, condition *condition); + long getConditionLongVal(session *session, condition *condition); + float getConditionFloatVal(session *session, condition *condition); + double getConditionDoubleVal(session *session, condition *condition); + signed char getConditionByteVal(session *session, condition *condition); + const char *getConditionStringVal(session *session, condition *condition); + bool getConditionBoolVal(session *session, condition *condition); + short getConditionShortVal(session *session, condition *condition); + val_list *getConditionListVal(session *session, condition *condition); /* Condition value puts */ - void setConditionVal(jlong message, struct condition *condition, struct val *value); - void setConditionIntVal(jlong message, struct condition *condition, int value); - void setConditionLongVal(jlong message, struct condition *condition, long value); - void setConditionFloatVal(jlong message, struct condition *condition, float value); - void setConditionDoubleVal(jlong message, struct condition *condition, double value); - void setConditionByteVal(jlong message, struct condition *condition, signed char value); - void setConditionStringVal(jlong message, struct condition *condition, const char *value); - void setConditionBoolVal(jlong message, struct condition *condition, bool value); - void setConditionShortVal(jlong message, struct condition *condition, short value); - void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); + void setConditionVal(session *session, condition *condition, val *value); + void setConditionIntVal(session *session, condition *condition, int value); + void setConditionLongVal(session *session, condition *condition, long value); + void setConditionFloatVal(session *session, condition *condition, float value); + void setConditionDoubleVal(session *session, condition *condition, double value); + void setConditionByteVal(session *session, condition *condition, signed char value); + void setConditionStringVal(session *session, condition *condition, const char *value); + void setConditionBoolVal(session *session, condition *condition, bool value); + void setConditionShortVal(session *session, condition *condition, short value); + void setConditionListVal(session *session, condition *condition, val_list *value); /*List Utility Methods*/ - int getIntItem(jlong message, struct val_list *list, int index); - long getLongItem(jlong message, struct val_list *list, int index); - float getFloatItem(jlong message, struct val_list *list, int index); - double getDoubleItem(jlong message, struct val_list *list, int index); - signed char getByteItem(jlong message, struct val_list *list, int index); - const char *getStringItem(jlong message, struct val_list *list, int index); - bool getBoolItem(jlong message, struct val_list *list, int index); - short getShortItem(jlong message, struct val_list *list, int index); - struct list_item *getItem(jlong message, struct val_list *list, int index); - struct val_list *getListItem(jlong message, struct val_list *list, int index); - struct val_map *getMapItem(jlong message, struct val_list *list, int index); - struct val_list *createList(jlong message); - void addItem(jlong message, struct val_list *list, struct list_item *item); - void addIntItem(jlong message, struct val_list *list, int val); - void addLongItem(jlong message, struct val_list *list, long val); - void addFloatItem(jlong message, struct val_list *list, float val); - void addDoubleItem(jlong message, struct val_list *list, double val); - void addByteItem(jlong message, struct val_list *list, signed char val); - void addStringItem(jlong message, struct val_list *list, const char *val); - void addBoolItem(jlong message, struct val_list *list, bool val); - void addShortItem(jlong message, struct val_list *list, short val); - void addListItem(jlong message, struct val_list *list, struct val_list *val); - void addMapItem(jlong message, struct val_list *list, struct val_map *map); + int getIntItem(session *session, val_list *list, int index); + long getLongItem(session *session, val_list *list, int index); + float getFloatItem(session *session, val_list *list, int index); + double getDoubleItem(session *session, val_list *list, int index); + signed char getByteItem(session *session, val_list *list, int index); + const char *getStringItem(session *session, val_list *list, int index); + bool getBoolItem(session *session, val_list *list, int index); + short getShortItem(session *session, val_list *list, int index); + list_item *getItem(session *session, val_list *list, int index); + val_list *getListItem(session *session, val_list *list, int index); + val_map *getMapItem(session *session, val_list *list, int index); + val_list *createList(session *session); + void addItem(session *session, val_list *list, list_item *item); + void addIntItem(session *session, val_list *list, int val); + void addLongItem(session *session, val_list *list, long val); + void addFloatItem(session *session, val_list *list, float val); + void addDoubleItem(session *session, val_list *list, double val); + void addByteItem(session *session, val_list *list, signed char val); + void addStringItem(session *session, val_list *list, const char *val); + void addBoolItem(session *session, val_list *list, bool val); + void addShortItem(session *session, val_list *list, short val); + void addListItem(session *session, val_list *list, val_list *val); + void addMapItem(session *session, val_list *list, val_map *map); /*Map Utility Methods*/ - struct val_map *createMap(jlong message); - int getSize(jlong message, struct val_map *map); - bool hasKey(jlong message, struct val_map *map, const char *key); + val_map *createMap(session *session); + int getSize(session *session, val_map *map); + bool hasKey(session *session, val_map *map, const char *key); /*Map Value Retrieval Methods*/ - struct map_val *getVal(jlong message, struct val_map *map, const char *key); - jobject getObjectVal(jlong message, struct val_map *map, const char *key); - int getIntVal(jlong message, struct val_map *map, const char *key); - long getLongVal(jlong message, struct val_map *map, const char *key); - float getFloatVal(jlong message, struct val_map *map, const char *key); - double getDoubleVal(jlong message, struct val_map *map, const char *key); - signed char getByteVal(jlong message, struct val_map *map, const char *key); - const char *getStringVal(jlong message, struct val_map *map, const char *key); - bool getBoolVal(jlong message, struct val_map *map, const char *key); - short getShortVal(jlong message, struct val_map *map, const char *key); - struct val_list *getListVal(jlong message, struct val_map *map, const char *key); - struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + map_val *getVal(session *session, val_map *map, const char *key); + jobject getObjectVal(session *session, val_map *map, const char *key); + int getIntVal(session *session, val_map *map, const char *key); + long getLongVal(session *session, val_map *map, const char *key); + float getFloatVal(session *session, val_map *map, const char *key); + double getDoubleVal(session *session, val_map *map, const char *key); + signed char getByteVal(session *session, val_map *map, const char *key); + const char *getStringVal(session *session, val_map *map, const char *key); + bool getBoolVal(session *session, val_map *map, const char *key); + short getShortVal(session *session, val_map *map, const char *key); + val_list *getListVal(session *session, val_map *map, const char *key); + val_map *getMapVal(session *session, val_map *map, const char *key); /*Insert or Update Methods*/ - void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); - void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); - void putIntVal(jlong message, struct val_map *map, const char *key, int val); - void putLongVal(jlong message, struct val_map *map, const char *key, long val); - void putFloatVal(jlong message, struct val_map *map, const char *key, float val); - void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); - void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); - void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); - void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); - void putShortVal(jlong message, struct val_map *map, const char *key, short val); - void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); - void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); + void putVal(session *session, val_map *map, const char *key, map_val *val); + void putObjectVal(session *session, val_map *map, const char *key, jobject val); + void putIntVal(session *session, val_map *map, const char *key, int val); + void putLongVal(session *session, val_map *map, const char *key, long val); + void putFloatVal(session *session, val_map *map, const char *key, float val); + void putDoubleVal(session *session, val_map *map, const char *key, double val); + void putByteVal(session *session, val_map *map, const char *key, signed char val); + void putStringVal(session *session, val_map *map, const char *key, const char *val); + void putBoolVal(session *session, val_map *map, const char *key, bool val); + void putShortVal(session *session, val_map *map, const char *key, short val); + void putListVal(session *session, val_map *map, const char *key, val_list *val); + void putMapVal(session *session, val_map *map, const char *key, val_map *val); /*Packet Methods*/ - void addPacketRecord(jlong message, struct packet *packet, struct record *record); - void setPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void addPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection); - void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - struct record_list *getPacketRecords(jlong message, struct packet *packet); - struct rejection_list *getPacketRejections(jlong message, struct packet *packet); + void addPacketRecord(session *session, packet *packet, record *record); + void setPacketRecords(session *session, packet *packet, record_list *records); + void addPacketRecords(session *session, packet *packet, record_list *records); + void setPacketRejections(session *session, packet *packet, rejection_list *rejections); + void addPacketRejection(session *session, packet *packet, rejection *rejection); + void addPacketRejections(session *session, packet *packet, rejection_list *rejections); + record_list *getPacketRecords(session *session, packet *packet); + rejection_list *getPacketRejections(session *session, packet *packet); #ifdef __cplusplus } diff --git a/src/cpp/main/common/MessageApiTransformationLib.cpp b/src/cpp/main/common/MessageApiTransformationLib.cpp index 96e56c2..3301ce0 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.cpp +++ b/src/cpp/main/common/MessageApiTransformationLib.cpp @@ -25,525 +25,525 @@ JNIEXPORT void JNICALL Java_gov_noaa_messageapi_transformations_NativeTransforma extern "C" { - struct val_map *getConstructor(jlong message) + val_map *getConstructor(jlong message) { return reinterpret_cast(message)->getTransformationUtils()->getConstructor(); } - struct record_list *getRecords(jlong message, const char *key) + record_list *getRecords(jlong message, const char *key) { return reinterpret_cast(message)->getTransformationUtils()->getRecords(key); } - struct record_list *createRecordList(jlong message) + record_list *createRecordList(jlong message) { return reinterpret_cast(message)->getRecordUtils()->createRecordList(); } - void addRecord(jlong message, struct record_list *record_list, struct record *record) + void addRecord(jlong message, record_list *record_list, record *record) { return reinterpret_cast(message)->getRecordUtils()->addRecord(record_list, record); } - struct record *getRecord(jlong message, struct record_list *recordList, int recordIndex) + record *getRecord(jlong message, record_list *recordList, int recordIndex) { return reinterpret_cast(message)->getRecordUtils()->getRecord(recordList, recordIndex); } - struct record *getRecordCopy(jlong message, struct record *record) + record *getRecordCopy(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getCopy(record); } - bool getRecordIsValid(jlong message, struct record *record) + bool getRecordIsValid(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->isValid(record); } - struct string_list *getFieldIds(jlong message, struct record *record) + string_list *getFieldIds(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getFieldIds(record); } - struct field_list *getFields(jlong message, struct record *record) + field_list *getFields(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getFields(record); } - struct field *getField(jlong message, struct record *record, const char* fieldId) + field *getField(jlong message, record *record, const char* fieldId) { return reinterpret_cast(message)->getRecordUtils()->getField(record, fieldId); } - bool hasField(jlong message, struct record *record, const char *fieldId) + bool hasField(jlong message, record *record, const char *fieldId) { return reinterpret_cast(message)->getRecordUtils()->hasField(record, fieldId); } - struct string_list *getConditionIds(jlong message, struct record *record) + string_list *getConditionIds(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getConditionIds(record); } - struct condition_list *getConditions(jlong message, struct record *record) + condition_list *getConditions(jlong message, record *record) { return reinterpret_cast(message)->getRecordUtils()->getConditions(record); } - struct condition *getCondition(jlong message, struct record *record, const char *conditionId) + condition *getCondition(jlong message, record *record, const char *conditionId) { return reinterpret_cast(message)->getRecordUtils()->getCondition(record, conditionId); } - bool hasCondition(jlong message, struct record *record, const char *conditionId) + bool hasCondition(jlong message, record *record, const char *conditionId) { return reinterpret_cast(message)->getRecordUtils()->hasCondition(record, conditionId); } /*Field Methods*/ - const char *getFieldId(jlong message, struct field *field) + const char *getFieldId(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getId(field); } - const char *getFieldType(jlong message, struct field *field) + const char *getFieldType(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getType(field); } - bool getFieldIsValid(jlong message, struct field *field) + bool getFieldIsValid(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isValid(field); } - bool getFieldIsRequired(jlong message, struct field *field) + bool getFieldIsRequired(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isRequired(field); } - bool getFieldIsNull(jlong message, struct field *field) + bool getFieldIsNull(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->isNull(field); } - struct val *getFieldVal(jlong message, struct field *field) + val *getFieldVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getVal(field); } - int getFieldIntVal(jlong message, struct field *field) + int getFieldIntVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getIntVal(field); } - long getFieldLongVal(jlong message, struct field *field) + long getFieldLongVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getLongVal(field); } - float getFieldFloatVal(jlong message, struct field *field) + float getFieldFloatVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getFloatVal(field); } - double getFieldDoubleVal(jlong message, struct field *field) + double getFieldDoubleVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getDoubleVal(field); } - signed char getFieldByteVal(jlong message, struct field *field) + signed char getFieldByteVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getByteVal(field); } - const char *getFieldStringVal(jlong message, struct field *field) + const char *getFieldStringVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getStringVal(field); } - bool getFieldBoolVal(jlong message, struct field *field) + bool getFieldBoolVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getBoolVal(field); } - short getFieldShortVal(jlong message, struct field *field) + short getFieldShortVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getShortVal(field); } - struct val_list *getFieldListVal(jlong message, struct field *field) + val_list *getFieldListVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getListVal(field); } - struct val_map *getFieldMapVal(jlong message, struct field *field) + val_map *getFieldMapVal(jlong message, field *field) { return reinterpret_cast(message)->getFieldUtils()->getMapVal(field); } - void setFieldVal(jlong message, struct field *field, struct val *value) + void setFieldVal(jlong message, field *field, val *value) { return reinterpret_cast(message)->getFieldUtils()->setVal(field, value); } - void setFieldIntVal(jlong message, struct field *field, int value) + void setFieldIntVal(jlong message, field *field, int value) { return reinterpret_cast(message)->getFieldUtils()->setIntVal(field, value); } - void setFieldLongVal(jlong message, struct field *field, long value) + void setFieldLongVal(jlong message, field *field, long value) { return reinterpret_cast(message)->getFieldUtils()->setLongVal(field, value); } - void setFieldFloatVal(jlong message, struct field *field, float value) + void setFieldFloatVal(jlong message, field *field, float value) { return reinterpret_cast(message)->getFieldUtils()->setFloatVal(field, value); } - void setFieldDoubleVal(jlong message, struct field *field, double value) + void setFieldDoubleVal(jlong message, field *field, double value) { return reinterpret_cast(message)->getFieldUtils()->setDoubleVal(field, value); } - void setFieldByteVal(jlong message, struct field *field, signed char value) + void setFieldByteVal(jlong message, field *field, signed char value) { return reinterpret_cast(message)->getFieldUtils()->setByteVal(field, value); } - void setFieldStringVal(jlong message, struct field *field, const char *value) + void setFieldStringVal(jlong message, field *field, const char *value) { return reinterpret_cast(message)->getFieldUtils()->setStringVal(field, value); } - void setFieldBoolVal(jlong message, struct field *field, bool value) + void setFieldBoolVal(jlong message, field *field, bool value) { return reinterpret_cast(message)->getFieldUtils()->setBoolVal(field, value); } - void setFieldShortVal(jlong message, struct field *field, short value) + void setFieldShortVal(jlong message, field *field, short value) { return reinterpret_cast(message)->getFieldUtils()->setShortVal(field, value); } - void setFieldListVal(jlong message, struct field *field, struct val_list *value) + void setFieldListVal(jlong message, field *field, val_list *value) { return reinterpret_cast(message)->getFieldUtils()->setListVal(field, value); } - void setFieldMapVal(jlong message, struct field *field, struct val_map *value) + void setFieldMapVal(jlong message, field *field, val_map *value) { return reinterpret_cast(message)->getFieldUtils()->setMapVal(field, value); } /*Condition Methods*/ - const char *getConditionId(jlong message, struct condition *condition) + const char *getConditionId(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getId(condition); } - const char *getConditionType(jlong message, struct condition *condition) + const char *getConditionType(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getType(condition); } - const char *getConditionOperator(jlong message, struct condition *condition) + const char *getConditionOperator(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getOperator(condition); } - bool getConditionIsNull(jlong message, struct condition *condition) + bool getConditionIsNull(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->isNull(condition); } - struct val *getConditionVal(jlong message, struct condition *condition) + val *getConditionVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getVal(condition); } - int getConditionIntVal(jlong message, struct condition *condition) + int getConditionIntVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getIntVal(condition); } - long getConditionLongVal(jlong message, struct condition *condition) + long getConditionLongVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getLongVal(condition); } - float getConditionFloatVal(jlong message, struct condition *condition) + float getConditionFloatVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getFloatVal(condition); } - double getConditionDoubleVal(jlong message, struct condition *condition) + double getConditionDoubleVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getDoubleVal(condition); } - signed char getConditionByteVal(jlong message, struct condition *condition) + signed char getConditionByteVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getByteVal(condition); } - const char *getConditionStringVal(jlong message, struct condition *condition) + const char *getConditionStringVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getStringVal(condition); } - bool getConditionBoolVal(jlong message, struct condition *condition) + bool getConditionBoolVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getBoolVal(condition); } - short getConditionShortVal(jlong message, struct condition *condition) + short getConditionShortVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getShortVal(condition); } - struct val_list *getConditionListVal(jlong message, struct condition *condition) + val_list *getConditionListVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getListVal(condition); } - struct val_map *getConditionMapVal(jlong message, struct condition *condition) + val_map *getConditionMapVal(jlong message, condition *condition) { return reinterpret_cast(message)->getConditionUtils()->getMapVal(condition); } - void setConditionVal(jlong message, struct condition *condition, struct val *value) + void setConditionVal(jlong message, condition *condition, val *value) { return reinterpret_cast(message)->getConditionUtils()->setVal(condition, value); } - void setConditionIntVal(jlong message, struct condition *condition, int value) + void setConditionIntVal(jlong message, condition *condition, int value) { return reinterpret_cast(message)->getConditionUtils()->setIntVal(condition, value); } - void setConditionLongVal(jlong message, struct condition *condition, long value) + void setConditionLongVal(jlong message, condition *condition, long value) { return reinterpret_cast(message)->getConditionUtils()->setLongVal(condition, value); } - void setConditionFloatVal(jlong message, struct condition *condition, float value) + void setConditionFloatVal(jlong message, condition *condition, float value) { return reinterpret_cast(message)->getConditionUtils()->setFloatVal(condition, value); } - void setConditionDoubleVal(jlong message, struct condition *condition, double value) + void setConditionDoubleVal(jlong message, condition *condition, double value) { return reinterpret_cast(message)->getConditionUtils()->setDoubleVal(condition, value); } - void setConditionByteVal(jlong message, struct condition *condition, signed char value) + void setConditionByteVal(jlong message, condition *condition, signed char value) { return reinterpret_cast(message)->getConditionUtils()->setByteVal(condition, value); } - void setConditionStringVal(jlong message, struct condition *condition, const char *value) + void setConditionStringVal(jlong message, condition *condition, const char *value) { return reinterpret_cast(message)->getConditionUtils()->setStringVal(condition, value); } - void setConditionBoolVal(jlong message, struct condition *condition, bool value) + void setConditionBoolVal(jlong message, condition *condition, bool value) { return reinterpret_cast(message)->getConditionUtils()->setBoolVal(condition, value); } - void setConditionShortVal(jlong message, struct condition *condition, short value) + void setConditionShortVal(jlong message, condition *condition, short value) { return reinterpret_cast(message)->getConditionUtils()->setShortVal(condition, value); } - void setConditionListVal(jlong message, struct condition *condition, struct val_list *value) + void setConditionListVal(jlong message, condition *condition, val_list *value) { return reinterpret_cast(message)->getConditionUtils()->setListVal(condition, value); } - void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value) + void setConditionMapVal(jlong message, condition *condition, val_map *value) { return reinterpret_cast(message)->getConditionUtils()->setMapVal(condition, value); } /*List Utility Methods*/ - struct list_item *getItem(jlong message, struct val_list *list, int index) + list_item *getItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getItem(list, index); } - struct val_list *getListItem(jlong message, struct val_list *list, int index) + val_list *getListItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getListItem(list, index); } - int getIntItem(jlong message, struct val_list *list, int index) + int getIntItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getIntItem(list, index); } - long getLongItem(jlong message, struct val_list *list, int index) + long getLongItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getLongItem(list, index); } - float getFloatItem(jlong message, struct val_list *list, int index) + float getFloatItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getFloatItem(list, index); } - double getDoubleItem(jlong message, struct val_list *list, int index) + double getDoubleItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getDoubleItem(list, index); } - signed char getByteItem(jlong message, struct val_list *list, int index) + signed char getByteItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getByteItem(list, index); } - const char *getStringItem(jlong message, struct val_list *list, int index) + const char *getStringItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getStringItem(list, index); } - bool getBoolItem(jlong message, struct val_list *list, int index) + bool getBoolItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getBoolItem(list, index); } - short getShortItem(jlong message, struct val_list *list, int index) + short getShortItem(jlong message, val_list *list, int index) { return reinterpret_cast(message)->getListUtils()->getShortItem(list, index); } - struct val_list *createList(jlong message) + val_list *createList(jlong message) { return reinterpret_cast(message)->getListUtils()->createList(); } - void addItem(jlong message, struct val_list *list, struct list_item *item) + void addItem(jlong message, val_list *list, list_item *item) { return reinterpret_cast(message)->getListUtils()->addItem(list, item); } - void addIntItem(jlong message, struct val_list *list, int val) + void addIntItem(jlong message, val_list *list, int val) { return reinterpret_cast(message)->getListUtils()->addIntItem(list, val); } - void addLongItem(jlong message, struct val_list *list, long val) + void addLongItem(jlong message, val_list *list, long val) { return reinterpret_cast(message)->getListUtils()->addLongItem(list, val); } - void addFloatItem(jlong message, struct val_list *list, float val) + void addFloatItem(jlong message, val_list *list, float val) { return reinterpret_cast(message)->getListUtils()->addFloatItem(list, val); } - void addDoubleItem(jlong message, struct val_list *list, double val) + void addDoubleItem(jlong message, val_list *list, double val) { return reinterpret_cast(message)->getListUtils()->addDoubleItem(list, val); } - void addByteItem(jlong message, struct val_list *list, signed char val) + void addByteItem(jlong message, val_list *list, signed char val) { return reinterpret_cast(message)->getListUtils()->addByteItem(list, val); } - void addStringItem(jlong message, struct val_list *list, const char *val) + void addStringItem(jlong message, val_list *list, const char *val) { return reinterpret_cast(message)->getListUtils()->addStringItem(list, val); } - void addBoolItem(jlong message, struct val_list *list, bool val) + void addBoolItem(jlong message, val_list *list, bool val) { return reinterpret_cast(message)->getListUtils()->addBoolItem(list, val); } - void addShortItem(jlong message, struct val_list *list, short val) + void addShortItem(jlong message, val_list *list, short val) { return reinterpret_cast(message)->getListUtils()->addShortItem(list, val); } - void addListItem(jlong message, struct val_list *list, struct val_list *val) + void addListItem(jlong message, val_list *list, val_list *val) { return reinterpret_cast(message)->getListUtils()->addListItem(list, val); } /*Rejection Utils*/ - struct rejection_list *createRejectionList(jlong message) + rejection_list *createRejectionList(jlong message) { return reinterpret_cast(message)->getRejectionUtils()->createRejectionList(); } - void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection) + void addRejection(jlong message, rejection_list *rejection_list, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->addRejection(rejection_list, rejection); } - struct rejection *getRejectionCopy(jlong message, struct rejection *rejection) + rejection *getRejectionCopy(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getCopy(rejection); } - struct record *getRejectionRecord(jlong message, struct rejection *rejection) + record *getRejectionRecord(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getRecord(rejection); } - struct string_list *getRejectionReasons(jlong message, struct rejection *rejection) + string_list *getRejectionReasons(jlong message, rejection *rejection) { return reinterpret_cast(message)->getRejectionUtils()->getReasons(rejection); } - void addRejectionReason(jlong message, struct rejection *rejection, const char *reason) + void addRejectionReason(jlong message, rejection *rejection, const char *reason) { return reinterpret_cast(message)->getRejectionUtils()->addReason(rejection, reason); } /*Packet Utils*/ - void addPacketRecord(jlong message, struct packet *packet, struct record *record) + void addPacketRecord(jlong message, packet *packet, record *record) { return reinterpret_cast(message)->getPacketUtils()->addRecord(packet, record); } - void setPacketRecords(jlong message, struct packet *packet, struct record_list *records) + void setPacketRecords(jlong message, packet *packet, record_list *records) { return reinterpret_cast(message)->getPacketUtils()->setRecords(packet, records); } - void addPacketRecords(jlong message, struct packet *packet, struct record_list *records) + void addPacketRecords(jlong message, packet *packet, record_list *records) { return reinterpret_cast(message)->getPacketUtils()->addRecords(packet, records); } - void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + void setPacketRejections(jlong message, packet *packet, rejection_list *rejections) { return reinterpret_cast(message)->getPacketUtils()->setRejections(packet, rejections); } - void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection) + void addPacketRejection(jlong message, packet *packet, rejection *rejection) { return reinterpret_cast(message)->getPacketUtils()->addRejection(packet, rejection); } - void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections) + void addPacketRejections(jlong message, packet *packet, rejection_list *rejections) { return reinterpret_cast(message)->getPacketUtils()->addRejections(packet, rejections); } - struct record_list *getPacketRecords(jlong message, struct packet *packet) + record_list *getPacketRecords(jlong message, packet *packet) { return reinterpret_cast(message)->getPacketUtils()->getRecords(packet); } - struct rejection_list *getPacketRejections(jlong message, struct packet *packet) + rejection_list *getPacketRejections(jlong message, packet *packet) { return reinterpret_cast(message)->getPacketUtils()->getRejections(packet); } diff --git a/src/cpp/main/common/MessageApiTransformationLib.h b/src/cpp/main/common/MessageApiTransformationLib.h index 510105e..6c8a227 100644 --- a/src/cpp/main/common/MessageApiTransformationLib.h +++ b/src/cpp/main/common/MessageApiTransformationLib.h @@ -12,164 +12,164 @@ extern "C" #endif /* Transformation methods */ - struct val_map *getConstructor(jlong message); - struct record_list *getRecords(jlong message, const char *key); + val_map *getConstructor(jlong message); + record_list *getRecords(jlong message, const char *key); /*Record Methods*/ - struct record_list *createRecordList(jlong message); - void addRecord(jlong message, struct record_list *record_list, struct record *record); + record_list *createRecordList(jlong message); + void addRecord(jlong message, record_list *record_list, record *record); - struct record *getRecordCopy(jlong message, struct record *record); - bool getRecordIsValid(jlong message, struct record *record); + record *getRecordCopy(jlong message, record *record); + bool getRecordIsValid(jlong message, record *record); - struct string_list *getFieldIds(jlong message, struct record *record); - struct field_list *getFields(jlong message, struct record *record); - struct field *getField(jlong message, struct record *record, const char *fieldId); - bool hasField(jlong message, struct record *record, const char *fieldId); + string_list *getFieldIds(jlong message, record *record); + field_list *getFields(jlong message, record *record); + field *getField(jlong message, record *record, const char *fieldId); + bool hasField(jlong message, record *record, const char *fieldId); - struct string_list *getConditionIds(jlong message, struct record *record); - struct condition_list *getConditions(jlong message, struct record *record); - struct condition *getCondition(jlong message, struct record *record, const char *conditionId); - bool hasCondition(jlong message, struct record *record, const char *conditionId); + string_list *getConditionIds(jlong message, record *record); + condition_list *getConditions(jlong message, record *record); + condition *getCondition(jlong message, record *record, const char *conditionId); + bool hasCondition(jlong message, record *record, const char *conditionId); /*Rejection Methods*/ - struct rejection_list *createRejectionList(jlong message); - void addRejection(jlong message, struct rejection_list *rejection_list, struct rejection *rejection); - struct rejection *getRejectionCopy(jlong message, struct rejection *rejection); - struct record *getRejectionRecord(jlong message, struct rejection *rejection); - struct string_list *getRejectionReasons(jlong message, struct rejection *rejection); - void addRejectionReason(jlong message, struct rejection *rejection, const char *reason); + rejection_list *createRejectionList(jlong message); + void addRejection(jlong message, rejection_list *rejection_list, rejection *rejection); + rejection *getRejectionCopy(jlong message, rejection *rejection); + record *getRejectionRecord(jlong message, rejection *rejection); + string_list *getRejectionReasons(jlong message, rejection *rejection); + void addRejectionReason(jlong message, rejection *rejection, const char *reason); /*Field Methods*/ - const char *getFieldId(jlong message, struct field *field); - const char *getFieldType(jlong message, struct field *field); - bool getFieldIsValid(jlong message, struct field *field); - bool getFieldIsRequired(jlong message, struct field *field); - bool getFieldIsNull(jlong message, struct field *field); - - struct val *getFieldVal(jlong message, struct field *field); - int getFieldIntVal(jlong message, struct field *field); - long getFieldLongVal(jlong message, struct field *field); - float getFieldFloatVal(jlong message, struct field *field); - double getFieldDoubleVal(jlong message, struct field *field); - signed char getFieldByteVal(jlong message, struct field *field); - const char *getFieldStringVal(jlong message, struct field *field); - bool getFieldBoolVal(jlong message, struct field *field); - short getFieldShortVal(jlong message, struct field *field); - struct val_list *getFieldListVal(jlong message, struct field *field); - struct val_map *getFieldMapVal(jlong message, struct field *field); - - void setFieldVal(jlong message, struct field *field, struct val *value); - void setFieldIntVal(jlong message, struct field *field, int value); - void setFieldLongVal(jlong message, struct field *field, long value); - void setFieldFloatVal(jlong message, struct field *field, float value); - void setFieldDoubleVal(jlong message, struct field *field, double value); - void setFieldByteVal(jlong message, struct field *field, signed char value); - void setFieldStringVal(jlong message, struct field *field, const char *value); - void setFieldBoolVal(jlong message, struct field *field, bool value); - void setFieldShortVal(jlong message, struct field *field, short value); - void setFieldListVal(jlong message, struct field *field, struct val_list *value); - void setFieldMapVal(jlong message, struct field *field, struct val_map *value); + const char *getFieldId(jlong message, field *field); + const char *getFieldType(jlong message, field *field); + bool getFieldIsValid(jlong message, field *field); + bool getFieldIsRequired(jlong message, field *field); + bool getFieldIsNull(jlong message, field *field); + + val *getFieldVal(jlong message, field *field); + int getFieldIntVal(jlong message, field *field); + long getFieldLongVal(jlong message, field *field); + float getFieldFloatVal(jlong message, field *field); + double getFieldDoubleVal(jlong message, field *field); + signed char getFieldByteVal(jlong message, field *field); + const char *getFieldStringVal(jlong message, field *field); + bool getFieldBoolVal(jlong message, field *field); + short getFieldShortVal(jlong message, field *field); + val_list *getFieldListVal(jlong message, field *field); + val_map *getFieldMapVal(jlong message, field *field); + + void setFieldVal(jlong message, field *field, val *value); + void setFieldIntVal(jlong message, field *field, int value); + void setFieldLongVal(jlong message, field *field, long value); + void setFieldFloatVal(jlong message, field *field, float value); + void setFieldDoubleVal(jlong message, field *field, double value); + void setFieldByteVal(jlong message, field *field, signed char value); + void setFieldStringVal(jlong message, field *field, const char *value); + void setFieldBoolVal(jlong message, field *field, bool value); + void setFieldShortVal(jlong message, field *field, short value); + void setFieldListVal(jlong message, field *field, val_list *value); + void setFieldMapVal(jlong message, field *field, val_map *value); /*Condition Methods*/ - const char *getConditionId(jlong message, struct condition *condition); - const char *getConditionType(jlong message, struct condition *condition); - const char *getConditionOperator(jlong message, struct condition *condition); - bool getConditionIsNull(jlong message, struct condition *condition); - - struct val *getConditionVal(jlong message, struct condition *condition); - int getConditionIntVal(jlong message, struct condition *condition); - long getConditionLongVal(jlong message, struct condition *condition); - float getConditionFloatVal(jlong message, struct condition *condition); - double getConditionDoubleVal(jlong message, struct condition *condition); - signed char getConditionByteVal(jlong message, struct condition *condition); - const char *getConditionStringVal(jlong message, struct condition *condition); - bool getConditionBoolVal(jlong message, struct condition *condition); - short getConditionShortVal(jlong message, struct condition *condition); - struct val_list *getConditionListVal(jlong message, struct condition *condition); - struct val_map *getConditionMapVal(jlong message, struct condition *condition); - - void setConditionVal(jlong message, struct condition *condition, struct val *value); - void setConditionIntVal(jlong message, struct condition *condition, int value); - void setConditionLongVal(jlong message, struct condition *condition, long value); - void setConditionFloatVal(jlong message, struct condition *condition, float value); - void setConditionDoubleVal(jlong message, struct condition *condition, double value); - void setConditionByteVal(jlong message, struct condition *condition, signed char value); - void setConditionStringVal(jlong message, struct condition *condition, const char *value); - void setConditionBoolVal(jlong message, struct condition *condition, bool value); - void setConditionShortVal(jlong message, struct condition *condition, short value); - void setConditionListVal(jlong message, struct condition *condition, struct val_list *value); - void setConditionMapVal(jlong message, struct condition *condition, struct val_map *value); + const char *getConditionId(jlong message, condition *condition); + const char *getConditionType(jlong message, condition *condition); + const char *getConditionOperator(jlong message, condition *condition); + bool getConditionIsNull(jlong message, condition *condition); + + val *getConditionVal(jlong message, condition *condition); + int getConditionIntVal(jlong message, condition *condition); + long getConditionLongVal(jlong message, condition *condition); + float getConditionFloatVal(jlong message, condition *condition); + double getConditionDoubleVal(jlong message, condition *condition); + signed char getConditionByteVal(jlong message, condition *condition); + const char *getConditionStringVal(jlong message, condition *condition); + bool getConditionBoolVal(jlong message, condition *condition); + short getConditionShortVal(jlong message, condition *condition); + val_list *getConditionListVal(jlong message, condition *condition); + val_map *getConditionMapVal(jlong message, condition *condition); + + void setConditionVal(jlong message, condition *condition, val *value); + void setConditionIntVal(jlong message, condition *condition, int value); + void setConditionLongVal(jlong message, condition *condition, long value); + void setConditionFloatVal(jlong message, condition *condition, float value); + void setConditionDoubleVal(jlong message, condition *condition, double value); + void setConditionByteVal(jlong message, condition *condition, signed char value); + void setConditionStringVal(jlong message, condition *condition, const char *value); + void setConditionBoolVal(jlong message, condition *condition, bool value); + void setConditionShortVal(jlong message, condition *condition, short value); + void setConditionListVal(jlong message, condition *condition, val_list *value); + void setConditionMapVal(jlong message, condition *condition, val_map *value); /*List Utility Methods*/ - struct val_list *createList(jlong message); + val_list *createList(jlong message); - int getIntItem(jlong message, struct val_list *list, int index); - long getLongItem(jlong message, struct val_list *list, int index); - float getFloatItem(jlong message, struct val_list *list, int index); - double getDoubleItem(jlong message, struct val_list *list, int index); - signed char getByteItem(jlong message, struct val_list *list, int index); - const char *getStringItem(jlong message, struct val_list *list, int index); - bool getBoolItem(jlong message, struct val_list *list, int index); - short getShortItem(jlong message, struct val_list *list, int index); - struct list_item *getItem(jlong message, struct val_list *list, int index); - struct val_list *getListItem(jlong message, struct val_list *list, int index); - struct val_map *getMapItem(jlong message, struct val_list *list, int index); - - void addItem(jlong message, struct val_list *list, struct list_item *item); - void addIntItem(jlong message, struct val_list *list, int val); - void addLongItem(jlong message, struct val_list *list, long val); - void addFloatItem(jlong message, struct val_list *list, float val); - void addDoubleItem(jlong message, struct val_list *list, double val); - void addByteItem(jlong message, struct val_list *list, signed char val); - void addStringItem(jlong message, struct val_list *list, const char *val); - void addBoolItem(jlong message, struct val_list *list, bool val); - void addShortItem(jlong message, struct val_list *list, short val); - void addListItem(jlong message, struct val_list *list, struct val_list *val); - void addMapItem(jlong message, struct val_list *list, struct val_map *map); + int getIntItem(jlong message, val_list *list, int index); + long getLongItem(jlong message, val_list *list, int index); + float getFloatItem(jlong message, val_list *list, int index); + double getDoubleItem(jlong message, val_list *list, int index); + signed char getByteItem(jlong message, val_list *list, int index); + const char *getStringItem(jlong message, val_list *list, int index); + bool getBoolItem(jlong message, val_list *list, int index); + short getShortItem(jlong message, val_list *list, int index); + list_item *getItem(jlong message, val_list *list, int index); + val_list *getListItem(jlong message, val_list *list, int index); + val_map *getMapItem(jlong message, val_list *list, int index); + + void addItem(jlong message, val_list *list, list_item *item); + void addIntItem(jlong message, val_list *list, int val); + void addLongItem(jlong message, val_list *list, long val); + void addFloatItem(jlong message, val_list *list, float val); + void addDoubleItem(jlong message, val_list *list, double val); + void addByteItem(jlong message, val_list *list, signed char val); + void addStringItem(jlong message, val_list *list, const char *val); + void addBoolItem(jlong message, val_list *list, bool val); + void addShortItem(jlong message, val_list *list, short val); + void addListItem(jlong message, val_list *list, val_list *val); + void addMapItem(jlong message, val_list *list, val_map *map); /*Map Utility Methods*/ - struct val_map *createMap(jlong message); - int getSize(jlong message, struct val_map *map); - bool hasKey(jlong message, struct val_map *map, const char *key); + val_map *createMap(jlong message); + int getSize(jlong message, val_map *map); + bool hasKey(jlong message, val_map *map, const char *key); /*Map Value Retrieval Methods*/ - struct map_val *getVal(jlong message, struct val_map *map, const char *key); - jobject getObjectVal(jlong message, struct val_map *map, const char *key); - int getIntVal(jlong message, struct val_map *map, const char *key); - long getLongVal(jlong message, struct val_map *map, const char *key); - float getFloatVal(jlong message, struct val_map *map, const char *key); - double getDoubleVal(jlong message, struct val_map *map, const char *key); - signed char getByteVal(jlong message, struct val_map *map, const char *key); - const char *getStringVal(jlong message, struct val_map *map, const char *key); - bool getBoolVal(jlong message, struct val_map *map, const char *key); - short getShortVal(jlong message, struct val_map *map, const char *key); - struct val_list *getListVal(jlong message, struct val_map *map, const char *key); - struct val_map *getMapVal(jlong message, struct val_map *map, const char *key); + map_val *getVal(jlong message, val_map *map, const char *key); + jobject getObjectVal(jlong message, val_map *map, const char *key); + int getIntVal(jlong message, val_map *map, const char *key); + long getLongVal(jlong message, val_map *map, const char *key); + float getFloatVal(jlong message, val_map *map, const char *key); + double getDoubleVal(jlong message, val_map *map, const char *key); + signed char getByteVal(jlong message, val_map *map, const char *key); + const char *getStringVal(jlong message, val_map *map, const char *key); + bool getBoolVal(jlong message, val_map *map, const char *key); + short getShortVal(jlong message, val_map *map, const char *key); + val_list *getListVal(jlong message, val_map *map, const char *key); + val_map *getMapVal(jlong message, val_map *map, const char *key); /*Insert or Update Methods*/ - void putVal(jlong message, struct val_map *map, const char *key, struct map_val *val); - void putObjectVal(jlong message, struct val_map *map, const char *key, jobject val); - void putIntVal(jlong message, struct val_map *map, const char *key, int val); - void putLongVal(jlong message, struct val_map *map, const char *key, long val); - void putFloatVal(jlong message, struct val_map *map, const char *key, float val); - void putDoubleVal(jlong message, struct val_map *map, const char *key, double val); - void putByteVal(jlong message, struct val_map *map, const char *key, signed char val); - void putStringVal(jlong message, struct val_map *map, const char *key, const char *val); - void putBoolVal(jlong message, struct val_map *map, const char *key, bool val); - void putShortVal(jlong message, struct val_map *map, const char *key, short val); - void putListVal(jlong message, struct val_map *map, const char *key, struct val_list *val); - void putMapVal(jlong message, struct val_map *map, const char *key, struct val_map *val); + void putVal(jlong message, val_map *map, const char *key, map_val *val); + void putObjectVal(jlong message, val_map *map, const char *key, jobject val); + void putIntVal(jlong message, val_map *map, const char *key, int val); + void putLongVal(jlong message, val_map *map, const char *key, long val); + void putFloatVal(jlong message, val_map *map, const char *key, float val); + void putDoubleVal(jlong message, val_map *map, const char *key, double val); + void putByteVal(jlong message, val_map *map, const char *key, signed char val); + void putStringVal(jlong message, val_map *map, const char *key, const char *val); + void putBoolVal(jlong message, val_map *map, const char *key, bool val); + void putShortVal(jlong message, val_map *map, const char *key, short val); + void putListVal(jlong message, val_map *map, const char *key, val_list *val); + void putMapVal(jlong message, val_map *map, const char *key, val_map *val); /*Packet Methods*/ - void addPacketRecord(jlong message, struct packet *packet, struct record *record); - void setPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void addPacketRecords(jlong message, struct packet *packet, struct record_list *records); - void setPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - void addPacketRejection(jlong message, struct packet *packet, struct rejection *rejection); - void addPacketRejections(jlong message, struct packet *packet, struct rejection_list *rejections); - struct record_list *getPacketRecords(jlong message, struct packet *packet); - struct rejection_list *getPacketRejections(jlong message, struct packet *packet); + void addPacketRecord(jlong message, packet *packet, record *record); + void setPacketRecords(jlong message, packet *packet, record_list *records); + void addPacketRecords(jlong message, packet *packet, record_list *records); + void setPacketRejections(jlong message, packet *packet, rejection_list *rejections); + void addPacketRejection(jlong message, packet *packet, rejection *rejection); + void addPacketRejections(jlong message, packet *packet, rejection_list *rejections); + record_list *getPacketRecords(jlong message, packet *packet); + rejection_list *getPacketRejections(jlong message, packet *packet); #ifdef __cplusplus } diff --git a/src/cpp/main/common/SessionUtils.cpp b/src/cpp/main/common/SessionUtils.cpp index adcf31a..01b802a 100644 --- a/src/cpp/main/common/SessionUtils.cpp +++ b/src/cpp/main/common/SessionUtils.cpp @@ -11,9 +11,9 @@ */ /* Default Constructor */ -SessionUtils::SessionUtils(JNIEnv *jvm) +SessionUtils::SessionUtils(JNIEnv *jvm, jobject session) { - this->loadGlobalRefs(jvm); + this->loadGlobalRefs(jvm, session); this->loadMethodIds(); } @@ -30,9 +30,9 @@ SessionUtils::~SessionUtils() /* Public API */ -struct request *SessionUtils::createRequest(struct session *session) +struct request *SessionUtils::createRequest() { - jobject jrequest = this->jvm->CallObjectMethod(session->jsession, this->createRequestMethodId); + jobject jrequest = this->jvm->CallObjectMethod(this->session, this->createRequestMethodId); struct request *request = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); request->jrequest = jrequest; return request; @@ -40,9 +40,10 @@ struct request *SessionUtils::createRequest(struct session *session) /* Private Methods */ -void SessionUtils::loadGlobalRefs(JNIEnv *jvm) +void SessionUtils::loadGlobalRefs(JNIEnv *jvm, jobject session) { this->jvm = jvm; + this->session = session; } void SessionUtils::loadMethodIds() diff --git a/src/cpp/main/common/SessionUtils.h b/src/cpp/main/common/SessionUtils.h index 77c2c04..00b834a 100644 --- a/src/cpp/main/common/SessionUtils.h +++ b/src/cpp/main/common/SessionUtils.h @@ -23,17 +23,18 @@ class SessionUtils public: /*Default constructor */ - SessionUtils(JNIEnv *javaEnv); + SessionUtils(JNIEnv *javaEnv, jobject jSession); /*Default Destructor */ ~SessionUtils(); /* Session Methods */ - struct request *createRequest(struct session *session); + struct request *createRequest(); private: /*Vars*/ JNIEnv *jvm; + jobject session; /*Request Methods*/ jmethodID createRequestMethodId; @@ -41,7 +42,7 @@ private: /*Load method IDS for reuse. MethodIDS do not count against the jref count and do need to be released.*/ void loadMethodIds(); - void loadGlobalRefs(JNIEnv *env); + void loadGlobalRefs(JNIEnv *env, jobject session); /*Grouped methods for returning the matching method signature string for a given interface*/ const char *getMethodSignature(const char *methodName); -- GitLab From a2946e6eac0b6889a3c7cf07e725b485895e7ff9 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Tue, 2 Jun 2020 14:43:15 -0400 Subject: [PATCH 18/53] cleanup in code comments --- src/cpp/main/common/MessageApiSession.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cpp/main/common/MessageApiSession.cpp b/src/cpp/main/common/MessageApiSession.cpp index fba52ec..d4a4122 100644 --- a/src/cpp/main/common/MessageApiSession.cpp +++ b/src/cpp/main/common/MessageApiSession.cpp @@ -8,8 +8,8 @@ #include /** -Constructor for the MessageApiEndpoint object. Takes a JNI environment pointer, an endpoint context (this refers to -the endpoint class that's instantiating the object), and a protocol record which holds containers of records. +Constructor for the MessageApiSession object. Takes a JNI environment pointer and a session context (this refers to +the instantiated java session object). */ MessageApiSession::MessageApiSession(JNIEnv *env, jobject session) { -- GitLab From b172f7c7fe082e7e195efdfa4be2798c39771a9b Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Wed, 24 Jun 2020 00:19:32 -0400 Subject: [PATCH 19/53] remove unused/optimized imports from java, exposed/found via lint --- lib/test/native/demosession/.gitignore | 0 .../native/demosession/libDemoSession.dylib | Bin 0 -> 126916 bytes messageapi-core.code-workspace | 41 +++++++++ scripts/test/jni/demosession/Makefile | 84 +++++++++--------- src/c/test/sessions/demosession/DemoSession.c | 45 ---------- .../sessions/demosession/NativeSessionDemo.c | 8 +- src/c/test/sessions/demosession/compile.sh | 5 +- src/cpp/main/common/MessageApiSession.h | 1 + src/cpp/main/common/MessageApiSessionLib.cpp | 1 - src/cpp/main/common/MessageApiSessionLib.h | 36 ++++---- src/cpp/main/common/RequestUtils.cpp | 12 +-- .../conditions/ComparisonCondition.java | 1 - .../conditions/CompositeCondition.java | 1 - .../containers/DefaultContainer.java | 1 - .../messageapi/endpoints/NativeEndpoint.java | 1 - .../interfaces/IComparisonCondition.java | 1 - .../interfaces/ICompositeCondition.java | 1 - .../messageapi/interfaces/IContainer.java | 1 - .../noaa/messageapi/interfaces/IProtocol.java | 1 - .../noaa/messageapi/interfaces/ISchema.java | 2 - .../conditions/BooleanConditionOperator.java | 1 - .../conditions/DoubleConditionOperator.java | 1 - .../conditions/FloatConditionOperator.java | 1 - .../conditions/IntegerConditionOperator.java | 1 - .../plugins/ContainerPluginParser.java | 1 - .../parsers/plugins/ProtocolPluginParser.java | 2 - .../parsers/plugins/SchemaPluginParser.java | 1 - .../parsers/plugins/SessionPluginParser.java | 2 - .../messageapi/protocols/DefaultProtocol.java | 1 - .../rejections/DefaultRejection.java | 2 - .../messageapi/requests/DefaultRequest.java | 1 - .../messageapi/responses/DefaultResponse.java | 1 - .../messageapi/schemas/DefaultSchema.java | 1 - .../messageapi/sessions/DefaultSession.java | 1 - .../transformations/NativeTransformation.java | 2 - 35 files changed, 118 insertions(+), 144 deletions(-) create mode 100644 lib/test/native/demosession/.gitignore create mode 100755 lib/test/native/demosession/libDemoSession.dylib create mode 100644 messageapi-core.code-workspace delete mode 100644 src/c/test/sessions/demosession/DemoSession.c diff --git a/lib/test/native/demosession/.gitignore b/lib/test/native/demosession/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/lib/test/native/demosession/libDemoSession.dylib b/lib/test/native/demosession/libDemoSession.dylib new file mode 100755 index 0000000000000000000000000000000000000000..f9efcfec35dfd9b5bae354fd3b1101d6e6eb67c6 GIT binary patch literal 126916 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 LlA@LnaGd`IIe-{- literal 0 HcmV?d00001 diff --git a/messageapi-core.code-workspace b/messageapi-core.code-workspace new file mode 100644 index 0000000..ba87e00 --- /dev/null +++ b/messageapi-core.code-workspace @@ -0,0 +1,41 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "java.configuration.updateBuildConfiguration": "automatic", + "files.associations": { + "gov_noaa_messageapi_endpoints_nativeendpoint.h": "c", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "system_error": "cpp", + "type_traits": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "string": "cpp", + "*.jnilib": "c" + } + } +} \ No newline at end of file diff --git a/scripts/test/jni/demosession/Makefile b/scripts/test/jni/demosession/Makefile index d26ed81..4ba455b 100644 --- a/scripts/test/jni/demosession/Makefile +++ b/scripts/test/jni/demosession/Makefile @@ -1,16 +1,16 @@ -### This is a Makefile for MessageAPI Native Endpoints. +### This is a Makefile for MessageAPI Native sessions. # The majority of this Makefile is standard, with very few user specified things. # There are a few specific requirements and other notable things to keep in mind when using this Makefile: ## 1. You must have a JDK installed (not JRE). This library requires the jni.h header included in your jdk. ## 2. JAVA_HOME must be set to your JDK home directory. This Makefile references JAVA_HOME in looking for jni.h ## 3. This Makefile assumes a specific project layout when setting the PROJECTPATH. If the Makefile is not working, -## you should look at how it uses PROJECTPATH, ENDPOINT_NAME, and ENDPOINT_TYPE to find required files. +## you should look at how it uses PROJECTPATH, SESSION_NAME, and SESSION_TYPE to find required files. ## if your project is set up differently, i.e. custom project layout, then path dependent vars will need to be ## looked at and possibly changed. #The following represents the root project path. DO NOT EDIT SCRIPTDIR=$(PWD) -PROJECTPATH=$(firstword $(subst /scripts/$(ENDPOINT_TYPE)/, ,$(SCRIPTDIR))) +PROJECTPATH=$(firstword $(subst /scripts/$(SESSION_TYPE)/, ,$(SCRIPTDIR))) #The following is used to determine how native resources are compiled. DO NOT EDIT. UNAME := $(shell uname) @@ -20,12 +20,12 @@ UNAME := $(shell uname) #The following vars are used to route source code and scripts (from the scripts and src dirs) #to the library dir as compiled files (the job name should match the name of the directory/job map.) #the job type is simply a test job or a main job and should either be test or main. -ENDPOINT_NAME=demosession -ENDPOINT_TYPE=test +SESSION_NAME=demosession +SESSION_TYPE=test #USER SPECIFIED #The following var represents the output name of the JniLib that will be created and referenced in the job map. -#Do not specify the extension (.so/.dll/.jnilib) - these are determined automatically on build. +#Do not specify the extension (.so/.dll/.jnilib/.dylib) - these are determined automatically on build. #The full path to the created library must be referenced in the endpoint config. LIBNAME=DemoSession @@ -33,7 +33,7 @@ LIBNAME=DemoSession #The following vars should contain strings representing the C, Fortran, and CPP libraries that glue the fortran code to java code. #These strings should contain the user libraries in the order they need to be compiled (ex, "First.c Second.c Third.c") #These vars do not need to specify libraries they depend on that are found in the common variables (those are automatically compiled first). -USERC=EndpointWrapper.c +USERC=NativeSessionDemo.c USERCPP= USERFORTRAN= @@ -47,12 +47,17 @@ ifeq ($(UNAME), Linux) JNIDIR="$(JAVA_HOME)/include" JNIMDDIR="$(JAVA_HOME)/include/linux" JVMHEADERS="$(JAVA_HOME)/include/linux" +JVMDIR="$(JAVA_HOME)/lib/server" +JLIDIR="$(JAVA_HOME)/lib/jli" endif + ifeq ($(UNAME), Darwin) #The following represent a standard OSX system. JNIDIR="$(JAVA_HOME)/include" JNIMDDIR="$(JAVA_HOME)/include/darwin" JVMHEADERS="$(JAVA_HOME)/include" +JVMDIR="$(JAVA_HOME)/lib/server" +JLIDIR="$(JAVA_HOME)/lib/jli" endif #compilers @@ -63,22 +68,21 @@ FF=gfortran #The following vars contain strings representing common libraries used by all code #at a project level. These should generally not be touched by users. COMMONC= -COMMONCPP=MessageApiEndpoint.cpp MessageApiEndpointLib.cpp +COMMONCPP=JniUtils.cpp TypeUtils.cpp ListUtils.cpp MapUtils.cpp ConditionUtils.cpp FieldUtils.cpp \ +RecordUtils.cpp RejectionUtils.cpp PacketUtils.cpp SessionUtils.cpp RequestUtils.cpp ResponseUtils.cpp \ +MessageApiSession.cpp MessageApiSessionLib.cpp COMMONFORTRAN= -JAVACLASSES:=$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/endpoints/NativeEndpoint.java -JAVAPATH=$(PROJECTPATH)/src/java/main:$(PROJECTPATH)/src/java/main/gov/noaa/messageapi/endpoints - -#The following contains source code paths derived from the ENDPOINT_NAME and ENDPOINT_TYPE supplied by the user. +#The following contains source code paths derived from the SESSION_NAME and SESSION_TYPE supplied by the user. COMMONCPATH=$(PROJECTPATH)/src/c/main/common/structs/ -USERCPATH=$(PROJECTPATH)/src/c/$(ENDPOINT_TYPE)/endpoints/$(ENDPOINT_NAME)/ -COMMONCPPPATH=$(PROJECTPATH)/src/cpp/main/common/endpoint/ -USERCPPPATH=$(PROJECTPATH)/src/cpp/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ +USERCPATH=$(PROJECTPATH)/src/c/$(SESSION_TYPE)/sessions/$(SESSION_NAME)/ +COMMONCPPPATH=$(PROJECTPATH)/src/cpp/main/common/ +USERCPPPATH=$(PROJECTPATH)/src/cpp/$(SESSION_TYPE)/$(SESSION_NAME)/ COMMONFORTRANPATH=$(PROJECTPATH)/src/fortran/main/common/ -USERFORTRANPATH=$(PROJECTPATH)/src/fortran/$(ENDPOINT_TYPE)/$(ENDPOINT_NAME)/ +USERFORTRANPATH=$(PROJECTPATH)/src/fortran/$(SESSION_TYPE)/$(SESSION_NAME)/ #The following var contains the target path for the project code. -TARGETPATH="$(PROJECTPATH)/lib/$(ENDPOINT_TYPE)/native/$(ENDPOINT_NAME)/" +TARGETPATH="$(PROJECTPATH)/lib/$(SESSION_TYPE)/native/$(SESSION_NAME)/" #The following is the target library for the native jni library. ifeq ($(UNAME), Linux) @@ -90,7 +94,8 @@ ifeq ($(UNAME), Darwin) LNFLAGS=-dynamiclib -shared -lgfortran -I$(JVMHEADERS) -framework JavaVM endif -CFLAGS=-I$(JVMHEADERS) -I$(COMMONCPPPATH) -I$(COMMONCPATH) -I$(USERCPPPATH) -I$(USERCPATH) -I$(JNIDIR) -I$(JNIMDDIR) -fpic -std=c99 +CFLAGS=-I$(JVMHEADERS) -I$(COMMONCPPPATH) -I$(COMMONCPATH) -I$(USERCPPPATH) -I$(USERCPATH) -I$(JNIDIR) -I$(JNIMDDIR) \ +-L$(JLIDIR) -L$(JVMDIR) -ljli -ljvm -fpic -std=c99 -Wl,-rpath,$(JVMDIR) -Wl,-rpath,$(JLIDIR) FFLAGS=-I$(COMMONFORTRANPATH) -I$(USERFORTRANPATH) -fPIC -fopenmp #The following is the target library for the native jni library. @@ -100,7 +105,7 @@ DYLIB=lib$(LIBNAME).so endif ifeq ($(UNAME), Darwin) #The following represents a standard OSX system. -DYLIB=lib$(LIBNAME).jnilib +DYLIB=lib$(LIBNAME).dylib endif #COMMONFORTRAN1=$(addprefix $(COMMONFORTRANPATH), $(COMMONFORTRAN)) @@ -110,41 +115,36 @@ USERC1=$(addprefix $(USERCPATH), $(USERC)) COMMONCPP1=$(addprefix $(COMMONCPPPATH), $(COMMONCPP)) USERCPP1=$(addprefix $(USERCPPPATH), $(USERCPP)) -all: clean gen-headers build - -.PHONY : clean gen-headers build +all: clean build -gen-headers: - echo "Generating headers. " - echo "" - $(foreach header,$(JAVACLASSES),javac -h $(USERCPATH) -classpath $(JAVAPATH) $(header);) - echo "" +.PHONY : clean build build: - echo "Building " $(ENDPOINT_NAME) " in " $(PROJECTPATH) + @echo "Building " $(SESSION_NAME) " in " $(PROJECTPATH) #echo "Compiling Fortran" #echo "" #cd $(TARGETPATH) && $(FF) $(FFLAGS) -c $(COMMONFORTRAN1) $(USERFORTRAN1) #echo "" - echo "Compiling CPP" - echo "" - cd $(TARGETPATH) && $(CXX) $(CFLAGS) -c $(COMMONCPP1) $(USERCPP1) - echo "" - echo "Compiling C" - echo "" - cd $(TARGETPATH) && $(CC) $(CFLAGS) -c $(COMMONC1) $(USERC1) - echo "" - echo "Creating JNI Library" - echo "" - cd $(TARGETPATH) && $(CXX) $(LNFLAGS) *.o -o $(DYLIB) - echo "Build success for " $(ENDPOINT_NAME) + @echo "Compiling CPP" + @echo "" + @cd $(TARGETPATH) && $(CXX) $(CFLAGS) -c $(COMMONCPP1) $(USERCPP1) + @echo "" + #@echo "Compiling C" + #@echo "" + #@cd $(TARGETPATH) && $(CC) $(CFLAGS) -c $(COMMONC1) $(USERC1) + @echo "" + @echo "Creating Shared Library" + @echo "" + @cd $(TARGETPATH) && $(CXX) $(LNFLAGS) *.o -o $(DYLIB) + @echo "Build success for " $(SESSION_NAME) clean: - echo "Cleaning up." - echo "" + @echo "Cleaning up." + @echo "" -cd $(TARGETPATH) && rm *.h -cd $(TARGETPATH) && rm *.o -cd $(TARGETPATH) && rm *.mod + -cd $(TARGETPATH) && rm *.dylib -cd $(TARGETPATH) && rm *.jnilib -cd $(TARGETPATH) && rm *.so echo "" diff --git a/src/c/test/sessions/demosession/DemoSession.c b/src/c/test/sessions/demosession/DemoSession.c deleted file mode 100644 index 904c745..0000000 --- a/src/c/test/sessions/demosession/DemoSession.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include "messageapi_structs.h" -#include "MessageApiSessionLib.h" - -int main(int argc, char **argv) -{ - JavaVM *vm; - JNIEnv *env; - JavaVMInitArgs vm_args; - jint res; - jclass cls; - jmethodID mid; - //jstring jstr; - jobjectArray main_args; - - //vm_args.version = JNI_V - vm_args.nOptions = 0; - res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); - if (res != JNI_OK) - { - printf("Failed to create Java VMn"); - return 1; - } - - cls = (*env)->FindClass(env, "Main"); - if (cls == NULL) - { - printf("Failed to find Main classn"); - return 1; - } - - mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V"); - if (mid == NULL) - { - printf("Failed to find main functionn"); - return 1; - } - - jstring jstr = (*env)->NewStringUTF(env, ""); - main_args = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), jstr); - (*env)->CallStaticVoidMethod(env, cls, mid, main_args); - - return 0; -} \ No newline at end of file diff --git a/src/c/test/sessions/demosession/NativeSessionDemo.c b/src/c/test/sessions/demosession/NativeSessionDemo.c index d530a07..1cb0dab 100644 --- a/src/c/test/sessions/demosession/NativeSessionDemo.c +++ b/src/c/test/sessions/demosession/NativeSessionDemo.c @@ -1,7 +1,6 @@ #include #include -//#include "messageapi_structs.h" -//#include "MessageApiSessionLib.h" +#include "messageapi_structs.h" int main(int argc, char **argv) { @@ -9,5 +8,10 @@ int main(int argc, char **argv) printf("Hello, World\n"); fflush(stdout); + //session *session = createSession("/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/resources/test/file-reader/manifest.json"); + + printf("Successfully created session."); + fflush(stdout); + return 0; } \ No newline at end of file diff --git a/src/c/test/sessions/demosession/compile.sh b/src/c/test/sessions/demosession/compile.sh index 8a314c2..c9dfe0f 100755 --- a/src/c/test/sessions/demosession/compile.sh +++ b/src/c/test/sessions/demosession/compile.sh @@ -1,3 +1,6 @@ #!/bin/bash -gcc NativeSessionDemo.c -I$(/usr/libexec/java_home)/include/ -I$(/usr/libexec/java_home)/include/darwin -L$(/usr/libexec/java_home)/jre/lib/jli -L$(/usr/libexec/java_home)/jre/lib/server/ -ljli -ljvm +#CDIR=/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/src/c/main/common/structs +#CPPDIR=/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/src/cpp/main/common +#echo $(/usr/libexec/java_home) +#gcc NativeSessionDemo.c -I$CDIR -I$CPPDIR -I$(/usr/libexec/java_home)/include/ -I$(/usr/libexec/java_home)/include/darwin -L$(/usr/libexec/java_home)/lib/jli -L$(/usr/libexec/java_home)/lib/server/ -ljli -ljvm -Wl,-rpath,$(/usr/libexec/java_home)/lib/jli -Wl,-rpath,$(/usr/libexec/java_home)/lib/server/ -o nativeSessionTest.bin \ No newline at end of file diff --git a/src/cpp/main/common/MessageApiSession.h b/src/cpp/main/common/MessageApiSession.h index 719371a..9eac29b 100644 --- a/src/cpp/main/common/MessageApiSession.h +++ b/src/cpp/main/common/MessageApiSession.h @@ -10,6 +10,7 @@ #include #include "JniUtils.h" +#include "TypeUtils.h" #include "MapUtils.h" #include "ListUtils.h" #include "SessionUtils.h" diff --git a/src/cpp/main/common/MessageApiSessionLib.cpp b/src/cpp/main/common/MessageApiSessionLib.cpp index bcdacc7..d4ab29e 100644 --- a/src/cpp/main/common/MessageApiSessionLib.cpp +++ b/src/cpp/main/common/MessageApiSessionLib.cpp @@ -7,7 +7,6 @@ extern "C" */ session *createSession(const char *spec) { - session *session; JavaVM *vm; JNIEnv *env; JavaVMInitArgs vm_args; diff --git a/src/cpp/main/common/MessageApiSessionLib.h b/src/cpp/main/common/MessageApiSessionLib.h index c7ff772..908d735 100644 --- a/src/cpp/main/common/MessageApiSessionLib.h +++ b/src/cpp/main/common/MessageApiSessionLib.h @@ -14,28 +14,28 @@ extern "C" #endif /* Session methods */ - session *createSession(const char* specPath); - void releaseSession(session *session); - request *createRequest(session *session); + extern session *createSession(const char* specPath); + extern void releaseSession(session *session); + extern request *createRequest(session *session); /* Request methods */ - record *createRequestRecord(request *request); - request *getRequestCopy(request *request); - request *getRequestCopyComponents(request *request, val_list *copy_components); - const char *getRequestType(request *request); - record_list *getRequestRecords(request *request); - record *getRequestRecord(request *request); - void setRequestRecords(request *request, record_list *records); - response *submitRequest(request *request); + extern record *createRequestRecord(session *session, request *request); + extern request *getRequestCopy(session *session, request *request); + extern request *getRequestCopyComponents(session *session, request *request, val_list *copy_components); + extern const char *getRequestType(session *session, request *request); + record_list *getRequestRecords(session *session, request *request); + record *getRequestRecord(session *session, request *request); + void setRequestRecords(session *session, request *request, record_list *records); + response *submitRequest(session *session, request *request); /* Response methods */ - bool isComplete(response *response); - request *getResponseRequest(response *response); - rejection_list *getResponseRejections(response *response); - record_list *getResponseRecords(response *response); - void setResponseRejections(response *response, rejection_list *rejections); - void setResponseRecords(response *response, record_list *records); - void setComplete(response *response, bool isComplete); + bool isComplete(session *session, response *response); + request *getResponseRequest(session *session, response *response); + rejection_list *getResponseRejections(session *session, response *response); + record_list *getResponseRecords(session *session, response *response); + void setResponseRejections(session *session, response *response, rejection_list *rejections); + void setResponseRecords(session *session, response *response, record_list *records); + void setComplete(session *session, response *response, bool isComplete); /*Record Methods*/ record_list *createRecordList(session *session); diff --git a/src/cpp/main/common/RequestUtils.cpp b/src/cpp/main/common/RequestUtils.cpp index a919644..70f0ab9 100644 --- a/src/cpp/main/common/RequestUtils.cpp +++ b/src/cpp/main/common/RequestUtils.cpp @@ -58,17 +58,17 @@ struct record *RequestUtils::createRecord(struct request *request) struct request *RequestUtils::getCopy(struct request *request) { jobject jrequest = this->jvm->CallObjectMethod(request->jrequest, this->getCopyDefaultMethodId); - struct request *request = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); - request->jrequest = jrequest; - return request; + struct request *requestCopy = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); + requestCopy->jrequest = jrequest; + return requestCopy; } struct request *RequestUtils::getCopy(struct request *request, struct val_list *copy_components) { jobject jrequest = this->jvm->CallObjectMethod(request->jrequest, this->getCopyDefaultMethodId, copy_components->jlist); - struct request *request = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); - request->jrequest = jrequest; - return request; + struct request *requestCopy = (struct request *)malloc(sizeof(struct request) + sizeof(jrequest)); + requestCopy->jrequest = jrequest; + return requestCopy; } const char *RequestUtils::getType(struct request *request) diff --git a/src/java/main/gov/noaa/messageapi/conditions/ComparisonCondition.java b/src/java/main/gov/noaa/messageapi/conditions/ComparisonCondition.java index f8b8437..4057dc8 100644 --- a/src/java/main/gov/noaa/messageapi/conditions/ComparisonCondition.java +++ b/src/java/main/gov/noaa/messageapi/conditions/ComparisonCondition.java @@ -2,7 +2,6 @@ package gov.noaa.messageapi.conditions; import java.util.Map; -import gov.noaa.messageapi.conditions.BaseCondition; import gov.noaa.messageapi.interfaces.IComparisonCondition;; /** diff --git a/src/java/main/gov/noaa/messageapi/conditions/CompositeCondition.java b/src/java/main/gov/noaa/messageapi/conditions/CompositeCondition.java index 4a6ce17..72c5912 100644 --- a/src/java/main/gov/noaa/messageapi/conditions/CompositeCondition.java +++ b/src/java/main/gov/noaa/messageapi/conditions/CompositeCondition.java @@ -3,7 +3,6 @@ package gov.noaa.messageapi.conditions; import java.util.List; import java.util.Map; -import gov.noaa.messageapi.conditions.BaseCondition; import gov.noaa.messageapi.interfaces.ICompositeCondition; /** diff --git a/src/java/main/gov/noaa/messageapi/containers/DefaultContainer.java b/src/java/main/gov/noaa/messageapi/containers/DefaultContainer.java index 6421017..36d6dbe 100644 --- a/src/java/main/gov/noaa/messageapi/containers/DefaultContainer.java +++ b/src/java/main/gov/noaa/messageapi/containers/DefaultContainer.java @@ -6,7 +6,6 @@ import gov.noaa.messageapi.interfaces.ISchema; import gov.noaa.messageapi.interfaces.IProtocol; import gov.noaa.messageapi.interfaces.IContainer; -import gov.noaa.messageapi.containers.BaseContainer; import gov.noaa.messageapi.metadata.DefaultMetadata; /** diff --git a/src/java/main/gov/noaa/messageapi/endpoints/NativeEndpoint.java b/src/java/main/gov/noaa/messageapi/endpoints/NativeEndpoint.java index 09d0b98..d4e03ef 100644 --- a/src/java/main/gov/noaa/messageapi/endpoints/NativeEndpoint.java +++ b/src/java/main/gov/noaa/messageapi/endpoints/NativeEndpoint.java @@ -11,7 +11,6 @@ import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.IPacket; import gov.noaa.messageapi.interfaces.IProtocolRecord; -import gov.noaa.messageapi.endpoints.BaseEndpoint; import gov.noaa.messageapi.fields.DefaultField; import gov.noaa.messageapi.records.schema.SchemaRecord; import gov.noaa.messageapi.rejections.DefaultRejection; diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IComparisonCondition.java b/src/java/main/gov/noaa/messageapi/interfaces/IComparisonCondition.java index 6738816..a95b548 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IComparisonCondition.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IComparisonCondition.java @@ -1,6 +1,5 @@ package gov.noaa.messageapi.interfaces; -import gov.noaa.messageapi.interfaces.ICondition; /** * ComparisonConditions represent value-checking comparisons. diff --git a/src/java/main/gov/noaa/messageapi/interfaces/ICompositeCondition.java b/src/java/main/gov/noaa/messageapi/interfaces/ICompositeCondition.java index 08df961..20d95e6 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/ICompositeCondition.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/ICompositeCondition.java @@ -1,7 +1,6 @@ package gov.noaa.messageapi.interfaces; import java.util.List; -import gov.noaa.messageapi.interfaces.ICondition; /** * A composite condition is a type of condition that combines other diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IContainer.java b/src/java/main/gov/noaa/messageapi/interfaces/IContainer.java index de71765..afe485d 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IContainer.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IContainer.java @@ -1,6 +1,5 @@ package gov.noaa.messageapi.interfaces; -import gov.noaa.messageapi.interfaces.IComponent; import gov.noaa.messageapi.definitions.ContainerDefinition; /** diff --git a/src/java/main/gov/noaa/messageapi/interfaces/IProtocol.java b/src/java/main/gov/noaa/messageapi/interfaces/IProtocol.java index 3336f91..f4750c0 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/IProtocol.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/IProtocol.java @@ -2,7 +2,6 @@ package gov.noaa.messageapi.interfaces; import java.util.List; -import gov.noaa.messageapi.interfaces.IComponent; import gov.noaa.messageapi.definitions.ProtocolDefinition; /** diff --git a/src/java/main/gov/noaa/messageapi/interfaces/ISchema.java b/src/java/main/gov/noaa/messageapi/interfaces/ISchema.java index 789f7a8..c3b6a7a 100644 --- a/src/java/main/gov/noaa/messageapi/interfaces/ISchema.java +++ b/src/java/main/gov/noaa/messageapi/interfaces/ISchema.java @@ -1,7 +1,5 @@ package gov.noaa.messageapi.interfaces; -import gov.noaa.messageapi.interfaces.IComponent; - import gov.noaa.messageapi.definitions.SchemaDefinition; /** diff --git a/src/java/main/gov/noaa/messageapi/operators/conditions/BooleanConditionOperator.java b/src/java/main/gov/noaa/messageapi/operators/conditions/BooleanConditionOperator.java index 93d49b8..ac5de9e 100644 --- a/src/java/main/gov/noaa/messageapi/operators/conditions/BooleanConditionOperator.java +++ b/src/java/main/gov/noaa/messageapi/operators/conditions/BooleanConditionOperator.java @@ -3,7 +3,6 @@ package gov.noaa.messageapi.operators.conditions; import gov.noaa.messageapi.interfaces.IConditionOperator; import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.ICondition; -import gov.noaa.messageapi.operators.conditions.SimpleConditionOperator; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/operators/conditions/DoubleConditionOperator.java b/src/java/main/gov/noaa/messageapi/operators/conditions/DoubleConditionOperator.java index b90fb16..4fbba0b 100644 --- a/src/java/main/gov/noaa/messageapi/operators/conditions/DoubleConditionOperator.java +++ b/src/java/main/gov/noaa/messageapi/operators/conditions/DoubleConditionOperator.java @@ -3,7 +3,6 @@ package gov.noaa.messageapi.operators.conditions; import gov.noaa.messageapi.interfaces.IConditionOperator; import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.ICondition; -import gov.noaa.messageapi.operators.conditions.SimpleConditionOperator; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/operators/conditions/FloatConditionOperator.java b/src/java/main/gov/noaa/messageapi/operators/conditions/FloatConditionOperator.java index d7178ae..936736b 100644 --- a/src/java/main/gov/noaa/messageapi/operators/conditions/FloatConditionOperator.java +++ b/src/java/main/gov/noaa/messageapi/operators/conditions/FloatConditionOperator.java @@ -3,7 +3,6 @@ package gov.noaa.messageapi.operators.conditions; import gov.noaa.messageapi.interfaces.IConditionOperator; import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.ICondition; -import gov.noaa.messageapi.operators.conditions.SimpleConditionOperator; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/operators/conditions/IntegerConditionOperator.java b/src/java/main/gov/noaa/messageapi/operators/conditions/IntegerConditionOperator.java index 4dddb3a..1a9496d 100644 --- a/src/java/main/gov/noaa/messageapi/operators/conditions/IntegerConditionOperator.java +++ b/src/java/main/gov/noaa/messageapi/operators/conditions/IntegerConditionOperator.java @@ -3,7 +3,6 @@ package gov.noaa.messageapi.operators.conditions; import gov.noaa.messageapi.interfaces.IConditionOperator; import gov.noaa.messageapi.interfaces.IField; import gov.noaa.messageapi.interfaces.ICondition; -import gov.noaa.messageapi.operators.conditions.SimpleConditionOperator; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java index 26aecd0..ea0a450 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.java @@ -5,7 +5,6 @@ import java.util.Set; import java.util.HashSet; import gov.noaa.messageapi.interfaces.IContainer; -import gov.noaa.messageapi.parsers.plugins.BasePluginParser; import gov.noaa.messageapi.interfaces.IPluginParser; /** diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java index 6ab3aad..679bbf9 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.java @@ -7,8 +7,6 @@ import java.util.HashSet; import gov.noaa.messageapi.interfaces.IProtocol; import gov.noaa.messageapi.interfaces.IPluginParser; -import gov.noaa.messageapi.parsers.plugins.BasePluginParser; - /** * @author Ryan Berkheimer */ diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java index 99454c1..8fe22a5 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.java @@ -6,7 +6,6 @@ import java.util.HashSet; import gov.noaa.messageapi.interfaces.ISchema; import gov.noaa.messageapi.interfaces.IPluginParser; -import gov.noaa.messageapi.parsers.plugins.BasePluginParser; /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java b/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java index d33a70c..bf448e8 100644 --- a/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java +++ b/src/java/main/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.java @@ -11,8 +11,6 @@ import gov.noaa.messageapi.interfaces.ISchema; import gov.noaa.messageapi.interfaces.IPluginParser; -import gov.noaa.messageapi.parsers.plugins.BasePluginParser; - /** * @author Ryan Berkheimer */ diff --git a/src/java/main/gov/noaa/messageapi/protocols/DefaultProtocol.java b/src/java/main/gov/noaa/messageapi/protocols/DefaultProtocol.java index 290dffb..dbaff5f 100644 --- a/src/java/main/gov/noaa/messageapi/protocols/DefaultProtocol.java +++ b/src/java/main/gov/noaa/messageapi/protocols/DefaultProtocol.java @@ -9,7 +9,6 @@ import gov.noaa.messageapi.interfaces.IContainer; import gov.noaa.messageapi.interfaces.IProtocol; import gov.noaa.messageapi.interfaces.IConnection; -import gov.noaa.messageapi.protocols.BaseProtocol; import gov.noaa.messageapi.metadata.DefaultMetadata; import gov.noaa.messageapi.connections.DefaultConnection; import gov.noaa.messageapi.definitions.ContainerDefinition; diff --git a/src/java/main/gov/noaa/messageapi/rejections/DefaultRejection.java b/src/java/main/gov/noaa/messageapi/rejections/DefaultRejection.java index 9dc0471..9aba2c3 100644 --- a/src/java/main/gov/noaa/messageapi/rejections/DefaultRejection.java +++ b/src/java/main/gov/noaa/messageapi/rejections/DefaultRejection.java @@ -4,8 +4,6 @@ import java.util.List; import gov.noaa.messageapi.interfaces.IRecord; import gov.noaa.messageapi.interfaces.IRejection; -import gov.noaa.messageapi.rejections.BaseRejection; - /** * @author Ryan Berkheimer diff --git a/src/java/main/gov/noaa/messageapi/requests/DefaultRequest.java b/src/java/main/gov/noaa/messageapi/requests/DefaultRequest.java index e0c150c..6235776 100644 --- a/src/java/main/gov/noaa/messageapi/requests/DefaultRequest.java +++ b/src/java/main/gov/noaa/messageapi/requests/DefaultRequest.java @@ -8,7 +8,6 @@ import gov.noaa.messageapi.interfaces.IRequest; import gov.noaa.messageapi.interfaces.IResponse; import gov.noaa.messageapi.interfaces.IProtocol; -import gov.noaa.messageapi.requests.BaseRequest; import gov.noaa.messageapi.responses.DefaultResponse; diff --git a/src/java/main/gov/noaa/messageapi/responses/DefaultResponse.java b/src/java/main/gov/noaa/messageapi/responses/DefaultResponse.java index 362f0d2..2b59648 100644 --- a/src/java/main/gov/noaa/messageapi/responses/DefaultResponse.java +++ b/src/java/main/gov/noaa/messageapi/responses/DefaultResponse.java @@ -14,7 +14,6 @@ import gov.noaa.messageapi.interfaces.IPacket; import gov.noaa.messageapi.interfaces.IProtocolRecord; import gov.noaa.messageapi.interfaces.IContainerRecord; -import gov.noaa.messageapi.responses.BaseResponse; import gov.noaa.messageapi.requests.DefaultRequest; import gov.noaa.messageapi.utils.protocol.ConnectionUtils; diff --git a/src/java/main/gov/noaa/messageapi/schemas/DefaultSchema.java b/src/java/main/gov/noaa/messageapi/schemas/DefaultSchema.java index 13f88d6..f6306d5 100644 --- a/src/java/main/gov/noaa/messageapi/schemas/DefaultSchema.java +++ b/src/java/main/gov/noaa/messageapi/schemas/DefaultSchema.java @@ -8,7 +8,6 @@ import gov.noaa.messageapi.interfaces.ISchema; import gov.noaa.messageapi.interfaces.IRecord; import gov.noaa.messageapi.interfaces.IConditionOperator; -import gov.noaa.messageapi.schemas.BaseSchema; import gov.noaa.messageapi.metadata.DefaultMetadata; import gov.noaa.messageapi.records.schema.SchemaRecord; diff --git a/src/java/main/gov/noaa/messageapi/sessions/DefaultSession.java b/src/java/main/gov/noaa/messageapi/sessions/DefaultSession.java index 070b7c0..9890d76 100644 --- a/src/java/main/gov/noaa/messageapi/sessions/DefaultSession.java +++ b/src/java/main/gov/noaa/messageapi/sessions/DefaultSession.java @@ -6,7 +6,6 @@ import gov.noaa.messageapi.interfaces.IProtocol; import gov.noaa.messageapi.interfaces.IContainer; import gov.noaa.messageapi.interfaces.IRequest; -import gov.noaa.messageapi.sessions.BaseSession; import gov.noaa.messageapi.requests.DefaultRequest; /** diff --git a/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java index 5ee3647..ad93cdc 100644 --- a/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java +++ b/src/java/main/gov/noaa/messageapi/transformations/NativeTransformation.java @@ -6,8 +6,6 @@ import java.util.List; import gov.noaa.messageapi.interfaces.ITransformation; import gov.noaa.messageapi.interfaces.IRecord; -import gov.noaa.messageapi.transformations.BaseTransformation; - /** *

NativeTransformation

This is a wrapper class for transformations that call into * native code held as binary libs through the JNI (Java Native -- GitLab From ecbd8ba85eac98977ceaa8a02c387d60676691f0 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Thu, 2 Jul 2020 15:37:27 +0000 Subject: [PATCH 20/53] updated .gitignore with new build information. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index dd77303..bd57373 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ *.jnilib *.gch +#Development +.DS_Store #for gradle builds build/* @@ -14,6 +16,7 @@ build/* #for visual-studio-code bin/* .vscode/* +.devcontainer/* #for leiningen builds .lein* -- GitLab From 24731b88e2e6f4c8112035435f87f969f70abd56 Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Thu, 2 Jul 2020 17:39:40 +0000 Subject: [PATCH 21/53] update README (minor formatting) --- .gitignore | 1 + Makefile | 19 ++++++--- README.md | 6 +-- resources/ci_cd/docker/Dockerfile.develop | 42 +++++++++++++++++++ .../ci_cd/gitlab/.gitlab-ci.yml | 2 +- resources/test/basic-native/parameters.json | 2 +- .../native-transformation/parameters.json | 2 +- 7 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 resources/ci_cd/docker/Dockerfile.develop rename .gitlab-ci.yml => resources/ci_cd/gitlab/.gitlab-ci.yml (92%) diff --git a/.gitignore b/.gitignore index bd57373..f38dfe3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ build/* bin/* .vscode/* .devcontainer/* +*.code-workspace #for leiningen builds .lein* diff --git a/Makefile b/Makefile index e8cbf75..a4fa0fe 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,17 @@ .PHONY : install -all: install -install: - echo "Running gradle build for MessageAPI." - ${GRADLE} - echo "Finished gradle build for MessageAPI." + +all: build-c build-java + +build-c: + @echo "Building C/C++ binary for native transformation tests." + make -C $(PWD)/scripts/test/jni/demotransformationlibrary + @echo "building C/C++ binary for native endpoint tests." + make -C $(PWD)/scripts/test/jni/demoendpointlibrary + @echo "Finished building C/C++ binaries." + +build-java: + @echo "Running java gradle build and tests for MessageAPI." + @gradle + @echo "Finished java gradle build and tests for MessageAPI." diff --git a/README.md b/README.md index d39b966..735ab17 100644 --- a/README.md +++ b/README.md @@ -67,8 +67,6 @@ Figure 1 below illustrates the layout of a Session - how MessageAPI structures a Everything that passes data in MessageAPI consumes and produces the same object type - the record. The manifests are used in code by creating a session based on them - and then using a stable API to create a request, add records, set field and/or condition values, and then submit, which immediately returns an async response. The response will hold its own records and rejections, and eventually get an 'isComplete' flag. That's the entirety of the API surface. Everything else depends on the Manifest. -All of these actions are - MessageAPI is designed to be capable of passing any message content - objects, database entries, emails, etc., to/through anywhere - database tables, inboxes, s3 buckets, ftp, smtp, kafka, files, directories etc. The benefits of using MessageAPI are its extreme schema flexibility, potential for tool decoupling and transport optimization, API standardization across all messaging, and self documentation through an information model. @@ -133,7 +131,7 @@ The following is an example of a DefaultSession manifest: } ``` -The general pattern in a manifest is to declare a key with the class as the plugin, and then provide another map that holds constructor parameters. The specification for MessageAPI consists of +The general pattern in a manifest is to declare a key with the class as the plugin, and then provide another map that holds constructor parameters. The specification for MessageAPI consists of: - A **Session**, which holds the primary **Schema**, **Container**, and **Protocol** dimensions - A **Schema**, which defines all the **Fields** and **Conditions** (optional) a user will interact with for each **Record** @@ -283,7 +281,7 @@ In the provided implementation, the types understood by the system (for use by c ###### Condition Sets -Conditions can be set on fields that qualify records when passed in, serving as a potentially powerful filtering tool. In the provided default plugin, conditions must specify at least a unique id, a type, and an operator. Conditions that are to be used in filtering must be valued on individual records. Conditions are also provided on a whole-request basis - to be used in containerization of records. In this case, conditions can be given values when +Conditions can be set on fields that qualify records when passed in, serving as a potentially powerful dynamic filtering tool. In the provided default plugin, conditions must specify at least a unique id, a type, and an operator. Conditions that are to be used in filtering must be valued on individual records. Conditions are also provided on a whole-request basis - to be used in containerization of records. In this case, conditions can be given values on the request itself, to be used for parsing into collection-containers by applying to every potential record that is declared as part of a collection set. There are two condition types in the provided implementation - composite and comparison. diff --git a/resources/ci_cd/docker/Dockerfile.develop b/resources/ci_cd/docker/Dockerfile.develop new file mode 100644 index 0000000..2b55811 --- /dev/null +++ b/resources/ci_cd/docker/Dockerfile.develop @@ -0,0 +1,42 @@ +#Dockerfile for RHEL7 MessageAPI Build on UBI (Openshift Compatible) +#This dockerfile installs the system so that it can be interactively developed and built. +#All build tools are installed and paths are set properly. Some probing tools are also +#installed automatically for development. + +#Base Image (RHEL7 UBI) +FROM registry.access.redhat.com/ubi7/ubi:latest + +#Install standard RHEL7 tools +RUN yum -y install --disableplugin=subscription-manager \ + locate vim unzip wget git java-11-openjdk-devel gcc gcc-gfortran gcc-c++ make \ + && yum --disableplugin=subscription-manager clean all + +#Install Java Variables +RUN cd $(dirname $(readlink -f $(which java))) && cd .. \ + && export JAVA_HOME=$PWD \ + && touch /etc/profile.d/java.sh \ + && echo "export JAVA_HOME=${JAVA_HOME}" > /etc/profile.d/java.sh \ + && echo "export PATH=${JAVA_HOME}/bin:$PATH" >> /etc/profile.d/java.sh \ + && echo "export CLASSPATH=${JAVA_HOME}/bin:${CLASSPATH}" >> /etc/profile.d/java.sh + +#Install Gradle and Variables +RUN wget https://services.gradle.org/distributions/gradle-5.4.1-bin.zip -P /tmp \ + && unzip -d /opt/gradle /tmp/gradle-*.zip \ + && export GRADLE_HOME=/opt/gradle/gradle-5.4.1 \ + && touch /etc/profile.d/gradle.sh \ + && echo "export GRADLE_HOME=${GRADLE_HOME}" > /etc/profile.d/gradle.sh \ + && echo "export PATH=${GRADLE_HOME}/bin:$PATH" >> /etc/profile.d/gradle.sh + +#Add default type user 'messageapi' +RUN useradd messageapi + +#Change to new 'messageapi' user +USER messageapi + +#Set PATH and other user variables in bashrc +RUN cd $(dirname $(readlink -f $(which java))) && cd .. \ + && export JAVA_HOME=$PWD \ + && echo "PATH=${JAVA_HOME}/bin:\$PATH" >> ~/.bashrc \ + && export GRADLE_HOME=/opt/gradle/gradle-5.4.1 \ + && echo "PATH=${GRADLE_HOME}/bin:\$PATH" >> ~/.bashrc \ + && source ~/.bashrc \ No newline at end of file diff --git a/.gitlab-ci.yml b/resources/ci_cd/gitlab/.gitlab-ci.yml similarity index 92% rename from .gitlab-ci.yml rename to resources/ci_cd/gitlab/.gitlab-ci.yml index ff45d18..a5fd31c 100644 --- a/.gitlab-ci.yml +++ b/resources/ci_cd/gitlab/.gitlab-ci.yml @@ -1,4 +1,4 @@ -#Testing 123456789012345 +#Gitlab Runner Configuration for Automatic CI/CD stages: - test - build diff --git a/resources/test/basic-native/parameters.json b/resources/test/basic-native/parameters.json index bf0c8ca..0a6d164 100644 --- a/resources/test/basic-native/parameters.json +++ b/resources/test/basic-native/parameters.json @@ -27,7 +27,7 @@ "fields": ["initial-value", "string-test", "int-list-test"]}], "connections": [{"id": "1", "collections": ["coll-1"], - "constructor": {"native-library": "/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/lib/test/native/demoendpointlibrary/libDemoEndpointLibrary.jnilib", + "constructor": {"native-library": "/workspaces/messageapi/lib/test/native/demoendpointlibrary/libDemoEndpointLibrary.so", "default-fields": [{"id": "test-integer", "type": "integer", "required": false, diff --git a/resources/test/native-transformation/parameters.json b/resources/test/native-transformation/parameters.json index 5b2f276..1447b40 100644 --- a/resources/test/native-transformation/parameters.json +++ b/resources/test/native-transformation/parameters.json @@ -28,7 +28,7 @@ "id": "transform-1", "operator": "gov.noaa.messageapi.transformations.NativeTransformation", "constructor": { - "native-library": "/Users/rberkheimer/projects/asos/ingest/libraries/messageapi/lib/test/native/demotransformationlibrary/libDemoTransformationLibrary.jnilib" + "native-library": "/workspaces/messageapi/lib/test/native/demotransformationlibrary/libDemoTransformationLibrary.so" }, "records": {"test_key": {"COLLECTION": "collection-1"}}} ], -- GitLab From 31e32a77794319c389b22068b52d973529ae5d8f Mon Sep 17 00:00:00 2001 From: Ryan Berkheimer Date: Sun, 5 Jul 2020 20:37:49 -0400 Subject: [PATCH 22/53] completed initial integration of artifact delivery system --- Makefile | 62 +- README.md | 21 +- .../c/messageapi_1_0_0/messageapi.tar | Bin 0 -> 747520 bytes .../java/messageapi_0_0_10/messageapi.tar | Bin 0 -> 13844480 bytes dist/docs/api/allclasses-frame.html | 112 + dist/docs/api/deprecated-list.html | 106 + .../messageapi/conditions/BaseCondition.html | 351 +++ .../conditions/ComparisonCondition.html | 407 +++ .../conditions/CompositeCondition.html | 412 +++ .../messageapi/conditions/package-frame.html | 58 + .../conditions/package-summary.html | 165 ++ .../connections/DefaultConnection.html | 421 +++ .../messageapi/connections/package-frame.html | 58 + .../connections/package-summary.html | 144 + .../messageapi/containers/BaseContainer.html | 436 ++++ .../containers/DefaultContainer.html | 374 +++ .../messageapi/containers/package-frame.html | 58 + .../containers/package-summary.html | 152 ++ .../definitions/SchemaDefinition.html | 375 +++ .../messageapi/definitions/package-frame.html | 58 + .../definitions/package-summary.html | 146 ++ .../factories/ConditionTypeFactory.html | 272 ++ .../messageapi/factories/SessionFactory.html | 260 ++ .../factories/SimpleConditionFactory.html | 298 +++ .../messageapi/factories/package-frame.html | 58 + .../messageapi/factories/package-summary.html | 162 ++ .../noaa/messageapi/fields/DefaultField.html | 518 ++++ .../noaa/messageapi/fields/package-frame.html | 58 + .../messageapi/fields/package-summary.html | 144 + .../messageapi/interfaces/ICollection.html | 326 +++ .../interfaces/IComparisonCondition.html | 262 ++ .../messageapi/interfaces/IComponent.html | 307 +++ .../interfaces/ICompositeCondition.html | 262 ++ .../messageapi/interfaces/ICondition.html | 368 +++ .../interfaces/IConditionFactory.html | 258 ++ .../interfaces/IConditionOperator.html | 242 ++ .../messageapi/interfaces/IConnection.html | 380 +++ .../messageapi/interfaces/IContainer.html | 281 ++ .../interfaces/IContainerRecord.html | 279 ++ .../noaa/messageapi/interfaces/IEndpoint.html | 341 +++ .../noaa/messageapi/interfaces/IField.html | 432 +++ .../noaa/messageapi/interfaces/IMetadata.html | 313 +++ .../noaa/messageapi/interfaces/IPacket.html | 403 +++ .../messageapi/interfaces/IPluginParser.html | 237 ++ .../noaa/messageapi/interfaces/IProtocol.html | 287 ++ .../interfaces/IProtocolRecord.html | 378 +++ .../noaa/messageapi/interfaces/IRecord.html | 556 ++++ .../messageapi/interfaces/IRejection.html | 291 +++ .../noaa/messageapi/interfaces/IRequest.html | 476 ++++ .../noaa/messageapi/interfaces/IResponse.html | 404 +++ .../noaa/messageapi/interfaces/ISchema.html | 301 +++ .../noaa/messageapi/interfaces/ISession.html | 290 +++ .../interfaces/ITransformation.html | 261 ++ .../messageapi/interfaces/package-frame.html | 58 + .../interfaces/package-summary.html | 354 +++ .../messageapi/metadata/DefaultMetadata.html | 368 +++ .../messageapi/metadata/package-frame.html | 58 + .../messageapi/metadata/package-summary.html | 145 ++ .../conditions/BooleanConditionOperator.html | 286 ++ .../conditions/DateTimeConditionOperator.html | 286 ++ .../conditions/DoubleConditionOperator.html | 286 ++ .../conditions/FloatConditionOperator.html | 286 ++ .../conditions/IntegerConditionOperator.html | 286 ++ .../conditions/SimpleConditionOperator.html | 270 ++ .../conditions/StringConditionOperator.html | 268 ++ .../operators/conditions/package-frame.html | 58 + .../operators/conditions/package-summary.html | 192 ++ .../messageapi/packets/DefaultPacket.html | 529 ++++ .../messageapi/packets/package-frame.html | 58 + .../messageapi/packets/package-summary.html | 145 ++ .../noaa/messageapi/parsers/BaseParser.html | 465 ++++ .../parsers/containers/MetadataParser.html | 349 +++ .../parsers/containers/package-frame.html | 58 + .../parsers/containers/package-summary.html | 144 + .../messageapi/parsers/package-frame.html | 58 + .../messageapi/parsers/package-summary.html | 144 + .../parsers/plugins/BasePluginParser.html | 419 +++ .../plugins/ContainerPluginParser.html | 350 +++ .../parsers/plugins/ProtocolPluginParser.html | 350 +++ .../parsers/plugins/SchemaPluginParser.html | 350 +++ .../parsers/plugins/SessionPluginParser.html | 351 +++ .../parsers/plugins/package-frame.html | 58 + .../parsers/plugins/package-summary.html | 176 ++ .../parsers/protocols/ConnectionParser.html | 349 +++ .../parsers/protocols/MetadataParser.html | 349 +++ .../parsers/protocols/package-frame.html | 58 + .../parsers/protocols/package-summary.html | 152 ++ .../schemas/ConditionOperatorParser.html | 256 ++ .../parsers/schemas/ConditionParser.html | 349 +++ .../parsers/schemas/FieldParser.html | 349 +++ .../parsers/schemas/MetadataParser.html | 349 +++ .../parsers/schemas/package-frame.html | 58 + .../parsers/schemas/package-summary.html | 168 ++ .../messageapi/protocols/BaseProtocol.html | 436 ++++ .../messageapi/protocols/package-frame.html | 58 + .../messageapi/protocols/package-summary.html | 144 + .../messageapi/rejections/BaseRejection.html | 352 +++ .../rejections/DefaultRejection.html | 354 +++ .../messageapi/rejections/package-frame.html | 58 + .../rejections/package-summary.html | 152 ++ .../messageapi/requests/DefaultRequest.html | 368 +++ .../messageapi/requests/package-frame.html | 58 + .../messageapi/requests/package-summary.html | 144 + .../messageapi/responses/BaseResponse.html | 474 ++++ .../messageapi/responses/package-frame.html | 58 + .../messageapi/responses/package-summary.html | 144 + .../noaa/messageapi/schemas/BaseSchema.html | 436 ++++ .../messageapi/schemas/DefaultSchema.html | 402 +++ .../messageapi/schemas/package-frame.html | 58 + .../messageapi/schemas/package-summary.html | 152 ++ .../noaa/messageapi/sessions/BaseSession.html | 338 +++ .../messageapi/sessions/DefaultSession.html | 337 +++ .../messageapi/sessions/package-frame.html | 58 + .../messageapi/sessions/package-summary.html | 153 ++ .../transformations/BaseTransformation.html | 339 +++ .../transformations/NativeTransformation.html | 362 +++ .../transformations/package-frame.html | 58 + .../transformations/package-summary.html | 154 ++ .../reductions/ReduceTransformation.html | 332 +++ .../reductions/package-frame.html | 58 + .../reductions/package-summary.html | 144 + .../messageapi/utils/general/EnvUtils.html | 256 ++ .../messageapi/utils/general/JsonUtils.html | 398 +++ .../messageapi/utils/general/PathUtils.html | 278 ++ .../utils/general/package-frame.html | 58 + .../utils/general/package-summary.html | 160 ++ .../messageapi/utils/request/ReasonUtils.html | 277 ++ .../utils/request/package-frame.html | 58 + .../utils/request/package-summary.html | 145 ++ dist/docs/api/groovy.ico | Bin 0 -> 9662 bytes dist/docs/api/help-doc.html | 196 ++ dist/docs/api/index-all.html | 1280 +++++++++ dist/docs/api/index.html | 90 + dist/docs/api/inherit.gif | Bin 0 -> 57 bytes dist/docs/api/overview-frame.html | 117 + dist/docs/api/overview-summary.html | 274 ++ dist/docs/api/package-list | 25 + dist/docs/api/stylesheet.css | 2306 +++++++++++++++++ lib/main/.gitignore | 0 .../native/demosession/libDemoSession.dylib | Bin 126916 -> 0 bytes .../{ci_cd => }/docker/Dockerfile.develop | 0 resources/{ci_cd => }/gitlab/.gitlab-ci.yml | 0 .../test/file-reader-native/manifest.json | 26 + .../test/file-reader-native/parameters.json | 11 + scripts/build/c/main/Makefile | 159 ++ .../c/test/endpoint}/Makefile | 2 +- .../c/test/session}/Makefile | 2 +- .../c/test/transformation}/Makefile | 2 +- scripts/install/c/main/install.sh | 5 + scripts/install/java/main/install.sh | 4 + scripts/install/package/install.sh | 3 + scripts/main/.gitignore | 0 .../{common => }/structs/messageapi_structs.h | 0 ...noaa_messageapi_endpoints_NativeEndpoint.h | 0 ...api_transformations_NativeTransformation.h | 0 .../EndpointWrapper.c | 0 ...noaa_messageapi_endpoints_NativeEndpoint.h | 37 + .../sessions/demosession/NativeSessionDemo.c | 17 - src/c/test/sessions/demosession/compile.sh | 6 - .../native_session/NativeSessionDemo.c | 74 + .../sessions/native_session/compile_rhel7.sh | 11 + .../native_session/nativesessiondemo.bin | Bin 0 -> 13176 bytes .../TransformationWrapper.c | 0 ...api_transformations_NativeTransformation.h | 37 + .../endpoint}/MessageApiEndpoint.cpp | 0 .../endpoint}/MessageApiEndpoint.h | 0 .../session}/MessageApiSession.cpp | 1 - .../session}/MessageApiSession.h | 0 .../MessageApiTransformation.cpp | 0 .../MessageApiTransformation.h | 0 src/cpp/main/common/MessageApiSessionLib.h | 196 -- .../endpoint}/MessageApiEndpointLib.cpp | 0 .../endpoint}/MessageApiEndpointLib.h | 0 .../session}/MessageApiSessionLib.cpp | 18 +- .../main/libs/session/MessageApiSessionLib.h | 196 ++ .../MessageApiTransformationLib.cpp | 0 .../MessageApiTransformationLib.h | 0 .../api/condition}/ConditionUtils.cpp | 0 .../api/condition}/ConditionUtils.h | 0 .../api/endpoint}/EndpointUtils.cpp | 0 .../api/endpoint}/EndpointUtils.h | 0 .../api/field}/FieldUtils.cpp | 2 +- .../{common => utils/api/field}/FieldUtils.h | 0 .../api/packet}/PacketUtils.cpp | 0 .../api/packet}/PacketUtils.h | 0 .../records/protocol}/ProtocolRecordUtils.cpp | 0 .../records/protocol}/ProtocolRecordUtils.h | 0 .../api/records/schema}/RecordUtils.cpp | 0 .../api/records/schema}/RecordUtils.h | 0 .../api/rejection}/RejectionUtils.cpp | 0 .../api/rejection}/RejectionUtils.h | 0 .../api/request}/RequestUtils.cpp | 0 .../api/request}/RequestUtils.h | 0 .../api/response}/ResponseUtils.cpp | 0 .../api/response}/ResponseUtils.h | 0 .../api/session}/SessionUtils.cpp | 0 .../api/session}/SessionUtils.h | 0 .../transformation}/TransformationUtils.cpp | 0 .../api/transformation}/TransformationUtils.h | 0 .../general/jni}/JniUtils.cpp | 2 +- .../{common => utils/general/jni}/JniUtils.h | 0 .../general/list}/ListUtils.cpp | 0 .../general/list}/ListUtils.h | 0 .../general/map}/MapUtils.cpp | 0 .../{common => utils/general/map}/MapUtils.h | 0 .../general/type}/TypeUtils.cpp | 0 .../general/type}/TypeUtils.h | 0 .../utils/protocol/ConnectionUtils.java | 2 +- 208 files changed, 35932 insertions(+), 243 deletions(-) create mode 100644 dist/artifacts/c/messageapi_1_0_0/messageapi.tar create mode 100644 dist/artifacts/java/messageapi_0_0_10/messageapi.tar create mode 100644 dist/docs/api/allclasses-frame.html create mode 100644 dist/docs/api/deprecated-list.html create mode 100644 dist/docs/api/gov/noaa/messageapi/conditions/BaseCondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/conditions/ComparisonCondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/conditions/CompositeCondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/conditions/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/conditions/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/connections/DefaultConnection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/connections/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/connections/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/containers/BaseContainer.html create mode 100644 dist/docs/api/gov/noaa/messageapi/containers/DefaultContainer.html create mode 100644 dist/docs/api/gov/noaa/messageapi/containers/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/containers/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/definitions/SchemaDefinition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/definitions/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/definitions/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/factories/ConditionTypeFactory.html create mode 100644 dist/docs/api/gov/noaa/messageapi/factories/SessionFactory.html create mode 100644 dist/docs/api/gov/noaa/messageapi/factories/SimpleConditionFactory.html create mode 100644 dist/docs/api/gov/noaa/messageapi/factories/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/factories/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/fields/DefaultField.html create mode 100644 dist/docs/api/gov/noaa/messageapi/fields/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/fields/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ICollection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IComparisonCondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IComponent.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ICompositeCondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ICondition.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IConditionFactory.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IConnection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IContainer.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IContainerRecord.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IEndpoint.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IField.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IMetadata.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IPacket.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IPluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IProtocol.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IProtocolRecord.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IRecord.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IRejection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IRequest.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/IResponse.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ISchema.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ISession.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/ITransformation.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/interfaces/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/metadata/DefaultMetadata.html create mode 100644 dist/docs/api/gov/noaa/messageapi/metadata/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/metadata/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/BooleanConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/DateTimeConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/DoubleConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/FloatConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/IntegerConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/SimpleConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/StringConditionOperator.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/operators/conditions/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/packets/DefaultPacket.html create mode 100644 dist/docs/api/gov/noaa/messageapi/packets/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/packets/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/BaseParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/containers/MetadataParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/containers/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/containers/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/BasePluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/ContainerPluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/ProtocolPluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/SchemaPluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/SessionPluginParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/plugins/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/protocols/ConnectionParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/protocols/MetadataParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/protocols/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/protocols/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/ConditionOperatorParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/ConditionParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/FieldParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/MetadataParser.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/parsers/schemas/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/protocols/BaseProtocol.html create mode 100644 dist/docs/api/gov/noaa/messageapi/protocols/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/protocols/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/rejections/BaseRejection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/rejections/DefaultRejection.html create mode 100644 dist/docs/api/gov/noaa/messageapi/rejections/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/rejections/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/requests/DefaultRequest.html create mode 100644 dist/docs/api/gov/noaa/messageapi/requests/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/requests/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/responses/BaseResponse.html create mode 100644 dist/docs/api/gov/noaa/messageapi/responses/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/responses/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/schemas/BaseSchema.html create mode 100644 dist/docs/api/gov/noaa/messageapi/schemas/DefaultSchema.html create mode 100644 dist/docs/api/gov/noaa/messageapi/schemas/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/schemas/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/sessions/BaseSession.html create mode 100644 dist/docs/api/gov/noaa/messageapi/sessions/DefaultSession.html create mode 100644 dist/docs/api/gov/noaa/messageapi/sessions/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/sessions/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/BaseTransformation.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/NativeTransformation.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/reductions/ReduceTransformation.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/reductions/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/transformations/reductions/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/general/EnvUtils.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/general/JsonUtils.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/general/PathUtils.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/general/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/general/package-summary.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/request/ReasonUtils.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/request/package-frame.html create mode 100644 dist/docs/api/gov/noaa/messageapi/utils/request/package-summary.html create mode 100644 dist/docs/api/groovy.ico create mode 100644 dist/docs/api/help-doc.html create mode 100644 dist/docs/api/index-all.html create mode 100644 dist/docs/api/index.html create mode 100644 dist/docs/api/inherit.gif create mode 100644 dist/docs/api/overview-frame.html create mode 100644 dist/docs/api/overview-summary.html create mode 100644 dist/docs/api/package-list create mode 100644 dist/docs/api/stylesheet.css delete mode 100644 lib/main/.gitignore delete mode 100755 lib/test/native/demosession/libDemoSession.dylib rename resources/{ci_cd => }/docker/Dockerfile.develop (100%) rename resources/{ci_cd => }/gitlab/.gitlab-ci.yml (100%) create mode 100644 resources/test/file-reader-native/manifest.json create mode 100644 resources/test/file-reader-native/parameters.json create mode 100644 scripts/build/c/main/Makefile rename scripts/{test/jni/demoendpointlibrary => build/c/test/endpoint}/Makefile (98%) rename scripts/{test/jni/demosession => build/c/test/session}/Makefile (98%) rename scripts/{test/jni/demotransformationlibrary => build/c/test/transformation}/Makefile (98%) create mode 100755 scripts/install/c/main/install.sh create mode 100644 scripts/install/java/main/install.sh create mode 100644 scripts/install/package/install.sh delete mode 100644 scripts/main/.gitignore rename src/c/main/{common => }/structs/messageapi_structs.h (100%) rename src/c/{test/endpoints/demoendpointlibrary => main/wrappers/endpoint}/gov_noaa_messageapi_endpoints_NativeEndpoint.h (100%) rename src/c/{test/transformations/demotransformationlibrary => main/wrappers/transformation}/gov_noaa_messageapi_transformations_NativeTransformation.h (100%) rename src/c/test/endpoints/{demoendpointlibrary => endpoint_lib}/EndpointWrapper.c (100%) create mode 100644 src/c/test/endpoints/endpoint_lib/gov_noaa_messageapi_endpoints_NativeEndpoint.h delete mode 100644 src/c/test/sessions/demosession/NativeSessionDemo.c delete mode 100755 src/c/test/sessions/demosession/compile.sh create mode 100644 src/c/test/sessions/native_session/NativeSessionDemo.c create mode 100755 src/c/test/sessions/native_session/compile_rhel7.sh create mode 100755 src/c/test/sessions/native_session/nativesessiondemo.bin rename src/c/test/transformations/{demotransformationlibrary => transformation_lib}/TransformationWrapper.c (100%) create mode 100644 src/c/test/transformations/transformation_lib/gov_noaa_messageapi_transformations_NativeTransformation.h rename src/cpp/main/{common => api/endpoint}/MessageApiEndpoint.cpp (100%) rename src/cpp/main/{common => api/endpoint}/MessageApiEndpoint.h (100%) rename src/cpp/main/{common => api/session}/MessageApiSession.cpp (99%) rename src/cpp/main/{common => api/session}/MessageApiSession.h (100%) rename src/cpp/main/{common => api/transformation}/MessageApiTransformation.cpp (100%) rename src/cpp/main/{common => api/transformation}/MessageApiTransformation.h (100%) delete mode 100644 src/cpp/main/common/MessageApiSessionLib.h rename src/cpp/main/{common => libs/endpoint}/MessageApiEndpointLib.cpp (100%) rename src/cpp/main/{common => libs/endpoint}/MessageApiEndpointLib.h (100%) rename src/cpp/main/{common => libs/session}/MessageApiSessionLib.cpp (98%) create mode 100644 src/cpp/main/libs/session/MessageApiSessionLib.h rename src/cpp/main/{common => libs/transformation}/MessageApiTransformationLib.cpp (100%) rename src/cpp/main/{common => libs/transformation}/MessageApiTransformationLib.h (100%) rename src/cpp/main/{common => utils/api/condition}/ConditionUtils.cpp (100%) rename src/cpp/main/{common => utils/api/condition}/ConditionUtils.h (100%) rename src/cpp/main/{common => utils/api/endpoint}/EndpointUtils.cpp (100%) rename src/cpp/main/{common => utils/api/endpoint}/EndpointUtils.h (100%) rename src/cpp/main/{common => utils/api/field}/FieldUtils.cpp (99%) rename src/cpp/main/{common => utils/api/field}/FieldUtils.h (100%) rename src/cpp/main/{common => utils/api/packet}/PacketUtils.cpp (100%) rename src/cpp/main/{common => utils/api/packet}/PacketUtils.h (100%) rename src/cpp/main/{common => utils/api/records/protocol}/ProtocolRecordUtils.cpp (100%) rename src/cpp/main/{common => utils/api/records/protocol}/ProtocolRecordUtils.h (100%) rename src/cpp/main/{common => utils/api/records/schema}/RecordUtils.cpp (100%) rename src/cpp/main/{common => utils/api/records/schema}/RecordUtils.h (100%) rename src/cpp/main/{common => utils/api/rejection}/RejectionUtils.cpp (100%) rename src/cpp/main/{common => utils/api/rejection}/RejectionUtils.h (100%) rename src/cpp/main/{common => utils/api/request}/RequestUtils.cpp (100%) rename src/cpp/main/{common => utils/api/request}/RequestUtils.h (100%) rename src/cpp/main/{common => utils/api/response}/ResponseUtils.cpp (100%) rename src/cpp/main/{common => utils/api/response}/ResponseUtils.h (100%) rename src/cpp/main/{common => utils/api/session}/SessionUtils.cpp (100%) rename src/cpp/main/{common => utils/api/session}/SessionUtils.h (100%) rename src/cpp/main/{common => utils/api/transformation}/TransformationUtils.cpp (100%) rename src/cpp/main/{common => utils/api/transformation}/TransformationUtils.h (100%) rename src/cpp/main/{common => utils/general/jni}/JniUtils.cpp (92%) rename src/cpp/main/{common => utils/general/jni}/JniUtils.h (100%) rename src/cpp/main/{common => utils/general/list}/ListUtils.cpp (100%) rename src/cpp/main/{common => utils/general/list}/ListUtils.h (100%) rename src/cpp/main/{common => utils/general/map}/MapUtils.cpp (100%) rename src/cpp/main/{common => utils/general/map}/MapUtils.h (100%) rename src/cpp/main/{common => utils/general/type}/TypeUtils.cpp (100%) rename src/cpp/main/{common => utils/general/type}/TypeUtils.h (100%) diff --git a/Makefile b/Makefile index a4fa0fe..98b79e5 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,63 @@ -.PHONY : install +#Primary Makefile for the MessageAPI package. +#This Makefile currently controls the Gradle build for Java and subsequent artifact packaging, +#the C/C++ library build and subsequent artifact packaging, and API documentation packaging. +#Library Name and Version +LIBRARY_NAME=messageapi +MAJOR_VERSION=0 +MINOR_VERSION=0 +PATCH_VERSION=10 +#Root Path Computation +PROJECT_ROOT:=$(PWD) -all: build-c build-java +#Java Related Paths +JAR_SRC_DIR=$(PROJECT_ROOT)/build/libs +SRC_JAR=messageapi-$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION)-all.jar +JAVA_ARTIFACT_DIR=$(PROJECT_ROOT)/dist/artifacts/java/$(LIBRARY_NAME)_$(MAJOR_VERSION)_$(MINOR_VERSION)_$(PATCH_VERSION) +TARGET_JAR=messageapi-core-$(MAJOR_VERSION).$(MINOR_VERSION).$(PATCH_VERSION).jar +JAR_INSTALL_SCRIPT=$(PROJECT_ROOT)/scripts/install/java/main/install.sh -build-c: - @echo "Building C/C++ binary for native transformation tests." - make -C $(PWD)/scripts/test/jni/demotransformationlibrary - @echo "building C/C++ binary for native endpoint tests." - make -C $(PWD)/scripts/test/jni/demoendpointlibrary - @echo "Finished building C/C++ binaries." +DOCS_SRC_DIR=$(PROJECT_ROOT)/build/docs/groovydoc +API_DOCS_DIR=$(PROJECT_ROOT)/dist/docs/api + +#C/C++ Related Paths +C_MAIN_BUILD_DIR=$(PROJECT_ROOT)/scripts/build/c/main + +.PHONY: build-c_cpp prep-java build-java dist-java copy-docs + +all: build-c_cpp prep-java build-java dist-java copy-docs + +build-c_cpp: + @echo "Building the shared library for C/C++ native sessions and the distributable native C artifacts." + @make -C $(C_MAIN_BUILD_DIR) + #@echo "Building C/C++ binary for native transformation tests." + #make -C $(PWD)/scripts/build/c/test/transformation + #@echo "building C/C++ binary for native endpoint tests." + #make -C $(PWD)/scripts/build/c/test/endpoint + @echo "Finished all C/C++ related build tasks." + +prep-java: + @echo "Cleaning any residual Java artifacts." + @rm -rf $(JAVA_ARTIFACT_DIR) + @rm -rf $(API_DOCS_DIR) + @echo "Java ready for build." build-java: @echo "Running java gradle build and tests for MessageAPI." @gradle @echo "Finished java gradle build and tests for MessageAPI." + +dist-java: + @echo "Creating distributable Java artifacts." + @cp $(JAR_SRC_DIR)/$(SRC_JAR) $(JAR_SRC_DIR)/$(TARGET_JAR) + @cp $(JAR_INSTALL_SCRIPT) $(JAR_SRC_DIR) + @mkdir -p $(JAVA_ARTIFACT_DIR) + @-cd $(JAR_SRC_DIR) && tar -cf $(LIBRARY_NAME).tar $(TARGET_JAR) install.sh + @-cd $(JAR_SRC_DIR) && mv $(LIBRARY_NAME).tar $(JAVA_ARTIFACT_DIR) + +copy-docs: + @echo "Copying API docs for distribution." + @mkdir -p $(API_DOCS_DIR) + @cp -R $(DOCS_SRC_DIR)/* $(API_DOCS_DIR) + @echo "Finished copying API docs for distribution." \ No newline at end of file diff --git a/README.md b/README.md index 735ab17..85771d4 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,14 @@ ## Version -**0.9.0** (Pre-Release) +**0.9.10** (Pre-Release) MessageAPI uses [Semantic Versioning 2.0.0](https://semver.org/) as its versioning strategy. The first official version will be released upon the implementation of the C native API. Subsequent minor versions will release the fortran, python, IDL, and R APIs. +## API Docs + +Use of this package is described throughout this README through design discussions and examples. Once familiar with the general use case of the package, more complete [API Docs](./dist/docs/api/index.html) can be referenced. + ## Overview MessageAPI is a structured-data-processing specification designed to allow the development of decomplected, transparent, easily understood, evolutionary, and highly configurable process oriented systems. MessageAPI does this by drawing a domain distinction between process structure (the 'Message' of MessageAPI) and data (the 'API' part) and then providing complimentary orthonormal bases that span each space. The structure and data domain definitions of MessageAPI are based on the principles of generic programming and designed using the language of Communicating Sequential Processes (CSP) in order to be easily picked up and understood by different audiences and users. @@ -708,7 +712,13 @@ Because requests contain a copy of the session variables which created them, the ##### Package Use -When installed from source or acquired through repository, the MessageAPI-all.jar contains all dependencies required to run standalone. Because of the way MessageAPI handles Session bootstrapping, it is not required to bundle the MessageAPI core with user ConditionFactories, TransformationFactories, or Endpoints. As long as these are made available to MessageAPI on the Java classpath at Session creation, Sessions will be able to use them. This design makes it easier to automate things like creating K8s pods of certain session types. +###### Prebuilt Resources +The package can be retrieved and used as a precompiled set of artifacts packaged as tar files. There are currently tar files for the core Java library and the precompiled C/C++ native library (compiled using the RHEL7 UBI, which is freely available from Redhat and compatible with Openshift). Each tar comes with an install.sh file that will install the relevant component for the current user. This means that for the Java package, the MessageAPI jar will be installed to a user directory, which will be added to the PATH and the Jar will be added to the CLASSPATH (if not already installed). The C library will add the shared library to the PATH and set up environment variables for use of the packaged header and source files. No root privileges are required to install or use the precompiled package resources. + +###### Building From Source +When acquired through repository, the package can be built from source in order to run included tests. A Dockerfile for building the package is included in the resources/docker directory - this Dockerfile is based on the RHEL7 UBI and contains all necessary packages needed to build the MessageAPI system. This file can be used as-is or as a reference to guide what resources and conditions are necessary. + +Important to note - because of the way MessageAPI handles Session bootstrapping, it is not required to bundle the MessageAPI core with user ConditionFactories, TransformationFactories, or Endpoints. As long as these are made available to MessageAPI on the Java classpath at Session creation, Sessions will be able to use them. This design makes it easier to automate things like creating K8s pods of certain session types. If installed from precom If desired or needed, MessageAPI can be bundled into other JARS or packages containing user Factories and Endpoints for portability, performance, security, or other reasons. @@ -718,7 +728,7 @@ If desired or needed, MessageAPI can be bundled into other JARS or packages cont ## Installation and Deployment -At the time of this writing, MessageAPI (0.0.10-PRERELEASE) was built using OpenJDK 11.0.3 with gradle 5.4.1. Older JDK versions are not guaranteed to work. +At the time of this writing, MessageAPI was built using OpenJDK 11.0.3 with gradle 5.4.1. Older JDK versions are not guaranteed to work. There was a breaking change between older versions of gradle and the 5 series, and a relative path resolution method was updated to accommodate this change. If building from scratch, the gradle version must be upgraded to 5.4.1+. @@ -740,10 +750,9 @@ Other dependencies are installed for the purposes of running tests, including Gr In addition to reading issue, tag, and push history in the git repository, developers may refer to the more detailed [developer work log history](./DeveloperWorkLog.md). This document outlines features currently and previously under focus, providing motivations, descriptions, design behaviors, and justifications. -### Bugs +### Bugs and Feature Requests -The package is in current, active development. -All bugs encountered should be reported to ryan.berkheimer@noaa.gov. +The package is in current, active development, and as such, some bugs or desired features are expected. Either type of note can be sent on to ryan.berkheimer@noaa.gov. ## License diff --git a/dist/artifacts/c/messageapi_1_0_0/messageapi.tar b/dist/artifacts/c/messageapi_1_0_0/messageapi.tar new file mode 100644 index 0000000000000000000000000000000000000000..c544f2cb72418cbd67e2539e32707e1c19cf8433 GIT binary patch literal 747520 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 literal 0 HcmV?d00001 diff --git a/dist/artifacts/java/messageapi_0_0_10/messageapi.tar b/dist/artifacts/java/messageapi_0_0_10/messageapi.tar new file mode 100644 index 0000000000000000000000000000000000000000..121f0a9f8a5d77f7e538c838e146e0fe9acbcc39 GIT binary patch literal 13844480 zcmd43b9Cg}x;C10(6MdXcE`4D+eXK>*|BZgwrzB5->iMUv%j@*&f0g3`^T+}%5S7< z&RMfkub$_9W?30IIOv%e>Dii58`#(zQPa`T(a_V;nCsaC{C{?%`?|5PFadmB=vkTR z{(NO&VxebXq@x3%XJnp00096KyE*f{bRe|{?DGlzphe3ihR^!(!#Vr0RK2Jj~N7B z>}!C|*B$B41Eu(+#e{_v6ltV{Z>7e^BqgY6W}qdgDJI9K>g4I>8MhB^#;J$JCZr}P z#i#%wPJ;}S_Vd-r_X|-_NehcePz+B=4)=A7{V?^iO|nhEm;#d_|Mb$J|FlQoua`El zasG$x{qvYV-p3zftZnr4{?~zjypO*R{J$Uf|2hZjf0$#dXYXKS@9@9QCHjlGww6vN zX4e0@hP$M_k`xdC0P=SL0IvUV4Fv;JBP%`GzpW_yx4qFASn4@AWGbn-%n2iX7;?(x zl5x^YXe`FD+4CZOE06+{ShnL=f9wY5lG+a?I2{&_V?V&Xr}xq`lVSI|h~B-LP$k)9 zvvrL*Je}-#e7#`E``r3`hv_EpuAvLPC80@CWwM*;1*R!kibi2*F3b(1oYIUVJvM@`QZc=vNhUWrJr+L z4PJAvW*Nq?0U=$r=^74`rL#{CD7n+R6q?FAbPpPSOu8v>%4o@qXK=+VJ@vv(PfKaY zY~Jzg!f;g|=+K#39ktD!$o=u?H6z)s3S^1mLYwm#Ii+@yeZX5TQ9r)&=%bjsIK`6Lf})+waW1K z3~tH*7U2PtKUYnUDM|qs`#5|Xuj9aAPNYz~0h@Fe7kgH>m_F)LM(-m>QoKF)#LyyC z;yYCV`^46j)ak?X(J}Y08∨!q1-JLyP5t-T7mU2&1d!W)UZ4M65Y-oB=p7vTv_O zY0^2tPgQoZhEFJ=g~q_)w%Y)wVIhC0R4^Lz7azt;j%I zb9%qWx7SWT*f_SFpCzgRIk~_zF^{d&k@l!G`eME%xwwx5hrZt=dTImu>&?*+PIh-@%Xar#5MWdC+nXRPj3iZs_KNoiBj2zbQixlNYz9K)OH!V zBfv~0W+HDmqs=9^9Mv$GAS+bSE$vknsg#?q)N{W>-9C9%XTeGrif)zJ3fMM15%6(8 zE^i}mIabIJ3S6gb^4EGXEPxjg{?8f}3t z${%BLH{+X(e{^X;D0-23Vr}D|iGN$xeX^@_S28rGHJ8OIUui7??}d!$v9)wjkjiyh z5Hgqim1-YFkSS8oDF#o!2sDMBEfXomMXFykv!|a7vS;CrgJ;f;6V~ii!PNt$rxbM; zcvp8j@n{MdS=A1vC#Bxar=%!Fud+EH*S81D7oGHUXnZ6gF^Kcy{+goXmI*E6liP8f zR(v9)*s+sIbj2SOXM{u4Zs}SxR~x3R6Q_u+r_UKYJa$FmJa>Vnb2CTar}5uR#`0sD zkDA9K0ESjmTzd*i)XvTNuss1yP2~9F=F1?*OK(s`|*)viLAbco<{uKl-jalZyJ$2+BIsb9f13JFnIfK`rY1Mjt`|Ez$66 z!!jwD_3<>f86&&{GGOi3AtkaifbYXu%`9}06uk{JiCKhyO=Y2Pmy}^cdY^IMzqxMmZxObHGG)X_}a75Gb77-M{xT7dS$8ySEgjR!|ud zP#GiEh`#68l)zSn^tu{3!LvVk3I<+=O}he4wBU z8 z#KI$XcVbN(S}qYCs2{lk-UvPjrjWlF??4YU3o;(%7hlP3`j}xs%{yVYxi$$rc3tj4 z)Ca!(=wm@JscWcHiwm74!GDkR4)m4?#?dC|$68>&n~uV8I%d7wQXi^p;TQIZ@

o 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%0Do=?$Abk3t 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