Java Class to access data from Adapter in Kotlin - java

Upgrading to Kotlin I came to the point of a Java Interface I was using to get data out of a Custom Recycler Adapter. Now in Kotlin I do not fully understand how to access the interface now. This is my Java Code I'm trying to get working in my Kotlin App.
btOK is a Button in my XML which collects all the selected Items my user has picked inside a ExpListView (You can find the full code here) and due the interface "SelectedDrink" I'm able to access the data.
Here the Button with the ClickListener:
btOk.setOnClickListener(view -> {
Button button = (Button) view;
msg = "Upload!\n";
ArrayList<SelectedDrink> selectedDrinks = expandableListAdapterDrinks.getOrderList();
Gson gson = new Gson();
for (SelectedDrink selectedDrink : selectedDrinks) {
msg += "aid=" + selectedDrink.content + "+qty=" + selectedDrink.qty + "\n";
}
final String jsonOrder = gson.toJson(selectedDrinks);
sendToServer(jsonOrder,sessionId);
}
});
this is the Interface:
public class SelectedDrink {
String content;
Double qty;
}
Now in Kotlin it gives me an error on these two boys here:
selectedDrink.content
selectedDrink.qty
that
"Cannot access: 'content/qty': it is public/package in
SelectedDrink"
I just don't understand what's the error about, neither how to fix it.

You can't access member variables directly in Java except public, You need getter/setter to access it.
Just create Getter methods
public class SelectedDrink {
private String content;
private Double qty;
public String getContent() {
return content;
}
public Double getQty() {
return qty;
}
}

Fields must be public
public class SelectedDrink {
public String content;
public Double qty;
}

Related

Getting getters from Java 17 subclasses, DTO

What could be the problem ?
I have a DTO class where I get john , after which I need to pull these values out of there and set them to another object.
Previously, I did it via VS code and everything worked fine. I moved these classes to the INTELLIJ IDEA after which I can't get the values from this class.
Example DTO UPDATE:
public class GetModel {
#JsonProperty("vendor")
private String vendor;
private List<Result> result = null;
//get/set
#JsonProperty("result")
public List<Result> getResult() {
return result;
}
#JsonProperty("result")
public void setResult(List<Result> result) {
this.result = result;
}
class Result {
#JsonProperty("FIELDS")
private Fields fields;
//get/set
class Fields {
#JsonProperty("adress")
private String adress;
//get/set
}
}
}
I am creating an object to set a value from a class GetModel
Example:
GetModel info;
Show show = new Show();
show.setAuthorityCyr(info.getResult().get(0).getFields().getAdress());
but I cannot get to it, respectively, and get the value.
the same project with the same code (only Java 11 was used) it gave these parameters.
Here Java 17 is used and does not give meaning.
Only in the context menu it shows incomprehensible fields as indicated in the image:
how to get to the values to set them in this case?
UPDATE
POJO :
public class Show {
// other fields
#JsonProperty("cyr")
private String authorityCyr;
#JsonProperty("cyr")
public String getAuthorityCyr() {
return authorityCyr;
}
#JsonProperty("cyr")
public void setAuthorityCyr(String authorityCyr) {
if(authorityCyr !=null){
this.authorityCyr = authorityCyr;
} else if(authorityCyr==null){
this.authorityCyr = "null";
}
}
// other get/set
}

How to deserialize types that inherit common base class - with Gson?

I have the following hierarchy:
RESPONSE
public class Response implements Serializable {
#SerializedName("message")
#Expose
private List<Message> messages;
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
}
MESSAGE
public class Message implements Serializable {
#SerializedName("type")
#Expose
#MessageType
private int type;
#SerializedName("position")
#Expose
#MessagePosition
private String position;
public int getType() {
return type;
}
public String getPosition() {
return position;
}
public void setType(#MessageType int type) {
this.type = type;
}
public void setPosition(#MessagePosition String position) {
this.position = position;
}
}
TEXT -> MESSAGE
public class TextMessage extends Message {
#SerializedName("text")
#Expose
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
IMAGE -> MESSAGE
public class ImageMessage extends Message {
#SerializedName("attachment")
#Expose
private Attachment attachment;
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
}
Trying to deserialize Message this way with GSon leads (naturally) to empty fields at text or attachment fields. I would like to have a best fit deserialization, which based on response would choose at run time which Message type (i.e. Text or Image) matches most fields to be fulfilled.
So far the only thoughts I had were:
1 - Use #JsonAdapter -> Didn't work
2 - Create another hierarchy structure to point classes at compile time like:
---- Response
|
- TextResponse -> List<TextMessage>
|
- ImageResponse -> List<ImageMessage>
Second option is not really what I want and makes me multiply the number of classes in a way that might get too complicated to apply later maintenance.
Does anyone know a way to handle this problem? Any framework or concepts that could be applied?
Thanks in advance
Maybe you could use Gson extras RunTimeTypeAdapterFactory. Check this example:
RuntimeTypeAdapterFactory<Message> factory = RuntimeTypeAdapterFactory
.of(Message.class, "type") // actually type is the default field to determine
// the sub class so not needed to set here
// but set just to point that it is used
// assuming value 1 in field "int type" identifies TextMessage
.registerSubtype(TextMessage.class, "1")
// and assuming int 2 identifies ImageMessage
.registerSubtype(ImageMessage.class, "2");
Then use GsonBuilder.registerTypeAdapterfactory(factory) to use this.
This just is not found from Gson core library. You need to fetch it here. You might also find some Maven/Gradle dep from global repo that someone has done but maybe easiest is just to copy this file.
It enables later hacks then if you need to modify its behavior.
I implemented this with GodClass that has all of message types fields.
but you don't use this POJO classes as DTO (Data Transfer Object) in your application.
Json is a protocol and not supported Inheritance and etc.
In same scenario I implemented this inheritance and hierarchy for DTOs.
PS: DTO in my answer is Models that we pass for example in Adapter or an Activity and so on.

How to transfer input data from a private void GUI to an ArrayList in a java class?

I need help with a specific problem in my class project. The goal of the project is to create a program in which you can register how much shares you own. Information that's required is the company name, how many shares you own and their respective value. I created a GUI class and a class where the information is transferred to. The input comes from a private void. I'm having trouble finding a way to transfer the input from the private void to a an arraylist in a class outside it.
Here is how I initialized the arraylist in the GUI class.
public class GUISharePortfolio_1 extends javax.swing.JFrame {
ArrayList<SharePackage.Share> Package = new ArrayList<SharePackage.Share>();
Next is how I get the company name, number of shares and their value from the GUI. Since it is a private void I have to transfer that information to the SharePackage class.
private void CreatePortfolioButtonActionPerformed(java.awt.event.ActionEvent evt) {
String name;
double number;
double value;
name = CompanyNameField.getText();
number = Double.parseDouble(NumberOfSharesField.getText());
value = Double.parseDouble(ValueOfShareField.getText());
Package.CompanyName(name);
Package.NumberOfShares(number);
Package.ValueOfShare(value);
}
I'm getting an error saying "cannot find symbol" under the CompanyName, NumberOfShares and ValueOfShare.
The public class to which the info should be transferred is this:
package shareportfolio;
import java.util.ArrayList;
public class SharePackage
{
private ArrayList<Share> Package = new ArrayList<Share>();
public class Share
{
private String companyname;
private double numberofshares;
private double valueofshare;
Share(String companyname, double numberofshares, double valueofshare)
{
this.companyname = companyname;
this.numberofshares = numberofshares;
this.valueofshare = valueofshare;
}
public void setCompanyName(String name)
{
companyname = name;
}
public String getCompanyName()
{
return(companyname);
}
public void setNumberOfShares(double number)
{
numberofshares = number;
}
public double getNumberOfShares()
{
return(numberofshares);
}
public void setValueOfShare(double value)
{
valueofshare = value;
}
public double getValueOfShare()
{
return(valueofshare);
}
}
}
I would appreciate any help very much.
You have a field named Package, who's type is ArrayList. ArrayList doesn't have a method called CompanyName. What you're probably trying to do is something like:
Package.add(new SharePackage.Share(companyname, numberofshares, valueofshares));
You have two such fields named 'Package', so not sure which one you're trying to add to. Maybe you're under the impression the fields are somehow the same one. They are not.
BTW: Definitely learn Java coding style before submitting this to anyone. You are naming fields with UpperCamelCase which makes it very difficult for a java programmer to read your code.
user1207705 that was the answer. I modified it to:
String name;
double number;
double value;
name = CompanyNameField.getText();
number = Double.parseDouble(NumberOfSharesField.getText());
value = Double.parseDouble(ValueOfShareField.getText());
Package.add(new SharePackage.Share(name, number, value));
Thank you for your help and I will work on Java coding style.

Viewing variables within a java object in the logs

I have a really simple wrapper class thats displayed below:
public class EmbedFoods {
private Collection<Food> foods;
public Collection<Food> getFoods() {
return foods;
}
public void setFoods(Collection<Foods> foods) {
this.foods = foods;
}
}
public class Food {
private String nutrition;
private String calories;
private String peanuts;
etc...
}
I get a list of "Food" for this EmbedFoods class by calling my API which returns a JSON string and I use Robospice for Spring Android to populate EmbedFoods automatically.
Now, I would like to view the object EmbedFoods in a human-readable format, preferably JSON.
If I go Log.e("embedFoods", EmbedFoods.toString());, it returns:
E/embedFoods [LModel.Food;#25ef9bbb
I can only see the model that is inside the embedFood class, but I cannot see variables that it comprises of. I was hoping to see a JSON string that shows all the variable of the java object printed in the logs.
How can I view all the variables that were set within the embedFood class other than debugging the line in which the embedFood is set in the app?
Well a way to do this can be done by overriding the toString method to display the correct values you want to see.
Something like
#Override
public String toString() {
Foods[] foods = collection.toArray();
String words = "[";
for (int i = 0; i < foods.length; i++) {
words = words + "{" + foods.nutrition + foods.etc + "}"
}
words = words + "]"
return words;
}
In your Embed foods.

Duplicate and add fields between classes

I was wondering if the following scenario is possible.
Having two classes (Source and Destination) where in code I could do this:
public class Source{
private String fieldA;
private String fieldB;
public Source(){ ... }
}
...
public class Destination{
public Destination(Source src){ ... }
}
Source src = new Source();
Destination dest = new Destination(src);
dest.fieldA = "test";
dest.fieldB = "test";
So what I mean here is that I have two classes, one called Source that contains (private) fields and one called Destination with no fields. After creating two objects of these classes and passing in Source into the constructor of Destination, I want to be able to duplicate/copy the fields of Source into Destination.
Could something like this be possible in Java, whether or not using Reflection? And if possible, can someone give me a minor example I can start with.
A hackish version to accomplish this is to add all fields to a Map. The fields can be copied from the source object to the destination object and the field name can be the key. Something along the lines of this:
public class FieldAccessor {
public static class Destination {
private final Map<String, Object> fields = new HashMap<>();
public Destination(Object o) {
final Set<Field> accessibleFields = Arrays.stream(o.getClass().getDeclaredFields())
.map(field -> {
field.setAccessible(true);
return field;
})
.collect(Collectors.toSet());
accessibleFields.forEach(field -> {
try {
fields.put(field.getName(), field.get(o));
} catch (IllegalAccessException e) {
throw new IllegalStateException("Unable to access field", e);
}
});
}
public Set<String> fieldNames() {
return fields.keySet();
}
public Optional<Object> fieldValue(String fieldName) {
return Optional.ofNullable(fields.get(fieldName));
}
}
public static class Source {
private final String fieldA;
private final Integer fieldB;
private final int fieldC;
public Source(String fieldA, Integer fieldB, int fieldC) {
this.fieldA = fieldA;
this.fieldB = fieldB;
this.fieldC = fieldC;
}
public String getFieldA() {
return fieldA;
}
public Integer getFieldB() {
return fieldB;
}
public int getFieldC() {
return fieldC;
}
}
#Test
public void testFields() {
Destination destination = new Destination(new Source("Abc", 123, 456));
destination.fieldNames().stream().forEach(fieldName -> {
System.out.println("Fieldname: " + fieldName + ", value: " + destination.fieldValue(fieldName).get());
});
}
}
For more info, check out this SO.
However, this is not something I would use in real production code. Instead, I would use some sort of serialization by e.g. using Jackson.
So you want to dynamically create fields in an object ? That's not directly possible in Java. If you just wanted to copy methods of an interface, the answer would have be to use a JDK proxy. It may still be of interest if :
you accept to only use getters and setters in Destination class
Source class implements an interface defining the setters and getters you want to copy
If you cannot accept those restrictions, you will have to look to CGLIB proxies or Javassist, that is libraries that dynamically modify the bytecode of the compiled class objects at load time. It is a really advanced feature, that is mainly used in frameworks or other libraries and not in high-level programs. Typically it is used in Object Relational Mappers like Hibernate to replace simple collection classes with enhanced ones that transparently gets (an save) their elements in database.
In any other case, trying to access private fields outside of the class should be seen as an indicator for a possible design flaw. private means implementation dependant and can change across versions and should not be used without knowing why.
The simplest and most efficient way to do it is copying the fields explicitly :
public Destination(Source src)
{
this.fieldA = src.getFieldA();
this.fieldB = src.getFieldB();
}
I don't see the point in using reflection for this purpose.
The only thing is in my mind for this at this time is extending Destination class from Source
public class Source{
private String fieldA;
private String fieldB;
//You need to have both Getter and Setter for fieldA and fieldB
public Source(){ ... }
}
...
public class Destination extends Source{
public Destination(){...}
}
Source src = new Destination();
dest.setFieldA("test");
dest.setFieldB("test");
Private members of Source cannot be accessed from Destination object even if you are passing a Source object to Destination.
You need to add string fieldA, fieldB to Destination to
string fieldA, fieldB;
public Destination(Source src)
{
fieldA = src.fieldA;
fieldB = src.fieldB;
}

Categories

Resources