This is my desired output
{ "event_type": "LOAD_AVAILABLE",
"event_data": {
"load": [
{
"Ord": "ORDER12344",
"ShipReqDt": "2021-10-29",
"load_items": [
{
"ItemDesc": "Apple 12oz English Domestic: 10004-000",
"Qty": 320
},
{
"ItemDesc": "Apple CTN 12",
"Qty": 980
}
]
}
]
}}
this is my code
def temp-table ttOrd serialize-name "load"
field Ord like Ord.Ord
field ShipReqDt like Ord.ShipReqDt.
def temp-table ttItem serialize-name "load_items"
field Ord like OrdDet.Ord serialize-hidden
field ItemDesc as char
field Qty like OrdDet.ActBox.
def dataset dsOrd serialize-name "event_data" for
ttOrd, ttItem
data-relation Rel1 for ttOrd, ttItem nested relation-fields(Ord, Ord).
procedure WriteJSON:
def var dFilename as char no-undo.
dFilename = dSessTmpDir + "/Test1.xml".
find Ord no-lock where
Ord.Ord = "ORDER12344"
no-error.
create ttOrd.
assign
ttOrd.Ord = Ord.Ord
ttOrd.ShipReqDt = Ord.ShipReqDt.
for each OrdDet where OrdDet.Ord = Ord.Ord on error undo, return error on stop undo, return error:
Create ttItem.
assign
ttItem.Ord = OrdDet.Ord
ttItem.ItemDesc = OrdDet.Descr
ttItem.Qty = OrdDet.Qty.
end.
dataset dsOrd:write-json("FILE", dFilename, true).
end procedure. /* WriteJSON */
the only thing missing from my output from the desired output is the one object in the first line
"event_type": "LOAD_AVAILABLE"
any suggestions on how to add them?
thank you
You can load the datasets's JSON into a JSON object first:
At the top of your program (first statement):
USING Progress.Json.ObjectModel.* FROM PROPATH.
DEFINE VARIABLE oJsonObject AS JsonObject NO-UNDO .
DEFINE VARIABLE oJsonObject2 AS JsonObject NO-UNDO .
and instead of your dsOrd:WRITE-JSON
oJsonObject = NEW JsonObject () .
dataset dsOrd:write-json("JsonObject", oJsonObject, true).
oJsonObject2 = NEW JsonObject () .
oJsonObject2:Add ("event_type", "LOAD_AVAILABLE") .
oJsonObject2:Add ("event_data", oJsonObject:GetJsonObject ("event_data") .
oJsonObject2:WriteFile(dFileName, TRUE) .
Related
I have a table in the form of driver start number and driver name. Now I want to determine the driver name based on the start number. Which solution approach can I follow for this?
20 - driver name A
44 - driver name B
4 - driver name C
......
That would be my approach:
String ReturnDriver(int startNumber) {
Switch(startNumber) {
case 20:
{
return "driver name A";
}
break;
case 44:
{
return "driver name B";
}
break;
case 4:
{
return "driver name C";
}
break;
}
}
Would be nice if Arduino had something similar to key/value pair dictionaries. I'm not sure what your data looks like, but I wrote a little function that can emulate key/value pairs using a string of names and numbers:
String getName(int n){
int start = input.indexOf(":",input.indexOf(String(n)));
int end = input.indexOf(",", start++);
if(end < 0) end = input.length();
String value = input.substring(start, end);
value.trim();
return value;
}
You can change the separating character to be whatever you need.
You can write some code to combine the data you have into a string like so:
String input = "20: Driver,"
"4: Name,"
"23: David";
or
String input = "20: Driver, 4: Name, 23: David";
find a name in a string:
Serial.print(getName(4));
> Name
Or if your drivers occupy all positions, just order them in an array:
//each element has an id starting from 0
String name[] = {"Name", "Driver", "David"};
position = 1; //array element 2
Serial.print(name[position]);
Let's pretend we have the following types:
type Message {
text : Option<string>
}
type Update {
msg : Option<Message>
}
How do I match it in one line, like in C# using null-conditional operator i.e update?.msg?.text ?
Is there a way to do it like this?:
match msg, msg.text with
| Some msg, Some txt -> ...
| None -> ...
because I don't want to be writing 2 nested match expressions.
You have two Record types (missing the "=" in your example). To match some variable of Update type, you could do as follows:
type Message = { text : Option<string> }
type Update = { msg : Option<Message> }
let u = {msg = Some({text = Some "text"})}
//all 3 possible cases
match u with
| {msg = Some({text = Some t})} -> t
| {msg = Some({text = None})} -> ""
| {msg = None} -> ""
Define variable cWord as Character no-undo.
cWord = "Web Development Tool".
Needed OUTPUT
Development
How do i get the longest word from this when its a 1 variable only,
This is a progress4gl code btw
DEFINE VARIABLE cWord AS CHARACTER NO-UNDO.
DEFINE VARIABLE iWord AS INTEGER NO-UNDO.
DEFINE VARIABLE iLongest AS INTEGER NO-UNDO.
DEFINE VARIABLE iLength AS INTEGER NO-UNDO.
DEFINE VARIABLE iLongestLength AS INTEGER NO-UNDO.
DEFINE VARIABLE iEntries AS INTEGER NO-UNDO.
ASSIGN cWord = "Web Development Tool"
iEntries = NUM-ENTRIES (cWord, " ").
DO iWord = 1 TO iEntries:
ASSIGN iLength = LENGTH (ENTRY (iWord, cWord, " ")) .
IF iLength > iLongestLength THEN
DO:
ASSIGN iLongest = iWord
iLongestLength = iLength .
END.
END.
MESSAGE ENTRY (iLongest, cWord, " ")
VIEW-AS ALERT-BOX INFORMATION BUTTONS OK.
Just because my favorite hammer is a temp-table ;-)
def var cword as longchar no-undo init "Web Development Tool".
define temp-table tt no-undo
field cc as char
.
temp-table tt:read-json(
"longchar",
'~{"tt":[~{"cc":"' + replace( cword, ' ', '"},~{"cc":"' ) + '"}]}'
).
for each tt by length( cc ) descending:
message tt.cc.
leave.
end.
https://abldojo.services.progress.com:443/#/?shareId=5e56f4a84b1a0f40c34b8c3c
If you have two words with same length, this will return first.
DEF VAR iCount AS INT NO-UNDO.
DEF VAR cLongest AS CHAR NO-UNDO.
DEF VAR cString AS CHAR NO-UNDO INIT 'Web Development Tool'.
DO iCount = 1 TO NUM-ENTRIES(cString,' '):
cLongest = (IF LENGTH(ENTRY(iCount,cString,' ')) > LENGTH(cLongest) THEN ENTRY(iCount,cString,' ') ELSE cLongest).
END.
MESSAGE cLongest
VIEW-AS ALERT-BOX INFO BUTTONS OK.
My table column ("ID") in which the celldata has some string and integers represented below.
ID
abc1
fgd5
hgt9
ftg7
I should get the following result after sort:
ID
abc1
fgd5
ftg7
hgt9
So how can I sort this column based on only the integer values in the column data.
Assuming
TableColumn<SomeEntity, String> idColumn ;
You can do
// any number of non-digits (consumed greedily),
// followed by any number of digits (consumed greedily, as a group named "value"),
// followed by anything
Pattern pattern = Pattern.compile("\\D*(?<value>\\d*).*");
idColumn.setComparator(Comparator.comparingInt(id -> {
Matcher matcher = pattern.matcher(id);
// value to return if no match:
int defaultValue = 0 ;
if (matcher.matches()) {
// get the portion of the match that matched the group named "value":
String value = matcher.group("value");
if (value.isEmpty()) {
return defaultValue ;
} else {
// convert to an int:
return Integer.parseInt(value);
}
} else {
return defaultValue ;
}
}));
I have a date field on an XPage, this control may contain a date or be blank. In a repeat control I have this code:
var doc:NotesDocument = detailData.getDocument();
var sDate = doc.getItemValue("ACAutoStart");
doc.recycle()
return "Start Date = " + sDate
If ACAutoStart contains a date then it is displayed as [10/10/2013 12:34:15 AM MDT] if it is blank it displays as []. As I understand it the [] indicates that the result is an array but if I try using sDate[0] there is an error. I can't use getItemValueDateTime as it does not like the null return. How do I get this into a simple string value?
Replace your last line with return "Start Date = " + sDate.firstElement().
doc.getItemValue() returns an object of class java.util.Vector. As it is not an Array you get the first element with firstElement() instead of [0] .
UPDATE:
As you mentioned in your comment it has to work also for empty values and you added try:
var sDate = "";
try {sDate = doc.getItemValue("ACAutoStart").firstElement()} catch (e) {};
return "Start Date = " + sDate
...just as another way (returns converted NotesDateTime to Date):
function getJavaDateData(doc:NotesDocument, field:string)
{
var item:NotesItem = doc.getFirstItem(field);
if (item != null){
var dt:NotesDateTime = item.getDateTimeValue();
if (dt != null){
return dt.toJavaDate();
}
}
return null;
}
Off-course need to be adapted for your logic...