Restrict access to only necessary data-class accessors / getters - java

I have a data class that is created in one class, and can be passed to one of several Android UI Activities that implement a specific Interface.
Each UI uses the same data, however, not all the UIs need all of the data. I was wondering if there was a simple solution that allows each UI to only use a specific part of the data (only use specific accessors / getters)
ClickListener Handler Class
// ICalculatorAbstraction is what all my UI's implement. It has method... void updateResult(ExpressionState expression)
public final View.OnClickListener listenerOn(final ICalculatorAbstraction UI) {
return listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
// Calculations
ExpressionState expression = new ExpressionState.Builder()
.setFirstNumber(num1)
.setSecondNumber(num2)
.setTotal(total)
.setOperator(operator.getSign())
.build();
UI.updateResult(expression);
}
};
}
ICalculatorAbstraction Interface
Again, all of my Android Activities (UIs) implement this interface
public interface ICalculatorAbstraction {
...
void updateResult(ExpressionState result);
}
Needs All Accessors UI
#Override
public void updateResult(ExpressionState result) {
String results = String.format( // NOTE: this one needs ALL the accessors / getters!!
"%s %s %s = %s",
result.getFirstNumber(),
result.getOperator(),
result.getSecondNumber(),
result.getTotal()
);
this.txtResult.setText(results);
Needs One Accessor UI
#Override
public void updateResult(ExpressionState result) {
String results = String.format( // NOTE: this one needs ONE accessor / getter!!
"Wow. Such Calcuation. %s",
result.getTotal()
// NOTE: These should not be allowed in this instance because this UI does not use them
// result.getFirstNumber()
// result.getOperator()
// result.getSecondNumber()
);
this.txtResult.setText(results);
How can I change updateResult(...) (both in the interface and in the UI) so that the specific UI's updateResult(...) will only let me use the needed assessors / getters?
I have tried to create a blank interface, and then created 2 abstract classes that implement that blank interface. The abstract classes had only the accessors / getters I needed, but when I tried to modify the above code, nothing worked.
Is this possible?
Update
Here is what I would like to see - "my best possible solution" you can say.
Needs All Accessors UI
#Override
public void updateResult(IAllAccessors result) {
String results = String.format(
"%s %s %s = %s",
result.getFirstNumber(),
result.getOperator(),
result.getSecondNumber(),
result.getTotal()
);
this.txtResult.setText(results);
Needs One Accessor UI
#Override
public void updateResult(IOneAccessorOnly result) {
String results = String.format(
"Wow. Such Calcuation. %s",
result.getTotal() // I should not be able to do result.getFirstNumber(); for example
);
this.txtResult.setText(results);
ExpressionState / Builder Class
public class ExpressionState implements IOneAccessorOnly, IAllAccessors {
private ExpressionState(Builder builder) { ... }
public double getFirstNumber() { ... } // IAllAccessors
public double getSecondNumber() { ... } // IAllAccessors
public String getOperator() { ... } // IAllAccessors
public double getTotal() { ... } // IAllAccessors, IOneAccessorOnly
public static class Builder { ... }
}
The problem with this solution, is that I cannot figure out what to do with my interface that I have above! I cannot have a parameter that will make the compiler happy with both UIs.
Update 2
I cannot have...
In my ClickListener class when creating ExpressionState with the builder
IOneAccessorOnly var = new ExperssionState.Builder()...
This is because in my ClickListener class, I don't know which one to create. It has to be very generic. In my UI's I want to simplify what I can use. I cannot do that with this approach
Because it does not know what to be, it has to be "everything"
ExpressionState var = new ExpressionState.Builder()...
It really cannot be anything other than that. The solution will have to deal with the UIs (Activities) specifically to narrow down what is allowed!!

If Expression state is your own class I'd make it implement two different interfaces like so.
public class ExpressionState implements InterfaceOne, InterfaceTwo {
public void interfaceOneGetterMethod()
public void interfaceTwoGetterMethod()
}
in another file:
public interface InterfaceOne {
public void interfaceOneGetterMethod();
and final file:
public interface InterfaceTwo {
public void interfaceTwoGetterMethod();
Now when you create the ExpressionState objects assign them to objects defined as:
InterfaceTwo var = new ExperssionState(blah);
Or modify your builder to just return interfaces( even better )

Related

Should I use an anonymous inner class to simulate 'out' parameters in Java?

I'm still a relative newbie when it comes to Java, coming mainly from a C# background.
I was discussing the lack of 'out' parameters in Java methods with a colleague and how to work around this. He suggested creating a structure/class to hold the various parameters and passing it back.
Sometimes this feels 'wrong' to me - especially if I have a special method that I want to use to return a subset of parameters from a larger class.
So I wondered about using anonymous inline classes instead to achieve this. Code sample below.
Is this a sensible approach? Just wondering what the perceived wisdom is on this.
public class MyClass {
Patient myPatient = null;
// An interface to enable us to return these variables in a single call
public interface VitalStatsResponse { public void returnStats(int bloodPressure, int heartRate); }
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats(VitalStatsResponse response)
{
response.returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats(new VitalStatsResponse() {
#Override
public void returnStats(int bloodPressure, int heartRate) {
// Handle returned variables here
}
});
}
}
I would go for the simple solution of creating a VitalStats object. If you need the VitalStatus of a patient, then VitalStats is a concept in your application that can be represented as an Object.
public class VitalStatus {
final int bloodPressure;
final int heartRate;
public VitalStats(int bloodPressure, int heartRate) {
this.bloodPressure = bloodPressure;
this.heartRate = heartRate;
}
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Other variables
public VitalStatus getVitalStatus() {
return new VitalStats(bloodPressured * 2, heartRate / 2);
}
}
Out params is a procedural solution for return times. Java primarily fits the Object Oriented paradigm of programming and as such don't be afraid to make objects. This fits with the S in SOLID if your class is doing a lot of complex things see if you can break it down into smaller more manageable pieces.
I would also use "class to hold the parameters" over "inline anonymous inner class"
public class MyClass implements VitalStatsResponse{
Patient myPatient = null;
private ArrayList<VitalStatsResponse> response;
void MyClass(ArrayList<VitalStatsResponse> response) {
this.response = response;
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats()
{
for(int i = 0; i < response.length; i++) {
// call returnStats method of every registered callback
response.get(i).returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
}
// any client can register/unregister callback via these methods
void registerResponse(VitalStatsResponse response) {
this.response.add(response);
}
void unRegisterResponse(VitalStatsResponse response) {
this.response.remove(response);
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats();
}
public void returnStats(int bloodPressure, int heartRate) {
// implement the body according to this class requirement
}
}

Java Builder Pattern pass to session JSP servlet

I just started learning and implementing builder patterns from Wiki. And also CH2 of Effective Java.
This pertains to JSP servlets, this might be a little convoluted, but I just wanted to pass this by you guys to see how to do this correctly.
Lets start with a scenario, where you can't build the object completely there are certain information that is not given. So most likely you have to put the object in session and then add variables to the session object later. How would I accomplish this with Build pattern?
Here is a code example
public class Widget(){
public static class Builder(){
public Builder(String id) {...}
public Builder serialNumber (String val) {...}
public Builder area (String val) {...}
public Widget build() { return new Widget(this); }
}
private Widget(Builder builder){...}
}
JSP Servlet 1 // only have ID information
Widget w = new Widget().Builder(id).build();
HttpSession session = request.getSession();
session.setAttribute("widget", w);
JSP Servlet 2 // Now I have serial and area
Widget.Builder w = (Widget.Builder) session.getAttribute("widget");
//** This is as far as I go **
w.serialNumber("something") // Now this works
.area("sideArea") //
.build() // < I know if I do this I will be creating another Object. Is there a way to use build pattern without creating redundant obj?
Thank you all...
w.serialNumber("something") // Can not find symbol
because serialNumber is not a method of the w object. What you're probably looking for is method chaining:
public class Widget {
... //assuming you have all the right fields here
public Widget setSerialNumber(String id) {
this.id = id;
return this;
}
public Widget setArea(String area) {
this.area = area;
return this;
}
public static class Builder(){
public Builder(String id) {...}
public Builder serialNumber (String val) {...}
public Builder area (String val) {...}
public Widget build() { return new Widget(this); }
}
private Widget(Builder builder){...}
}
then you can do something like this:
w.setSerialNumber(id).setArea(area);
Use Widget.Builder when you want to construct a new Widget object, and method chaining when you want to change an existing Widget object.

Notification handling in android

I am developing a multi player game, which have a module which works on the basis of notifications send by server. For example: Action of other player, score update, action to do etc.
I am receiving notification in json format. I am wondering if there is some codding pattern exist which automatically deliver different notifications to their corresponding handlers. Many thanks for your help.
Well, cannot say if this classifies as a pattern:
My take on it would be to simply create a separate class, lets call it JSONGameStateFilter, to filter the JSON object based on the received value plus the state of the game
Something like:
public class JSONGameStateFilter() {
public interface GameInterface1 {
// callback methods for activity 1
// example: public void newPlayerArrived(String name, int score);
// ...
}
public interface GameInterface2 {
// callback methods for activity 2
}
public interface GameInterface3 {
// callback methods for activity 3
}
private GameInterface1 callback1;
private GameInterface2 callback2;
private GameInterface3 callback3;
private JSONGameStateFilter instance;
public static JSONGameStateFilter getInstance() {
if (instance != null) {
return instance = new JSONGameStateFilter();
}
}
private JSONGameStateFilter() {}
public void registerListener(GameInterface1 callback) {
// called by Activity1 implementing GameInterface1
// by JSONGameStateFilter.newInstance().registerListener(this);
this.callback1 = callback;
}
public void registerListener(GameInterface2 callback) {
this.callback2 = callback;
}
public void registerListener(GameInterface3 callback) {
this.callback3 = callback;
}
public void filterJSON(JSONObject object) {
// read JSON and gamestate
// depending on situation call the right callback
// example: if (callback1 != null) callback1.newPlayerArrived(name, score)
}
}
The design of this approach would be to implement varies of callbacks on each activity (known pattern for fragments to communicate back to activity).
This is untested and written just now but I am pretty confident that it would work well.

Pass outer anon class ref to a method in an inner anon class

How to pass outer anon class ref to a method in an inner anon class in Java?
I have a method that makes async call to a server - sendCall(some_args, callback). The callback is represented by anonymous class (let's name it OuterAnon) and contains a method for failure case. Inside this method a message box is created and sendCall() is called each time OK button is pressed. So I need to pass OuterAnon to the method again.
Here is a code to demonstrate what I mean:
private void sendCall(MyData data, OuterAnon<Boolean> callback){/*...*/}
private void myCall(final MyData data) {
sendCall(data, new OuterAnon<Boolean>() {
public void onFailure(Throwable throwable) {
final OuterAnon<Boolean> callback = this; //how to avoid this?
MessageBox.show(throwable.getMessage(), new MessageListener() {
public void process(MessageBox.OnClick action) {
if (action == MessageBox.OnClick.OK) {
sendCall(new MyData("resend?"), callback);
}
}
});
}
}
});
}
As you noticed, I take a ref for callback here:
final OuterAnon<Boolean> callback = this;
and use it here:
sendCall(new MyData("resend?"), callback);
But I want to avoid ref creation and pass callback like:
sendCall(new MyData("resend?"), this); //at the moment we point to MessageListener instead of OuterAnon.
Is there any way to do it in Java?
It's hard for us to fix since you've only shown incomplete code with classes that aren't supplied, so I don't know if this example is syntactically correct. That being said, a refactoring like this may suit your needs:
private void myCall(final MyData data)
{
sendCall(data, new OuterAnon<Boolean>()
{
public void onFailure(Throwable throwable)
{
showErrorMessage(throwable);
}
});
}
private void showErrorMessage(Throwable throwable)
{
MessageBox.show(throwable.getMessage(), new MessageListener()
{
public void process(MessageBox.OnClick action)
{
if (action == MessageBox.OnClick.OK)
{
sendCall(new MyData("resend?"));
}
}
});
}
private void sendCall(MyData data)
{
sendCall(data, this);
}
In general, I think it's a usually good idea to abstract code out of anon inner classes and into their own method on the enclosing class. It's now testable, reusable, and more readable, IMO.
If you really need to specify the onFailure inside the inner class the way you showed the code, and if you need to use that specific reference for callback, and you need to code this way...
Let's answer the question: no.
In my attempts, I've achieved 3 ways to access the anon-inner-least instance inside the anon-inner-most instance, but I think that none satisfies what you expect.
In that case, the anon-inner-most doesn't have a reference to the anon-inner-least: as you said, the this now points to the anon-inner-least.
Also, I tried to search at the java specification, but couldn't find exactly the answer to the question - if someone find the answer there, please contribute.
My try:
import java.util.ArrayList;
import java.util.LinkedList;
public abstract class AnonTest {
public static void main(String[] args) {
new ArrayList<Object>() {
private static final long serialVersionUID = -5986194903357006553L;
{
// initialize inner anon class
add("1");
}
// Way 1
private Object thisReference1 = this;
// Way 2
private Object getThisReference2() {
return this;
}
#Override
public boolean equals(Object obj) {
// Way 3
final Object thisReference3 = this;
new LinkedList<Object>() {
private static final long serialVersionUID = 900418265794508265L;
{
// initialize inner inner anon class
add("2");
}
#Override
public boolean equals(Object innerObj) {
// achieving the instance
System.out.println(thisReference1);
System.out.println(getThisReference2());
System.out.println(thisReference3);
System.out.println(this);
System.out.println();
// achieving the class
System.out.println(thisReference1.getClass());
System.out.println(getThisReference2().getClass());
System.out.println(thisReference3.getClass());
System.out.println(this.getClass());
System.out.println(this.getClass().getEnclosingClass());
return super.equals(innerObj);
}
}.equals("");
return super.equals(obj);
}
}.equals("");
}
}

pass class name via context and use it to store static value in different class

The dialogue and the array displays just fine, I just want to be able to set the static variable from the originating class within the onClick that is in a method that is in a different class. All of the try, catch and
<?> were things that I put in at the insistence of the compiler:
public class Setter
{
public void myList(Context context, Class<?> thisclass, int arrayid, String choice)
{
return new AlertDialog.Builder(context)
.setItems(arrayid, new OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
setChoice(thisclass, context, arrayid, which, choice);
}
})
.create();
}
public void setChoice(Class<?> thisclass, Context context, int arrayid, int which, String choice)
{
String[] array = context.getResources().getStringArray(arrayid);
try
{
Field f = thisclass.getDeclaredField(choice);
f.set(null, array[which]);
}
catch (SecurityException e)
{
e.printStackTrace();
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
}
}
public class ClassA extends Activity
{
static String stringa;
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
AlertDialog thinga = setted.myList(this, getclass(), R.array.thinga, stringa).show();
...
}
}
When I select an item from the list, I get this from debugger:
ClassCache.findFieldByName(Field[], String) line: 438
Class.getDeclaredField(String) line: 666
Setter.setChoice(Class, Context, int, int, String) line: 45 // the line with the Field
I think I'm passing it the class wrong but this is a bit out of my current depth.
I have a number of different classes each with their own static Strings. I am passing the method below the name of the String (in choice) and the context of what I had hoped was the original class that called a method that called a method that led to the code below. I was hoping I could call context.choice = something and the machine would read that as ClassA.stringa = something; how do I do that?
Briefly, I want to have a list of items that the user can choose from be the content of a dialogue, and have their selection be saved and accessible to the class that called for the creation of the dialogue. Perhaps I'm going about this all wrong but I got tired of dealing with other 'kludges' involving using spinners to do the same thing.
Because onClick can't have non-final objects declared elsewhere (at least that is my understanding) I thought maybe I could get around that by calling to another method, setChoice that would store the value of whatever was chosen. I would definitively say this is a kludge and would love to be shown the light as to how you are supposed to deal with these things.
Java does not have closures, but you can get close with anonymous inner classes.
String output;
public void onCreate() {
Setter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
output = "selected";
}
});
}
See also this swing tutorial: http://download.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
Edit:
In spirit of your example, this should look like this:
public class Setter
{
public void setChoice(IsetString setter, String something)
{
setter.setString(something);
}
}
class ClassA extends Activity implements setString
{
static String stringa;
string polka = "dots";
Setter setted = new Setter();
...
public void onCreate()
{
super.onCreate();
...
setted.setChoice(new IsetString() {
#Override
public void setString(String s) {
stringa = s;
}
}, polka);
...
}
}
interface IsetString {
void setString(String s);
}
The short answer - use the Reflection API.
The long answer - you'll need to obtain access to the Fields of the desired Context Class. Once you gain access to the Field instances, you can set their values using the set() method; the API call is a bit tricky in that you'll need to pass in the object reference (the context object and not the context class) whose field you wish to modify.
It is necessary that your Context, choice and something parameters to the method, contain the necessary information to make this operation as simple as possible. In other words, the Context class might have to contain the actual Class object (or provides a way to get one) that contains the field.
You can use reflection for that. Suppose you context is class itself
public void setChoice(Class<?> context, String choice, String something)
{
try {
Field f = context.getDeclaredField(choice);
f.set(null, something);
} catch (....) {
}
}
Add proper exception handling
Note that first argument to set is null. That is only valid for static methods. So you may want to check that method is static using f.getModifiers().

Categories