diff --git a/Makefile b/Makefile index ac7a7f5..1b24fcc 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -MSI_JSON_UTILS = msi_json_arrayops +MSI_JSON_UTILS = msi_json_arrayops msi_json_objops MSI_ADMIN_UTILS = msi_unmount MAKEFLAGS += --no-print-directory diff --git a/msi_json_objops/Makefile b/msi_json_objops/Makefile new file mode 100644 index 0000000..9da78ec --- /dev/null +++ b/msi_json_objops/Makefile @@ -0,0 +1,12 @@ +GCC = g++ + +INC=-I/usr/include/irods/ -I/usr/include/irods/boost/ -I/usr/include/irods/jansson/src + +all: libmsi_json_objops + +libmsi_json_objops: + ${GCC} ${INC} -DRODS_SERVER -fPIC "-Wl,-E" -shared -g -Wno-deprecated -rdynamic -o $@.so $@.cpp /usr/lib/libirods_client.a /usr/lib/irods/externals/libjansson.a + + +clean: + @rm -f ./*.so diff --git a/msi_json_objops/README.md b/msi_json_objops/README.md new file mode 100644 index 0000000..a1cdf99 --- /dev/null +++ b/msi_json_objops/README.md @@ -0,0 +1,32 @@ +# msi_json_objops + +Add/set/get/rm element of a given JSON object. + +### Copyright and license + +This microservice has kindly been provided by the Donders Institute for +Brain, Cognition and Behaviour. + +Copyright (c) 2016, Radboud University, Nijmegen, The Netherlands +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADV \ No newline at end of file diff --git a/msi_json_objops/libmsi_json_objops.cpp b/msi_json_objops/libmsi_json_objops.cpp new file mode 100644 index 0000000..1ec7540 --- /dev/null +++ b/msi_json_objops/libmsi_json_objops.cpp @@ -0,0 +1,140 @@ +// =-=-=-=-=-=-=- +#include "apiHeaderAll.hpp" +#include "msParam.hpp" +#include "reGlobalsExtern.hpp" +#include "irods_ms_plugin.hpp" +#include "reFuncDefs.hpp" +#include "jansson.h" + +// =-=-=-=-=-=-=- +// STL/boost Includes +#include +#include +#include +#include + +extern "C" { + // =-=-=-=-=-=-=- + int msi_json_objops_impl(msParam_t* json_str, msParam_t* kvp, msParam_t* ops, ruleExecInfo_t* rei) { + using std::cout; + using std::endl; + using std::string; + + char *null_cstr = new char[5]; + char *true_cstr = new char[5]; + char *false_cstr = new char[6]; + + strcpy(null_cstr, "null"); + strcpy(true_cstr, "true"); + strcpy(false_cstr, "false"); + + // input type check + const char *inJsonStr = parseMspForStr( json_str ); + const char *inOps = parseMspForStr( ops ); + if( ! inJsonStr || ! inOps) { + cout << "msi_json_objops - invalid input for string" << endl; + return SYS_INVALID_INPUT_PARAM; + } + + if (kvp == NULL || kvp->inOutStruct == NULL || + kvp->type == NULL || strcmp(kvp->type, KeyValPair_MS_T) != 0) { + cout << "msi_json_objops - invalid input for key-value pairs" << endl; + return SYS_INVALID_INPUT_PARAM; + } + + keyValPair_t *inKVP; + inKVP = (keyValPair_t*) kvp->inOutStruct; + + string strOps(inOps); + + json_error_t error; + json_t *root; + + // try to make initial inJsonStr if it's an empty string + if ( strcmp(inJsonStr, "") == 0 ) { + inJsonStr = "{}"; + } + + // try to load JSON object + root = json_loads(inJsonStr, 0, &error); + if ( ! root ) { + cout << "msi_json_objops - invalid json document" << endl; + json_decref(root); + return SYS_INVALID_INPUT_PARAM; + } + + for (int ik=0; iklen; ik++) { + + char* inKey = inKVP->keyWord[ik]; + char* inVal = inKVP->value[ik]; + + json_t *jval; + if (strcmp(inVal, null_cstr) == 0) { + jval = json_null(); + } else { + jval = json_loads(inVal, 0, &error); + if ( ! jval ) jval = json_string(inVal); + } + + // try to find objects in the key + json_t *data = json_object_get(root, inKey); + + if ( strOps == "get" ) { + if ( json_is_null(data) ) { + inKVP->value[ik] = null_cstr; + } else if ( json_is_true(data) ) { + inKVP->value[ik] = true_cstr; + } else if ( json_is_false(data) ) { + inKVP->value[ik] = false_cstr; + } else if ( json_is_string(data) ) { + const char* val_str = json_string_value(data); + char *val_cstr = new char[strlen(val_str) + 1]; + strcpy(val_cstr, val_str); + inKVP->value[ik] = val_cstr; + } else { + inKVP->value[ik] = json_dumps(data,0); + } + } else if ( strOps == "add" ) { + if (json_is_array( data )) { + json_array_append_new(data, jval); + } else { + json_object_set_new(root, inKey, jval); + } + } else if ( strOps == "set" ) { + json_object_set_new(root, inKey, jval); + } else if ( strOps == "rm" ) { + if ( data ) { + if ( json_is_array( data ) ) { + size_t i_match = json_array_size(data); + for( int i=0; iinOutStruct = (void *) inKVP; + kvp->type = (char *) strdup(KeyValPair_MS_T); + + fillStrInMsParam(json_str, json_dumps(root, 0)); + + json_decref(root); + + // Done + return 0; + } + + irods::ms_table_entry* plugin_factory() { + irods::ms_table_entry* msvc = new irods::ms_table_entry(3); + + msvc->add_operation("msi_json_objops_impl", "msi_json_objops"); + + return msvc; + } + +} // extern "C" diff --git a/msi_json_objops/msi_json_objops_test.r b/msi_json_objops/msi_json_objops_test.r new file mode 100644 index 0000000..10697a5 --- /dev/null +++ b/msi_json_objops/msi_json_objops_test.r @@ -0,0 +1,42 @@ +myTestRule { + + *json_str = ""; + + ## build JSON object from key-value pairs + msiString2KeyValPair("", *kvp); + msiAddKeyVal(*kvp, 'type', 'DATA_SHARING'); + msiAddKeyVal(*kvp, 'collId', '12345'); + msiAddKeyVal(*kvp, 'title', 'DICOM 原生資料備份'); + msiAddKeyVal(*kvp, 'creatorList', '["U505173-ru.nl","hurngchunlee-icloud.com"]'); + msiAddKeyVal(*kvp, 'associatedPublication', '[{"type":"PMID", "id":"654321"}]'); + + *ec = errorcode( msi_json_objops(*json_str, *kvp, "add") ); + writeLine("stdout", *json_str); + + ## modify JSON object (add/set/get/rm) + msiString2KeyValPair("", *kvp); + msiAddKeyVal(*kvp, 'associatedPublication', '{"type":"arXiv", "id":"xyz/123"}'); + *ec = errorcode( msi_json_objops(*json_str, *kvp, "add") ); + writeLine("stdout", *json_str); + + msiString2KeyValPair("", *kvp); + msiAddKeyVal(*kvp, 'associatedPublication', '{"type":"PMID", "id":"654321"}'); + *ec = errorcode( msi_json_objops(*json_str, *kvp, "rm") ); + writeLine("stdout", *json_str); + + msiString2KeyValPair("", *kvp); + msiAddKeyVal(*kvp, 'creatorList', '["hurngchunlee-icloud.com","U505173-ru.nl"]'); + *ec = errorcode( msi_json_objops(*json_str, *kvp, "set") ); + writeLine("stdout", *json_str); + + msiString2KeyValPair("", *kvp); + msiAddKeyVal(*kvp, 'creatorList', ''); + msiAddKeyVal(*kvp, 'associatedPublication', ''); + msiAddKeyVal(*kvp, 'collId', ''); + msiAddKeyVal(*kvp, 'title', ''); + #msiAddKeyVal(*kvp, 'associatedPublication', ''); + *ec = errorcode( msi_json_objops(*json_str, *kvp, "get") ); + writeLine("stdout", str(*kvp)); +} +OUTPUT ruleExecOut +