Create a message from a collection of collections in MULE ESB - collections

I have a JSON like:
{
"EDITORS" : [{
"EDITOR" : "MCGRAM HILL",
"BOOKS" : [{
"NAME" : "DIFFERENTIAL CALCULUS",
"YEAR" : "1995",
"TIMES_READ" : "135"
}, {
"NAME" : "2012 THE END OF THE WORLD",
"YEAR" : "2012,",
"TIMES_READ" : "56"
}
]
}, {
"EDITOR" : "DEMIDOVICH",
"BOOKS" : [{
"NAME" : "SOME TITTLE",
"YEAR" : "1975,",
"TIMES_READ" : "154"
}, {
"NAME" : "THE LITTLE PRINCE",
"YEAR" : "1987,",
"TIMES_READ" : "57"
}
]
}, {
"EDITOR" : "ADRIAN LOPEZ ASC.",
"BOOKS" : [{
"NAME" : "SOMETHING",
"YEAR" : "2008,",
"TIMES_READ" : "10"
}
]
}
]
}
I need to transform it into an output like:
payload[0]= The editor MCGRAM HILL has:
The book DIFFERENTIAL CALCULUS published in 1995 has been readed 135 times.
The book 2012 THE END OF THE WORLD published in 2012 has been readed 56 times.
payload[1]= The editor DEMIDOVICH has:
The book SOME TITTLE published in 1975 has been readed 154 times.
The book THE LITTLE PRINCE published in 1987 has been readed 57 times.
payload[2]= The editor ADRIAN LOPEZ ASC. has:
The book SOMETHING published in 2008 has been readed 10 times.
So far I transform the JSON to an Java Object, then use a foreach scope with the collection #[payload.EDITORS]
Inside the foreach I create a variable Intro = "The editor #[payload.EDITOR] has:"
And after that I'm lost.
I have tried to set payload to #[payload.BOOKS] and then use another foreach but this only shows the last book, and have also try Collection Aggregator but don't know what to write in "Message info Mapping".
How can I accomplish the required output?
Any help could be greatly appreciated, thanks in advance.

Try following with dataweave
%dw 1.0
%output application/json
---
{(payload.EDITORS map ((data, index) -> {
payload : "The editor " ++ data.EDITOR ++ " has:\r\n" ++
{(data.BOOKS map {
pqr : "The book " ++ $.NAME ++ " published in " ++ $.YEAR ++ " has been readed " ++ $.'TIMES_READ' ++ " times."
})} pluck $ joinBy "\r\n"
}))} pluck $
Json Output for reference. You can transform to java to get desired output.
[
"The editor MCGRAM HILL has:\r\nThe book DIFFERENTIAL CALCULUS published in 1995 has been readed 135 times.\r\nThe book 2012 THE END OF THE WORLD published in 2012, has been readed 56 times.",
"The editor DEMIDOVICH has:\r\nThe book SOME TITTLE published in 1975, has been readed 154 times.\r\nThe book THE LITTLE PRINCE published in 1987, has been readed 57 times.",
"The editor ADRIAN LOPEZ ASC. has:\r\nThe book SOMETHING published in 2008, has been readed 10 times."
]
Hope this helps.

IMHO, you don't need to set payload inside the foreach scope.
I tried the following configuration and it produces a list of string which containing those message. I think you can modify the last message processor to display the expected output (e.g.: add another foreach or expression to extract the message from the final payload/ArrayList).
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<set-variable variableName="messageMapping" value="#[new java.util.ArrayList()]" doc:name="Variable"/>
<foreach collection="#[payload.EDITORS]" doc:name="For Each">
<set-variable variableName="messageEditor" value="The editor #[payload.EDITOR] has: " doc:name="Variable"/>
<foreach collection="#[payload.BOOKS]" doc:name="For Each">
<expression-transformer expression="#[flowVars.messageEditor += "\r\nThe book " + payload.NAME + " published in " + payload.YEAR + " has been readed " + payload.TIMES_READ + " times."]" doc:name="Expression"/>
</foreach>
<expression-transformer expression="#[flowVars.messageMapping.add(flowVars.messageEditor)]" doc:name="Expression"/>
</foreach>
<set-payload value="#[flowVars.messageMapping]" doc:name="Set Payload"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
If you prefer to use DataWeave, then you can use the following code:
%dw 1.0
%output application/java
---
payload.EDITORS map (
'The editor ' ++ $.EDITOR ++ ' has:\r\n' ++
($.BOOKS map (
'The book ' ++ $.NAME ++ ' published in ' ++ $.YEAR ++ ' has been readed ' ++ $.TIMES_READ ++ ' times.'
) joinBy '\r\n')
)

Dataweave doens't feel like the right approach, specially because the output is plain txt.
Personally I'd probably use json-to-object (see below) and parse template.
<json:json-to-object-transformer returnClass="java.util.Map" />

Related

Using jq to loop over objects and return an iterated value

I have an enteresting TODO that I'd like some eyes on. I'm using journalctl to grab system journal entries and output as JSON. journalctl outputs as JSON objects separated by a newline.
Here's a sample of a JSON object outputted from journalctl:
{ "__CURSOR" : "s=bd3afe956aec45d89cf3939e839c3647;i=3e084;b=6dd8a3060bdb448d848f4694339c6e94;m=5d0fd53a6;t=5c797ae76d38f;x=6cdb742ba83df8f5", "__REALTIME_TIMES
TAMP" : "1626829164613612", "__MONOTONIC_TIMESTAMP" : "24980054950", "_BOOT_ID" : "6dd8a3030bdb446d858f4694337c6e94", "PRIORITY" : "6", "SYSLOG_FACILITY" : "3",
"CODE_FILE" : "../src/core/job.c", "CODE_LINE" : "845", "CODE_FUNC" :
"job_log_status_message", "SYSLOG_IDENTIFIER" : "systemd", "JOB_TYPE" : "start", "JOB_RES
ULT" : "done", "MESSAGE_ID" : "39f53479d3a045ac8e11786248231fbf", "_TRANSPORT" : "journal", "_PID" : "11282", "_UID" : "1162", "_GID" : "1162", "_COMM" : "syste
md", "_EXE" : "/lib/systemd/systemd", "_CMDLINE" : "/lib/systemd/systemd --user", "_CAP_EFFECTIVE" : "0", "_SELINUX_CONTEXT" : "unconfined\n", "_AUDIT_SESSION"
: "974", "_AUDIT_LOGINUID" : "1162", "_SYSTEMD_CGROUP" : "/user.slice/user-1162.slice/user#1162.service/init.scope", "_SYSTEMD_OWNER_UID" : "1162", "_SYSTEMD_UN
IT" : "user#1162.service", "_SYSTEMD_USER_UNIT" : "init.scope", "_SYSTEMD_SLICE" : "user-1162.slice", "_SYSTEMD_USER_SLICE" : "-.slice", "_SYSTEMD_INVOCATION_ID
" : "1f72568e79c34f14a525f98ce6a151c2", "_MACHINE_ID" : "32c9faf3dd90422881ce03690ebf0015", "_HOSTNAME" : "ip-192-168-22-27", "MESSAGE" : "Listening on port.", "USER_UNIT" : "dirmngr.socket", "USER_INVOCATION_ID" :
"7c1e914aada947cd80a45d68275751dc", "_SOURCE_REALTIME_TIMESTAMP" :
"1626829165607533" }
I'm using --after-cursor to get a subset of the journal. There is no --before-cursor option afaik so I'm trying to find a way to stop at a specific cursor and search the JSON objects between the first and last cursor.
At the moment I'm using the following snippet (sloppy by my own admission) to search the journal after a cursor and count the objects where a match is found.
journalctl -u my-service --after-cursor="$FIRST_CURSOR" -o json | jq -n 'inputs|select(.MESSAGE|test(".*My search string .*")) | jq length | wc -l
I'd like to do this more intelligently with possibly an if/else statement but I'm a jq novice.
A jq-only solution would be:
[inputs|select(.MESSAGE|test("My search string")) | length] | length
Notice there is no need for the initial or final .* in the regex
For future reference, please follow the "mcve" guidelines at http://stackoverflow.com/help/mcve .
In particular, your JSON got mangled while copying-and-pasting into SO; and an actual example, with expected output, would be appreciated.

Error while calling for loop inside awk command

The snippet reads as below:
echo -n "Filename: "
read filename
echo -n "Data Fields? "
read -a ar
awk -F '[[:space:]][[:space:]]+' 'BEGIN{OFS = "--"} {for val in "${ar[#]}" printf $val }' $filename
ar is an array i am reading, filename is name of a file i am reading too.
The file looks as below :
100 Thomas Manager Sales $5,000
200 Jason Developer Technology $5,500
300 Sanjay Sysadmin Technology $7,000
400 Nisha Manager Marketing $9,500
500 Randy DBA Technology $6,000
What i am trying to do is, accept the filename from user, also take the field number he wants to display, and then scan the file and produce the output accordingly.
The array "ar" contains the field numbers, like 1,2,3.
Input is as below:
$ sh awk_prac.sh
Filename: employee.txt
Data Fields: 2 3
Now according to the input i gave above, the output should look like below:
Thomas Manager
Jason Developer
Sanjay Sysadmin
Nisha Manager
Randy DBA
But everytime i run the code, it shows a syntax error pointing under "val" after for.
awk: cmd. line:1: BEGIN{OFS = "--"} {for val in "${ar[#]}" printf $val }
awk: cmd. line:1: ^ syntax error
Can anyone point out the mistake. #i_am_new_to_this#
The problem with your code is explained in the comments under your question (awk is not shell), here's how to solve it:
$ cat tst.sh
echo -n "Filename: "
read filename
echo -n "Data Fields? "
read fields
awk -v fields="$fields" 'BEGIN{n=split(fields,f)} {for (i=1; i<=n; i++) printf "%s%s", $(f[i]), (i<n?OFS:ORS)}' "$filename"
$ ./tst.sh
Filename: file
Data Fields? 2 3
Thomas Manager
Jason Developer
Sanjay Sysadmin
Nisha Manager
Randy DBA

error in uploading json file on firebase and firebase is not recognizing it

In my project i am uploading json file to firebase which is i want to upload to firebase and my code of importtofire.json is here :-
{
"SCHOOL NAME" : "Amrit Yatayat school",
"ADDRESS" : "7'/'2 Chhoti Gawlati Sardar Patel Marg Indore ,Indore '-' 452001",
"PHONE NO." : "(0731) 2464534"
}
In uploading these data i am getting these error :-
Invalid JSON data or key values. Key values can’t contain $ # [ ] / or . Learn more
Please help me
In your code just remove . which you had used and then your error will solve it is here "PHONE NO." to "PHONE NO"
No changes to your code just save the file as UTF-8 encoding
in SublimeText > File > Save with Encoding > UTF-8

Convert QUrl with percent encoding into string

I use a URL entered by the user as text to initialize a QUrl object. Later I want to convert the QUrl back into a string for displaying it and to check it using regular expression. This works fine as long as the user does not enter any percent encoded URLs.
Why doesn't the following example code work?
qDebug() << QUrl("http://test.com/query?q=%2B%2Be%3Axyz%2Fen").toDisplayString(QUrl::FullyDecoded);
It simply doesn't decode any of the percent-encoded characters. It should print "http://test.com/query?q=++e:xyz/en" but it actually prints "http://test.com/query?q=%2B%2Be%3Axyz%2Fen".
I also tried a lot of other methods like fromUserInput() but I could not make the code work correctly in Qt5.3.
Can someone explain me how to do this and why the above code doesn't work (i.e. showing the decoded URL) even when using QUrl::FullyDecoded?
UPDATE
After getting the fromPercentEncoding() hint, I tried the following code:
QUrl UrlFromUserInput(const QString& input)
{
QByteArray latin = input.toLatin1();
QByteArray utf8 = input.toUtf8();
if (latin != utf8)
{
// URL string containing unicode characters (no percent encoding expected)
return QUrl::fromUserInput(input);
}
else
{
// URL string containing ASCII characters only (assume possible %-encoding)
return QUrl::fromUserInput(QUrl::fromPercentEncoding(input.toLatin1()));
}
}
This allows the user to input unicode URLs and percent-encoded URLs and it is possible to decode both kinds of URLs for displaying/matching. However the percent-encoded URLs did not work in QWebView... the web-server responded differently (it returned a different page). So obviously QUrl::fromPercentEncoding() is not a clean solution since it effectively changes the URL. I could create two QUrl objects in the above function... one constructed directly, one constructed using fromPercentEncoding(), using the first for QWebView and the latter for displaying/matching only... but this seems absurd.
#Conclusion
I've done some research, the conclusion so far is: absurd.
QUrl::fromPercentEncoding() is the way to go and what OP has done in the UPDATE section should've been the accepted answer to the question in title.
I think Qt's document of QUrl::toDisplayString is a little bit misleading :
"Returns a human-displayable string representation of the URL. The output can be customized by passing flags with options. The option
RemovePassword is always enabled, since passwords should never be
shown back to users."
Actually it doesn't claim any decoding ability, the document here is unclear about it's behavior. But at least the password part is true. I've found some clues on Gitorious:
"Add QUrl::toDisplayString(), which is toString() without password. And fix documentation of toString() which said this was the method to
use for displaying to humans, while this has never been true."
#Test Code
In order to discern the decoding ability of different functions. The following code has been tested on Qt 5.2.1 (not tested on Qt 5.3 yet!)
QString target(/*path*/);
QUrl url_path(target);
qDebug() << "[Original String]:" << target;
qDebug() << "--------------------------------------------------------------------";
qDebug() << "(QUrl::toEncoded) :" << url_path.toEncoded(QUrl::FullyEncoded);
qDebug() << "(QUrl::url) :" << url_path.url();
qDebug() << "(QUrl::toString) :" << url_path.toString();
qDebug() << "(QUrl::toDisplayString) :" << url_path.toDisplayString(QUrl::FullyDecoded);
qDebug() << "(QUrl::fromPercentEncoding):" << url_path.fromPercentEncoding(target.toUtf8());
Return QByteArray: QUrl::toEncoded
Return QString: QUrl::url, QUrl::toString, QUrl::toDisplayString, QUrl::fromPercentEncoding
P.S. QUrl::url is just synonym for QUrl::toString.
#Output
[Case 1]: When target path = "%_%" (test the functionality of encoding):
[Original String]: "%_%"
--------------------------------------------------------------------
(QUrl::toEncoded) : "%25_%25"
(QUrl::url) : "%25_%25"
(QUrl::toString) : "%25_%25"
(QUrl::toDisplayString) : "%25_%25"
(QUrl::fromPercentEncoding): "%_%"
[Case 2]: When target path = "Meow !" (test the functionality of encoding):
[Original String]: "Meow !"
--------------------------------------------------------------------
(QUrl::toEncoded) : "Meow%20!"
(QUrl::url) : "Meow !"
(QUrl::toString) : "Meow !"
(QUrl::toDisplayString) : "Meow%20!" // "Meow !" when using QUrl::PrettyDecoded mode
(QUrl::fromPercentEncoding): "Meow !"
[Case 3]: When target path = "Meow|!" (test the functionality of encoding):
[Original String]: "Meow|!"
--------------------------------------------------------------------
(QUrl::toEncoded) : "Meow%7C!"
(QUrl::url) : "Meow%7C!"
(QUrl::toString) : "Meow%7C!"
(QUrl::toDisplayString) : "Meow|!" // "Meow%7C!" when using QUrl::PrettyDecoded mode
(QUrl::fromPercentEncoding): "Meow|!"
[Case 4]: When target path = "http://test.com/query?q=++e:xyz/en" (none % encoded):
[Original String]: "http://test.com/query?q=++e:xyz/en"
--------------------------------------------------------------------
(QUrl::toEncoded) : "http://test.com/query?q=++e:xyz/en"
(QUrl::url) : "http://test.com/query?q=++e:xyz/en"
(QUrl::toString) : "http://test.com/query?q=++e:xyz/en"
(QUrl::toDisplayString) : "http://test.com/query?q=++e:xyz/en"
(QUrl::fromPercentEncoding): "http://test.com/query?q=++e:xyz/en"
[Case 5]: When target path = "http://test.com/query?q=%2B%2Be%3Axyz%2Fen" (% encoded):
[Original String]: "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"
--------------------------------------------------------------------
(QUrl::toEncoded) : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"
(QUrl::url) : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"
(QUrl::toString) : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"
(QUrl::toDisplayString) : "http://test.com/query?q=%2B%2Be%3Axyz%2Fen"
(QUrl::fromPercentEncoding): "http://test.com/query?q=++e:xyz/en"
P.S. I also encounter the bug that Ilya mentioned in comments: Percent Encoding doesn't seem to be working for '+' in QUrl
#Summary
The result of QUrl::toDisplayString is ambiguous. As the document says, the QUrl::FullyDecoded mode must be used with care. No matter what type of URL you got, encode them by QUrl::toEncode and display them with QUrl::fromPercentEncoding when necessary.
As for the malfunction of percent-encoded URLs in QWebView mentioned in OP, more details are needed to debug it. Different function and different mode used could be the reason.
#Helpful Resources
RFC 3986 (which QUrl conforms)
Encode table
Source of qurl.cpp on Gitorious
I am not sure why toDisplayString(QUrl::FullyDecoded) does not work.
After trying several versions I have found that copy.query(QUrl::FullyDecoded) does decode the query part. The Documentation has an example with the the following code does return the decoded URL:
QUrl url("http://test.com/query?q=%2B%2Be%3Axyz%2Fen");
url.setQuery(url.query(QUrl::FullyDecoded), QUrl::DecodedMode);
qDebug() << url.toString();
To solve the problem this way is not optimal because the query part is copied without need.
You can use QUrlQuery::toString(QUrl::FullyEncoded) or QUrl::fromPercentEncoding() for this converting.

Neocomplete and Eclim don't work together

with the default set up, there nothing shows about the auto completion,either no autocomplete shows up nor <C-X><C-U> key, the later shows "pattern not found", Is there anyone can tell me how to make it working?
here my vimrc file:
set nocompatible
syntax on
set laststatus=2
set encoding=utf-8
set guifont=Anonymous\ Pro\ for\ Powerline:h13
let g:Powerline_symbols = 'fancy'
if has("gui_running")
set guioptions=egmrt
set transparency=10
set guifont=menlo:h14
endif
imap jj <Esc>
set autoindent
set tabstop=4
set shiftwidth=4
filetype off " required!
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()
" let Vundle manage Vundle
" required!
Bundle 'gmarik/vundle'
" My Bundles here:
" original repos on github
Bundle 'scrooloose/nerdtree'
Bundle 'majutsushi/tagbar'
Bundle 'tpope/vim-rails'
Bundle 'Shougo/neocomplcache'
Bundle 'nanotech/jellybeans.vim'
Bundle 'Rip-Rip/clang_complete'
Bundle 'osyo-manga/neocomplcache-clang_complete'
colorscheme jellybeans
Bundle 'godlygeek/tabular'
Bundle 'Lokaltog/vim-powerline'
Bundle 'tpope/vim-haml'
Bundle 'nathanaelkane/vim-indent-guides'
Bundle 'vim-ruby/vim-ruby'
Bundle 'kchmck/vim-coffee-script'
" vim-scripts repos
Bundle 'DrawIt'
Bundle 'tComment'
Bundle 'sudo.vim'
Bundle 'Align'
" non github repos
"Bundle 'git://git.wincent.com/command-t.git'
filetype plugin indent on " required!
nmap 88 :TagbarToggle<CR>
nmap 99 :NERDTreeToggle<CR>
" use neocomplcache & clang_complete
" add neocomplcache option
let g:neocomplcache_force_overwrite_completefunc=1
" add clang_complete option
let g:clang_complete_auto=1
" Disable AutoComplPop.
let g:acp_enableAtStartup = 0
" Use neocomplcache.
let g:neocomplcache_enable_at_startup = 1
" Use smartcase.
let g:neocomplcache_enable_smart_case = 1
" Use camel case completion.
let g:neocomplcache_enable_camel_case_completion = 1
" Use underbar completion.
let g:neocomplcache_enable_underbar_completion = 1
" Set minimum syntax keyword length.
let g:neocomplcache_min_syntax_length = 3
let g:neocomplcache_lock_buffer_name_pattern = '\*ku\*'
" Define dictionary.
let g:neocomplcache_dictionary_filetype_lists = {
\ 'default' : '',
\ 'vimshell' : $HOME.'/.vimshell_hist',
\ 'scheme' : $HOME.'/.gosh_completions'
\ }
" Define keyword.
if !exists('g:neocomplcache_keyword_patterns')
let g:neocomplcache_keyword_patterns = {}
endif
let g:neocomplcache_keyword_patterns['default'] = '\h\w*'
" Plugin key-mappings.
imap <C-k> <Plug>(neocomplcache_snippets_expand)
smap <C-k> <Plug>(neocomplcache_snippets_expand)
inoremap <expr><C-g> neocomplcache#undo_completion()
inoremap <expr><C-l> neocomplcache#complete_common_string()
" SuperTab like snippets behavior.
"imap <expr><TAB> neocomplcache#sources#snippets_complete#expandable() ? "\<Plug>(neocomplcache_snippets_expand)" : pumvisible() ? "\<C-n>" : "\<TAB>"
" Recommended key-mappings.
" <CR>: close popup and save indent.
inoremap <expr><CR> neocomplcache#smart_close_popup() . "\<CR>"
" <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplcache#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplcache#smart_close_popup()."\<C-h>"
inoremap <expr><C-y> neocomplcache#close_popup()
inoremap <expr><C-e> neocomplcache#cancel_popup()
" AutoComplPop like behavior.
"let g:neocomplcache_enable_auto_select = 1
" Shell like behavior(not recommended).
"set completeopt+=longest
"let g:neocomplcache_enable_auto_select = 1
"let g:neocomplcache_disable_auto_complete = 1
"inoremap <expr><TAB> pumvisible() ? "\<Down>" : "\<TAB>"
"inoremap <expr><CR> neocomplcache#smart_close_popup() . "\<CR>"
" Enable omni completion.
autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
" Enable heavy omni completion.
if !exists('g:neocomplcache_omni_patterns')
let g:neocomplcache_omni_patterns = {}
endif
let g:neocomplcache_omni_patterns.ruby = '[^. *\t]\.\w*\|\h\w*::'
"autocmd FileType ruby setlocal omnifunc=rubycomplete#Complete
let g:neocomplcache_omni_patterns.php = '[^. \t]->\h\w*\|\h\w*::'
Put this in your vimrc
let g:EclimCompletionMethod = 'omnifunc'
Check out http://eclim.org/vim/code_completion.html for more information.

Resources