Rhino Evaluating a javascript object in Java - java

Im quite new to Rhino and trying to convert a javascript object to a java object but unable to do so. It doesnt seem to evaluate properly.
The javascript that I have is,
var myObject = new Object();
myObject.string1 = 'Hello';
myObject.string2 = 'World';
myObject.id = 1;
var parser = new Packages.com.MyParser();
var returnStr = parser.PrintObj(myObject);
And I have the following java class that I want to evaluate this to,
public class Person extends ScriptableObject {
private int id;
private String string1;
private String string2;
public Person() {}
public void jsConstructor() {
this.string1 = "";
this.string2 = "";
this.id = 0;
}
public int getID()
{
return this.id;
}
public void jsSet_id(int value)
{
this.id = value;
}
public int jsGet_id()
{
return this.id;
}
public String jsGet_string1()
{
return this.string1;
}
public void jsSet_string1(String value)
{
this.string1 = value;
}
public String jsGet_string2() {
return this.string2;
}
public void jsSet_string2(String value)
{
this.string2 = value;
}
#Override
public String toString() {
return id + " " + string1 + " " + string2;
}
#Override
public String getClassName() {
return "Person";
}
And the skeleton of my parser is,
public class MyParser {
public String PrintObj(ScriptableObject obj) {
// Need to convert to Person object here
// Obviously casting doesnt work here
return null;
}
}
Thanks

OK figured it out !
First of all i needed to define the class in javascript as. It was complaining at first it couldn't find the class without the namespace "com". Had to add that...
defineClass("com.Person")
var myObject = new Person();
myObject.string1 = 'Hello';
myObject.string2 = 'World';
myObject.id = 1;
var parser = new Packages.com.MyParser();
var returnStr = parser.PrintObj(myObject);
And then in the parser I added the following,
public String PrintObj(ScriptableObject obj) {
try {
Person pObj = (Person)Context.jsToJava(obj, Person.class);
System.out.println("Printing person: " + pObj);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}

Related

How to use #lombok.Builder.Default with java records

Before java 16 you would use a class with a lombok value annotation, because records didn't exist yet (except in preview). If you wanted a builder and wanted a field to have a default value, you would annotate it like so:
#Builder
#Value
public class SomeClass {
private final int id;
private final String someString;
#Builder.Default
private final String someOtherString = "DefaultVal";
}
This would generate the following class:
public final class SomeClass {
private final int id;
private final String someString;
private final String someOtherString;
SomeClass(int id, String someString, String someOtherString) {
this.id = id;
this.someString = someString;
this.someOtherString = someOtherString;
}
private static String $default$someOtherString() {
return "DefaultVal";
}
public static SomeClassBuilder builder() {
return new SomeClassBuilder();
}
public int getId() {
return this.id;
}
public String getSomeString() {
return this.someString;
}
public String getSomeOtherString() {
return this.someOtherString;
}
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof SomeClass)) return false;
final SomeClass other = (SomeClass) o;
if (this.getId() != other.getId()) return false;
final Object this$someString = this.getSomeString();
final Object other$someString = other.getSomeString();
if (this$someString == null ? other$someString != null : !this$someString.equals(other$someString))
return false;
final Object this$someOtherString = this.getSomeOtherString();
final Object other$someOtherString = other.getSomeOtherString();
if (this$someOtherString == null ? other$someOtherString != null : !this$someOtherString.equals(other$someOtherString))
return false;
return true;
}
public int hashCode() {
final int PRIME = 59;
int result = 1;
result = result * PRIME + this.getId();
final Object $someString = this.getSomeString();
result = result * PRIME + ($someString == null ? 43 : $someString.hashCode());
final Object $someOtherString = this.getSomeOtherString();
result = result * PRIME + ($someOtherString == null ? 43 : $someOtherString.hashCode());
return result;
}
public String toString() {
return "SomeClass(id=" + this.getId() + ", someString=" + this.getSomeString() + ", someOtherString=" + this.getSomeOtherString() + ")";
}
public static class SomeClassBuilder {
private int id;
private String someString;
private String someOtherString$value;
private boolean someOtherString$set;
SomeClassBuilder() {
}
public SomeClassBuilder id(int id) {
this.id = id;
return this;
}
public SomeClassBuilder someString(String someString) {
this.someString = someString;
return this;
}
public SomeClassBuilder someOtherString(String someOtherString) {
this.someOtherString$value = someOtherString;
this.someOtherString$set = true;
return this;
}
public SomeClass build() {
String someOtherString$value = this.someOtherString$value;
if (!this.someOtherString$set) {
someOtherString$value = SomeClass.$default$someOtherString();
}
return new SomeClass(id, someString, someOtherString$value);
}
public String toString() {
return "SomeClass.SomeClassBuilder(id=" + this.id + ", someString=" + this.someString + ", someOtherString$value=" + this.someOtherString$value + ")";
}
}
}
Now that we are well beyond java 16 and records have been added, I was trying to get this to work with those records. #Builder seems to work fine, but how can I use #Builder.Default with records?
#Builder
public record SomeClass(
int id,
String someString,
#Builder.Default
String someOtherString = "DefaultVal"
) {
}
The above code obviously doesn't work, because you can't assign a value in a record property definition. Is there a way to use #Builder.Default with records? For instance, can #Builder.ObtainVia be used for this or does that really only work with toBuilder()?
If you're looking to solve default values you can use this:
public record SomeClass(
int id,
String someString,
String someOtherString){
public SomeClass(){
this(UUID.randomUUID(), "default","default");
}
}

Java Reflection traverse into nested object and list and update the fields

I have the following complex POJO class Invoice
public class Measure {
private String id;
private Float value;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public Float getValue() { return value; }
public void setValue(Float value) { this.value = value; }
}
public class LineItem {
private Integer lineNumber;
private Measure shipped;
private List<LineItem> lineItems;
public Integer getLineNumber() { return lineNumber; }
public void setLineNumber(Integer lineNumber) { this.lineNumber = lineNumber; }
public Measure getShipped() { return shipped; }
public void setShipped(Measure shipped) { this.shipped = shipped; }
public List<LineItem> getLineItems() { return lineItems; }
public void setLineItems(List<LineItem> lineItems) { this.lineItems = lineItems; }
}
public class Invoice {
private String originUid;
private String vehicleUid;
private List<LineItem> lineItems;
public String getOriginUid() { return originUid; }
public void setOriginUid(String originUid) { this.originUid = originUid; }
public String getVehicleUid() { return vehicleUid; }
public void setVehicleUid(String vehicleUid) { this.vehicleUid = vehicleUid; }
public List<LineItem> getLineItems() { return lineItems; }
public void setLineItems(List<LineItem> lineItems) { this.lineItems = lineItems; }
}
Now I want to traverse deep into every single field including nested objects in the Invoice object and update them using Reflection.
I can call updateIncomingObject() recursively. But I need to know how to get the nested objects out of the field as shown in the commented section.
public Object updateIncomingObject(Object incomingObject) {
Field[] incoming = incomingObject.getClass().getDeclaredFields();
for (Field incomingField : incoming) {
incomingField.setAccessible(true);
if (incomingField.getType().isArray()) {
// for (each occurrence in thisArray ???) {
// Object result = updateIncomingObject(occurrence);
// thisArray.set(index,result);
// }
// incomingField.set(incomingObject, thisArray);
}
else if (!incomingField.getType().getName().startsWith("java.lang")) {
// Object objInstance = incomingField.???;
// Object result = updateIncomingObject(objInstance);
// incomingField.set(incomingObject, result);
}
else {
if (incomingField.getType().equals(String.class) && incomingField.get(incomingObject) != null) {
String trimmed = incomingField.get(incomingObject).toString().trim();
incomingField.set(incomingObject, trimmed);
}
}
}
return incomingObject;
}
How do I turn field into object instance?
To access the objects of an array (fields defined with []) you can do the following:
if (incomingField.getType().isArray()) {
Object[] thisArray = (Object[]) incomingField.get(incomingObject);
for (int k = 0; k < thisArray.length; k++) {
Object occurrence = thisArray[k];
Object result = updateIncomingObject(occurrence);
thisArray[k] = result;
}
incomingField.set(incomingObject, thisArray);
}
To access the objects of a List you can do the following:
if (List.class.isAssignableFrom(incomingField.getType())) {
List<?> thisList = (List<?>) incomingField.get(incomingObject);
for (int k = 0; k < thisList.size(); k++) {
Object occurrence = thisList.get(k);
Object result = updateIncomingObject(occurrence);
thisList.set(k, occurrence);
}
}
Note: If you call updateIncomingObject when iterating on arrays/lists and the object in the array/list is an array (Object[]) your method won't do anything, because the number of declared fields for an array (Object[]) class is 0.
I hope this helps you.

Calling a parametrized method from LibraryCollection class to main Class

I am working on library management system project. Below is my LibraryCollection class. I would like to call my findMaterials() and checkOutMaterial() methods in the main class.
I have been trying to call as in below method but I don't get any value in the console.
public static LibraryCollection librarycollectObj1 = new LibraryCollection(10);
String search = null;
librarycollectObj1.findMaterial(search);
Thanks;
//LibraryCollection Class
public class LibraryCollection
{
private int collectionMaxSize;
private Material[] libraryCollection;
public LibraryCollection(int theMaxSize)
{
collectionMaxSize = theMaxSize;
libraryCollection = new Material[collectionMaxSize];
}
public LibraryCollection(int theCollectSize, Material[] theArray)
{
collectionMaxSize = theCollectSize;
libraryCollection = theArray;
}
//(1)----------------Find MATERIAL-----------------
public Material findMaterial(String theFindMaterial)
{
if(theFindMaterial == null)
{
return null;
}
for(int i = 0; i < libraryCollection.length; i++)
{
if(libraryCollection[i] !=null && theFindMaterial.equals(libraryCollection[i].getMaterialId()))
{
return libraryCollection[i];
}
}
return null;
}
//Material ID & checkedOutPtron ID;
public boolean checkOutMaterial(String matrlID, String patronId)
{
Material thisMaterial = findMaterial(matrlID);
if(thisMaterial == null)
{
System.out.println("The material doesn't exist" );
return false;
}
if(thisMaterial.checkedOut())
{
System.out.println("The material has been already checked out " );
return false;
}
thisMaterial.setCheckedOut(true);
thisMaterial.setPatronCheckout(Integer.parseInt(patronId));//Convert string value into int
return true;
}
//Material Class
public class Material
{
private static int materialID = 0 ;
private int mtrId;
private String title;
private boolean checkedOut ;
private int checkedOutPatron;
public Material()
{
mtrId = 0;
title = "";
checkedOut = false;
checkedOutPatron = 0;
}
public Material(int theId, String theTitle)
{
mtrId = theId;
title = theTitle;
}
//Getter Method
public String getMaterialId()
{
return mtrId + "";
}
public String getTitle()
{
return title;
}
public void setCheckedOut(boolean theCheckout)
{
checkedOut = theCheckout;
}
public void setPatronCheckout(int patronCheckout)
{
checkedOutPatron = patronCheckout;
}
public boolean checkedOut()
{
return checkedOut;
}
public int getCheckedOutPatron()
{
return checkedOutPatron;
}
//ToString Method
public String toString()
{
return " \nMaterial ID: " + mtrId + " \nMaterial Title: " + title + " \nChecked Out: "
+ checkedOut + " \nPatron check out: " + checkedOutPatron;
}
public static int getNextID()
{
materialID++;
return materialID;
}
}
When you run:
String search = null
librarycollectObj1.findMaterial(search);
You execute
public Material findMaterial(String theFindMaterial)
{
if(theFindMaterial == null)
{
return null;
}
Since theFindMaterial = search and search = null then you exit the method without doing anything because theFindMaterial = null.
You could do something like this:
public static LibraryCollection librarycollectObj1 = new LibraryCollection(10);
// Initialize the object somehow
for (int i = 0; i < 10; i++) {
librarycollectObj1.libraryCollection[i] = new Material(i, "");
}
String search = "1";
// Do some null checking in production code
System.out.println(librarycollectObj1.findMaterial(search). getMaterialId());

Object instantiation with all fields

I have some classes in my project and when I want to instantiate object from them using myClass.newInstance() to build SQL queries, it just creates the object with one field and I can't retrieve all class fields to complete my query. When I get size of my object it returns '1' instead of '3'.
Any idea what should I do?
Here-under you can find one class and my query builder.
#JupiterEntity
#TableName(name="tbl_person")
public class Person {
#PrimaryKey
#DbColumn(name = "clmn_id")
private int id;
#DbColumn(name="clmn_name", length = 1024)
private String name;
#DbColumn(name="clmn_family", length = 1024)
private String family;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFamily() {
return family;
}
public void setFamily(String family) {
this.family = family;
}
}
And here is when I want to instantiat an object from my class:
public MySQLEntityManager() {
StringBuilder stringBuilder = new StringBuilder();
if(ServiceLocator.getConfiguration().createDDL()) {
for(Class entityClass : ServiceLocator.getConfiguration().getEntities()) {
Object obj = new Object();
try {
obj = entityClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
stringBuilder.append("DROP TABLE ")
.append("'")
.append(ServiceLocator.getConfiguration().getDatabaseName())
.append("'.'")
.append(getTableName(obj)).append("' ");
System.out.println(stringBuilder.toString());
stringBuilder.setLength(0);
stringBuilder.append("CREATE TABLE")
.append("'")
.append(ServiceLocator.getConfiguration().getDatabaseName())
.append("'.'")
.append(getTableName(obj)).append("' ");
Map<Field, Object> fields = ReflectionHelper.getValuesOfFields(obj);
for(Field field : fields.keySet()) {
System.out.println(field.getName() + " -> " + fields.get(field));
}
String delimiter = "";
for (Field field : fields.keySet()) {
String columnName = field.getName();
if (field.isAnnotationPresent(DbColumn.class)) {
DbColumn dbColumn = field.getAnnotation(DbColumn.class);
columnName = dbColumn.name();
}
stringBuilder.append(delimiter).append(columnName);
delimiter = ", ";
}
System.out.println("*****" + stringBuilder.toString());
delimiter = "";
System.out.println(stringBuilder.toString());
}
}
}
So the problem is that ReflectionHelper.getValuesOfFields(obj) isn't returning what you want. You can debug that, or use obj.getClass().getDeclaredFields() instead of some NIH junk.

How to access nested elements of json object using getJSONArray method

I have a JSON response that looks like this:
{
"result": {
"map": {
"entry": [
{
"key": { "#xsi.type": "xs:string", "$": "ContentA" },
"value": "fsdf"
},
{
"key": { "#xsi.type": "xs:string", "$": "ContentB" },
"value": "dfdf"
}
]
}
}
}
I want to access the value of the "entry" array object. I am trying to access:
RESPONSE_JSON_OBJECT.getJSONArray("entry");
I am getting JSONException. Can someone please help me get the JSON array from the above JSON response?
You have to decompose the full object to reach the entry array.
Assuming REPONSE_JSON_OBJECT is already a parsed JSONObject.
REPONSE_JSON_OBJECT.getJSONObject("result")
.getJSONObject("map")
.getJSONArray("entry");
Try this code using Gson library and get the things done.
Gson gson = new GsonBuilder().create();
JsonObject job = gson.fromJson(JsonString, JsonObject.class);
JsonElement entry=job.getAsJsonObject("results").getAsJsonObject("map").getAsJsonArray("entry");
String str = entry.toString();
System.out.println(str);
I suggest you to use Gson library. It allows to parse JSON string into object data model. Please, see my example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class GsonProgram {
public static void main(String... args) {
String response = "{\"result\":{\"map\":{\"entry\":[{\"key\":{\"#xsi.type\":\"xs:string\",\"$\":\"ContentA\"},\"value\":\"fsdf\"},{\"key\":{\"#xsi.type\":\"xs:string\",\"$\":\"ContentB\"},\"value\":\"dfdf\"}]}}}";
Gson gson = new GsonBuilder().serializeNulls().create();
Response res = gson.fromJson(response, Response.class);
System.out.println("Entries: " + res.getResult().getMap().getEntry());
}
}
class Response {
private Result result;
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
#Override
public String toString() {
return result.toString();
}
}
class Result {
private MapNode map;
public MapNode getMap() {
return map;
}
public void setMap(MapNode map) {
this.map = map;
}
#Override
public String toString() {
return map.toString();
}
}
class MapNode {
List<Entry> entry = new ArrayList<Entry>();
public List<Entry> getEntry() {
return entry;
}
public void setEntry(List<Entry> entry) {
this.entry = entry;
}
#Override
public String toString() {
return Arrays.toString(entry.toArray());
}
}
class Entry {
private Key key;
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Key getKey() {
return key;
}
public void setKey(Key key) {
this.key = key;
}
#Override
public String toString() {
return "[key=" + key + ", value=" + value + "]";
}
}
class Key {
#SerializedName("$")
private String value;
#SerializedName("#xsi.type")
private String type;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#Override
public String toString() {
return "[value=" + value + ", type=" + type + "]";
}
}
Program output:
Entries: [[key=[value=ContentA, type=xs:string], value=fsdf], [key=[value=ContentB, type=xs:string], value=dfdf]]
If you not familiar with this library, then you can find a lot of informations in "Gson User Guide".
This is for Nikola.
public static JSONObject setProperty(JSONObject js1, String keys, String valueNew) throws JSONException {
String[] keyMain = keys.split("\\.");
for (String keym : keyMain) {
Iterator iterator = js1.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
if ((js1.optJSONArray(key) == null) && (js1.optJSONObject(key) == null)) {
if ((key.equals(keym)) && (js1.get(key).toString().equals(valueMain))) {
js1.put(key, valueNew);
return js1;
}
}
if (js1.optJSONObject(key) != null) {
if ((key.equals(keym))) {
js1 = js1.getJSONObject(key);
break;
}
}
if (js1.optJSONArray(key) != null) {
JSONArray jArray = js1.getJSONArray(key);
JSONObject j;
for (int i = 0; i < jArray.length(); i++) {
js1 = jArray.getJSONObject(i);
break;
}
}
}
}
return js1;
}
public static void main(String[] args) throws IOException, JSONException {
String text = "{ "key1":{ "key2":{ "key3":{ "key4":[ { "fieldValue":"Empty", "fieldName":"Enter Field Name 1" }, { "fieldValue":"Empty", "fieldName":"Enter Field Name 2" } ] } } } }";
JSONObject json = new JSONObject(text);
setProperty(json, "ke1.key2.key3.key4.fieldValue", "nikola");
System.out.println(json.toString(4));
}
If it's help bro,Do not forget to up for my reputation)))
You can try this:
JSONObject result = new JSONObject("Your string here").getJSONObject("result");
JSONObject map = result.getJSONObject("map");
JSONArray entries= map.getJSONArray("entry");
I hope this helps.
I'm also faced with this issue. So I solved with recursion. Maybe it will be helpfull.
I created method.I used org.json library.
public static JSONObject function(JSONObject obj, String keyMain, String newValue) throws Exception {
// We need to know keys of Jsonobject
Iterator iterator = obj.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
// if object is just string we change value in key
if ((obj.optJSONArray(key)==null) && (obj.optJSONObject(key)==null)) {
if ((key.equals(keyMain)) && (obj.get(key).toString().equals(valueMain))) {
// put new value
obj.put(key, newValue);
return obj;
}
}
// if it's jsonobject
if (obj.optJSONObject(key) != null) {
function(obj.getJSONObject(key), keyMain, valueMain, newValue);
}
// if it's jsonarray
if (obj.optJSONArray(key) != null) {
JSONArray jArray = obj.getJSONArray(key);
for (int i=0;i<jArray.length();i++) {
function(jArray.getJSONObject(i), keyMain, valueMain, newValue);
}
}
}
return obj;
}
if you have questions, I can explain...
I would also try it this way
1) Create the Java Beans from the JSON schema
2) Use JSON parser libraries to avoid any sort of exception
3) Cast the parse result to the Java object that was created from the initial JSON schema.
Below is an example JSON Schema"
{
"USD" : {"15m" : 478.68, "last" : 478.68, "buy" : 478.55, "sell" : 478.68, "symbol" : "$"},
"JPY" : {"15m" : 51033.99, "last" : 51033.99, "buy" : 51020.13, "sell" : 51033.99, "symbol" : "¥"},
}
Code
public class Container {
private JPY JPY;
private USD USD;
public JPY getJPY ()
{
return JPY;
}
public void setJPY (JPY JPY)
{
this.JPY = JPY;
}
public USD getUSD ()
{
return USD;
}
public void setUSD (USD USD)
{
this.USD = USD;
}
#Override
public String toString()
{
return "ClassPojo [JPY = "+JPY+", USD = "+USD+"]";
}
}
public class JPY
{
#SerializedName("15m")
private double fifitenM;
private String symbol;
private double last;
private double sell;
private double buy;
public double getFifitenM ()
{
return fifitenM;
}
public void setFifitenM (double fifitenM)
{
this.fifitenM = fifitenM;
}
public String getSymbol ()
{
return symbol;
}
public void setSymbol (String symbol)
{
this.symbol = symbol;
}
public double getLast ()
{
return last;
}
public void setLast (double last)
{
this.last = last;
}
public double getSell ()
{
return sell;
}
public void setSell (double sell)
{
this.sell = sell;
}
public double getBuy ()
{
return buy;
}
public void setBuy (double buy)
{
this.buy = buy;
}
#Override
public String toString()
{
return "ClassPojo [15m = "+fifitenM+", symbol = "+symbol+", last = "+last+", sell = "+sell+", buy = "+buy+"]";
}
}
public class USD
{
#SerializedName("15m")
private double fifitenM;
private String symbol;
private double last;
private double sell;
private double buy;
public double getFifitenM ()
{
return fifitenM;
}
public void setFifitenM (double fifitenM)
{
this.fifitenM = fifitenM;
}
public String getSymbol ()
{
return symbol;
}
public void setSymbol (String symbol)
{
this.symbol = symbol;
}
public double getLast ()
{
return last;
}
public void setLast (double last)
{
this.last = last;
}
public double getSell ()
{
return sell;
}
public void setSell (double sell)
{
this.sell = sell;
}
public double getBuy ()
{
return buy;
}
public void setBuy (double buy)
{
this.buy = buy;
}
#Override
public String toString()
{
return "ClassPojo [15m = "+fifitenM+", symbol = "+symbol+", last = "+last+", sell = "+sell+", buy = "+buy+"]";
}
}
public class MainMethd
{
public static void main(String[] args) throws JsonIOException, JsonSyntaxException, FileNotFoundException {
// TODO Auto-generated method stub
JsonParser parser = new JsonParser();
Object obj = parser.parse(new FileReader("C:\\Users\\Documents\\file.json"));
String res = obj.toString();
Gson gson = new Gson();
Container container = new Container();
container = gson.fromJson(res, Container.class);
System.out.println(container.getUSD());
System.out.println("Sell Price : " + container.getUSD().getSymbol()+""+ container.getUSD().getSell());
System.out.println("Buy Price : " + container.getUSD().getSymbol()+""+ container.getUSD().getBuy());
}
}
Output from the main method is:
ClassPojo [15m = 478.68, symbol = $, last = 478.68, sell = 478.68, buy = 478.55]
Sell Price : $478.68
Buy Price : $478.55
Hope this helps.

Categories

Resources