JavaFx: CustomTableSkin with CustomTableHeaderRow - java

I am working on a CustomTableViewSkin, where I pass some config arguments to configure my skin depending on the parameter passed to.
One of the config possibility is related to the TableHeaderRow which is initialized in the init method of the ableHeaderRow which is called in the constructor.
Since I am forced to call the super constructor, there aren't my config parameters yet initialized, and even if I #Override the createTableHeaderRow() it doesn't really work as I need.
I found a solution or better said, a workaround but I'm not sure how safe is it to use.
Here is a simple code, which shows what I mean.
public class MyTableSkin<T> extends TableViewSkin<T> {
private Set<Param> params;
public MyTableSkin(TableView<T> tableView, Set<Param> params) {
super(tableView);
this.params = params;
}
#Override
protected TableHeaderRow createTableHeaderRow() {
// NPE at params since this method is called in super constructor there params are not initialized.
if (params.contains(Param.TABLE_HEADER)) {
return new MyTableHeaderRow(this);
}
return super.createTableHeaderRow();
}
private static class MyTableHeaderRow extends TableHeaderRow {
public MyTableHeaderRow(TableViewSkinBase skin) {
super(skin);
}
}
public enum Param {
TABLE_HEADER
}
}
After a little bit experimenting I found this way:
public class MyTableSkin<T> extends TableViewSkin<T> {
private Set<Param> params;
public MyTableSkin(TableView<T> tableView, Set<Param> params) {
super(tableView);
this.params = params;
getChildren().clear(); // if I didn't do this an exception is thrown
// calling init again to "reinitialize" the skin.
super.init(tableView); // how safe is this? :)
}
#Override
protected TableHeaderRow createTableHeaderRow() {
// Now it enters the if after the second init call, after params are initialized.
if (params != null && params.contains(Param.TABLE_HEADER)) {
return new MyTableHeaderRow(this);
}
return super.createTableHeaderRow();
}
private static class MyTableHeaderRow extends TableHeaderRow {
public MyTableHeaderRow(TableViewSkinBase skin) {
super(skin);
}
}
public enum Param {
TABLE_HEADER
}
}
This way it works and I get my new fancy `table header, however I see the init has a lot of things in it, it does the listener initialization and many other stuff.
The main question is: is this way safe? Do I have to worry about the other stuff which is done in the init, or simply ignore them? I am thinking about the double registering the listeners for example.
If this is not so safe, or at all, I would suggest any modification to my code, or even a completely new solution which allows me to customize the header if a param is set. This custom skin is not only for the header. params could contain a lot of configurations which can be done to the skin, so I cannot really create a new skin for every configuration/parameter.

Related

Java: Parameter traversal?

I have this code:
public class Compiler {
public void compile(String template, Object o, Object params) {
//...
context(o, params);
//...
}
private void context(Object o, Object params) {
//...
substitue(o, params);
//...
}
private void substitue(Object o, Object params) {
//...
print(params);
//...
}
private void print(Object params) {//use parameter params here, only here
//...
System.out.println(params);
//...
}
}
As you can see, the parameter params is used only in the print method, not in compile, context or substitue. The problem is adding the params to the signature of all the methods down to print.
In general, when I'm facing this problem I refactor my code like the following :
public class Compiler {
public void compile(String template, Object o, Object params) {
//...
new InnerCompiler(template, o, params).compile();
//...
}
private static class InnerCompiler {
private final String template;
private final Object o;
private final Object params;
InnerCompiler(String template, Object o, Object params) {
this.template = template;
this.o = o;
this.params = params;
}
private void compile() {
//...
context();
//...
}
private void context() {
//...
substitue();
//...
}
private vois substitue() {
//...
print();
//...
}
private void print() {
//...
System.out.println(this.params);
//...
}
}
}
This is a very basic example to illustrate the case of passing a parameter to all the methods even if it is not used by the method itself but by the next one (or deeper).
I'm looking for the name of this problem (maybe an anti-pattern). In the title I've put (Parameter traversal) but it could be wrong or it means another thing.
The first version of your code where you were passing parameters repeatedly down through the call-stack is referred to as "tramp data". You can read about it in a similar question on the Software Engineering site. What I think you're trying to do is to use Dependency Injection. I say "trying" because you're not injecting your dependencies into the Compiler instance, itself.
Instead, I would argue that what you're actually using is a really small version of the Bounded Context pattern. By this, I mean that your InnerCompiler class is a bounded context as described in Domain-Driven Design and might be more aptly named: CompilerContext. That being said, bounded contexts are usually domain level constructs that you are using to encapsulate complicated service-level data sets. A set of three parameters don't usually merit the term "bounded context", but that threshold is pretty subjective IMO, and you might be oversimplifying your code here for the sake of an easily understandable MCVE.
To use the DI pattern in a more standard form, I would change your code to something like the following:
public class Compiler {
private final String template;
private final Object o;
private final Object params;
Compiler(String template, Object o, Object params) {
this.template = template;
this.o = o;
this.params = params;
}
public void compile() {
//...
context();
//...
}
private void context() {
//...
substitute();
//...
}
private void substitute() {
//...
print();
//...
}
private void print() {
//...
System.out.println(this.params);
//...
}
}
This achieves what you're doing right now, without resorting to an artificial inner class.
Note that if you truly need something like a compiler to be used as a singleton as you have in your version of the code, consider using a CompilerFactory class with a newCompiler() method which would call the constructor and inject the dependencies.
I hope this answers your question. I know that this answer isn't a pattern out of the Design Patterns book by the Gang of Four, but IMO none of the patterns in that book truly reflect your code or your intent.
What you are trying to do seems to me to change parameter passing to global state.

factory object creation using per-subclass method

I have a simple Factory (GenericFudge) that creates objects of different types depending on external circumstances. Currently, my code looks something like this:
abstract class Fudge {
Fudge() {
}
void make() {
System.out.println("made.");
}
}
class VanillaFudge extends Fudge {
#Override
void make() {
System.out.print("Vanilla ");
super.make();
}
}
class ChocolateFudge extends Fudge {
#Override
void make() {
System.out.print("Chocolate ");
super.make();
}
}
class InvalidFlavorException extends Exception {};
// factory / proxy
public class GenericFudge {
Fudge mFudge = null;
GenericFudge(String flavor) throws InvalidFlavorException {
if (flavor.equals("Chocolate")) {
mFudge = new ChocolateFudge();
} else if (flavor.equals("Vanilla")) {
mFudge = new VanillaFudge();
}
}
void make() {
mFudge.make();
}
public static void main(String args[]) {
for (String flavor : new String[] {"Chocolate", "Vanilla"}) {
GenericFudge fudge;
try {
fudge = new GenericFudge(flavor);
fudge.make();
} catch (InvalidFlavorException e) {
System.out.println("Sorry, we don't make that flavor");
}
}
}
}
My goal is to get the details of chocolate and vanilla out of GenericFudge, so that when CaramelFudge is implemented, no changes to GenericFudge are required. For example, GenericFudge would iteratively call a "createIfItsMyFlavor()" method for every xxxFudge class. (In my actual application, I have to try them iteratively, but I'd be interested in other possibilities.)
My instinct was to use a static initializer per subclass (per xxxFudge) that adds "itself" to a list by calling a registerFudge method of GenericFudge, but this hits the chicken-and-egg problem (the class is never used, so its static initializer never gets invoked).
No doubt there's a better way I haven't envisioned. Thanks!
If you are using any kind of dependency injection system like Spring, this is easy to implement using #PostConstruct. If this works, then you can call a register method in GenericFudge from the method you annotate with PostConstruct. In GenericFudge, you have a map, and whenever addType is called you add it to the map. That way your GenericFudge remains unchanged, and new callers will register using PostConstruct. To simplify things further, you can define this in your base class Fudge, and pass the fudge name using the constructor, that way you don't have to declare the register method in each sub-class.
private String fudge;
public Fudge(final String fudge) {
this.fudge = fudge;
}
#Autowired
private GenericFudge fudge;
#PostConstruct
private void register() {
fudge.addType(fudge, this);
}
In GenericFudge
private Map<String, Fudge> fudgeTypes = Maps.newHashMap();
public void register(final String fudgeType, final Fudge fudgeInstance) {
fudgeTypes.put(fudgeType, fudgeInstance);
}
If you do not use any dependency injection system:
Another approach could be to have a static method in the base class Fudge, where you declare all the types of fudge and then return an instance based on the request. That way you don't modify the GenericFudge class, but only the base class of Fudge. This is not ideal, but it gets you away from having to modify the GenericFudge class, and instead of "registering" with something like PostConstruct, you put an entry into the Map.
Example (ImmutableMap from Guava, you can declare the map however you like , this is only for the example):
public abstract class Fudge {
private static final Map<String, Fudge> FUDGE_TYPES = ImmutableMap.of(
"Type1", new Type1Fudge(),
"Type2", new Type2Fudge()
// Add new entry when implemented
);
public static Fudge getFudge(final String fudge) {
if (FUDGE_TYPES.containsKey(fudge)) {
return FUDGE_TYPES.get(fudge);
} else {
// handle missing fudge depending on your preference
}
}
}

Async task using generics for different return types from doInBackground

I have a utility class that extends Async task. I will be using this call to make HTTP requests in the background but I will also have more specialized sub classes of this that prepare the parameters, headers, url to call, so I can remove more common work from the GUI.
The issue is that I want to make use of Generics. The base API class doInBackground will return a string, there's a more specialized Json subclass that will call parent and return a JSONObject and do some parsing of the json response, there's specialized classes that extend the Json subclass and return List of custom objects, and so on. The reason for this is if we need to swap in XML and XML processing the specialized sub classes will have both a JSON and XML implementation. This is because we are re-using for a couple different api's overall.
So I tried playing around with Generics but I'm not 100% sure I understand the implementation in this case. It's obvious when you want to do things like List and make a list of List but how do I apply it here? I think I'm mainly confused about mocking up the code vs implementation, will everything just be T in the base and subclasses, than when I instantiate instances somewhere else like in the GUI that's when I specify the type of return I expect? Than I think I understand. So what I'm saying is when writing up the classes I only use T, never specify a Type and in the code where I instantiate instances that's when I specify a type and that's what the return type of doInBackground will be?
I also want to be able to implement onPostExecute() generically because I will use a callback setup so the GUI can easily subscribe to when the call is finished and process the result, but the interfact will also have a generic for the onPostExecute(T response). So I can create new instances, pass 'this', and when the async task is finished it will call the callback with the result and the callback can handle the appropriate type.
public class Base<T> extends AsyncTask<String, Integer, T>
{
protected Callback callback = null; //interface implemented for processing response
public Base setCallback(Callback callback){ this.callback = callback; return this; }
#Override
protected T doInBackground(String... uri)
{
//do http call
String response = "";
return response; //raw string of server response
}
#Override
final protected void onPostExecute(T result)
{
//no overrides, same every time
if( callback != null )
{
callback.finished(result); //forward generic result, but there it will be typed
}
}
public class JsonBase<T> extends Base<T>
{
#Override
protected T doInBackground(String... uri)
{
//this will be a JSONObject returned
String result = (String)super.dpInBackground(uri); //gives me back a string
return new JSONObject(result); //return a json object
}
}
public class SpecializedBase<T> extends JsonBase<T>
{
#Override
protected T doInBackground(String... uri)
{
//this will be a List<String> returned
//iterate over all json array strings and pass back
return new List<String>();
}
}
class FragmentFoo extends Fragment implements Callback
{
#Override
protected void onViewCreate(...)
{
//Example usage
new JsonBase< JSONObject >().setCallback(this).execute("<url">);
new SpecializedBase< List<String> >().setCallback(this).execute(""); //hard coded internally for example
}
//Can we do something like this?
#Override
protected void finished(JSONObject object)
{
//handle json response
}
#Override
protected void finished(List<String> strings)
{
//handle list of strings response
}
}
interface Callback
{
public <T> void finish(T response);
}
The specialized sub classes of Async will be tailored to specific types, and return different types, and we want to handle those specialized type depending on where we are in the GUI and what we're doing. Otherwise all we can do is all the logic in the GUI or have another middle layer of wrappers...This is all just a primitive example illustrating my point and how we want this to work.
Just kept T and anytime it complained about casting (T)response I just added a suppress warning. As long as I know what to expect in the specific callback and cast to that type, it's fine. But could easily crash at runtime if I make a mistake and cast it to something else.
It compiles, runs, and works. But doesn't seem like a clean appropriate solution.
I know this is an old question but I've just come across it - used most of your solution and improved it a little to solve the issue you had.
I'll just paste the code, but basically just type the list but rather than using it as a return value I use an integer static for the return value in the callback and create the list as a field of the asynctask object itself which is then accessed in the callback method. (I also use a DatabaseLoaderParams for clarity)
public class DatabaseLoader<T> extends AsyncTask<DatabaseLoaderParams, Void, Integer> {
ArrayList<T> returnList;
protected DbLoaderCallback callback = null; //interface implemented for processing response
public DatabaseLoader setCallback(DbLoaderCallback callback){ this.callback = callback; return this; }
#Override
protected Integer doInBackground(DatabaseLoaderParams... params) {
//you have to give the object class to the asynctask
ArrayList<T> mReturnList = getList(params[0].objectClass);
try {
// DB loading code
} catch (Exception e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
// Done!
returnList=mReturnList;
return params[0].startId;
}
#Override
final protected void onPostExecute(Integer startId)
{
if( callback != null && startId>0)
{
callback.onLoadFinished(startId); //forward generic result, but there it will be typed
}
}
private <T> ArrayList<T> getList(Class<T> requiredType) {
return new ArrayList<T>();
}
In the activity:
#Override
public void onLoadFinished(int startId)
{
switch(startId){
case INTEGER_STATIC:
//check the type if you want but I don't bother
for(DBObject dbObject : DBLoader.returnList){
....

Refactoring predecessor code

I'd like to ask for help and some suggestion how to refactor source code which I receive.
Here is pseudocode of my method:
public void generalMethod(String type) {
InputParameters params = new InputParameters();
if (type.equals("someKey1"){
decodeSomeKey1(params);
} else if (type.equals("someKey2"){
decodeSomeKey2(params);
} else if (type.equals("someKey3"){
decodeSomeKey3(params);
} else if (type.equals("someKey4"){
etc...
}
}
}
All methods have the same input parameters. In first step I created new interface and created for each method separate class which implements created interface.
interface ISomeInterfaceDecoder {
void decode(InputParameters params);
}
class DecodeSomeKey1 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
class DecodeSomeKey2 implements ISomeInterfaceDecoder {
#Override
public void decode(InputParameters params) {
// some implementation
}
}
Then I created factory class as follows:
class Factory {
ISomeInterfaceDecoder getDecoder(String type) {
if (type.equals("someKey1"){
return new DecodeSomeKey1();
} else if (type.equals("someKey2"){
return new DecodeSomeKey2();
} else if (type.equals("someKey3"){
return new DecodeSomeKey3());
} else if (type.equals("someKey3"){
etc...
}
}
}
}
After these changes the code looks like this:
class SomeClass {
Factory factory = new Factory();
public void generalMethod(String type) {
InputParameters params = new InputParameters();
ISomeInterfaceDecoder decoder = factory.getDecoder(type);
decoder.decode(params);
}
}
Code of this method looks better but...
This method is called very very often. Each time a new instance of the given class is created. This can cause performance problems. So, I think it's not good approach to this problem.
Can you give me some suggestion how I should to refactor this code?
Thanks in advance for help.
Instead of having a key as a String, make it an enum. Then in the enum you can implement the decode() method like this:
public enum MyKeyEnum {
VALUE1 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE1
}
},
VALUE2 {
public void decode(InputParameters ip) {
// do specific decoding for VALUE2
}
}
...
;
public abstract void decode(InputParameters ip);
}
Now in the calling code you can do something like this:
public void generalMethod(MyKeyEnum type) {
InputParameters params = new InputParameters();
type.decode(params);
}
The advantage is that all the decode methods are in 1 enum, you dont need a specific class for each of the decoders. Also when a new value is added to the enum, you cannot forget to implement the decode method (or it will not compile).
Can you give me some suggestion how I should to refactor this code?
I see no mention of automated regression testing, and that would be my first step, to put in a test suite (via, say, JUnit or TestNG) before going further.
After that, I'd perhaps introduce a Map of String keys to Decoder objects.
But put the test framework in first. Otherwise you'll never really know if you've introduced bugs or different modes of operation.
Introduce caching/singletons in your factory, that you only return an algorithm once. Also, make your factory a singleton.
Create a static Map<String, ISomeInterfaceDecoder> where you map the identifier to algorithms executing the call which means no factory class and no algorithm instantiation. Works only, if you have stateless algorithms.

Refactoring classes that use global variables

I'm working on some classes that get part of their configuration from global variables, e.g.
class MyClass {
public void MyClass(Hashtable<String, String> params) {
this.foo = GlobalClass.GLOBALVAR.get("foo");
this.bar = GlobalClass.GLOBALVAR.get("bar");
this.params = params;
}
}
This is bad for a couple of reasons, GLOBALVAR talks to a database to get some of the variables and this makes it really hard to make unit tests. The other problem is that I have many (dozens) of classes that inherit from MyClass, so I can't easily change the constructor signature.
My current solution is to create an additional default constructor and setter methods for params, foo and bar.
class MyClass {
// Other code still here for backwards compatibility.
public void MyClass() {
// Do nothing much.
}
public void setParams(Hashtable<String, String> params) {
this.params = params;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
Any ideas on a good way to refactor this, besides the way I did it? My other thought would be to use a factory method, but I'm afraid I'll run into polymorphic substitution problems.
I think I would start by doing the following. It let's your existing code work without modification, and allows you to add new constructors to the subclasses as you can. Once all of the subclasses have the new constructor, and all of the calls to the old constructors are gone, you can get rid of the GlobalClass and the constructors that use it. You can also then, hopefully, work on cleaning up the GLOBALVAR (the Car class in my code).
import java.util.Hashtable;
class MyClass
{
private final Foo foo;
private final Bar bar;
private final Hashtable<String, String> params;
public MyClass(final Hashtable<String, String> params)
{
this(params, GlobalClass.GLOBALVAR);
}
// added constructor
public MyClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
this.foo = fooBar.getFoo();
this.bar = fooBar.getBar();
this.params = params;
}
}
class MySubClass
extends MyClass
{
public MySubClass(final Hashtable<String, String> params)
{
super(params);
}
// added constructor
public MySubClass(final Hashtable<String, String> params,
final FooBar fooBar)
{
super(params, fooBar);
}
}
// unchanged
class GlobalClass
{
public static Car GLOBALVAR;
}
// added interface
interface FooBar
{
Foo getFoo();
Bar getBar();
}
class Car
// added implements
implements FooBar
{
private Foo foo = new Foo();
private Bar bar = new Bar();
public Object get(final String name)
{
if(name.equals("foo"))
{
return (foo);
}
if(name.equals("bar"))
{
return (bar);
}
throw new Error();
}
// added method
public Foo getFoo()
{
return ((Foo)get("foo"));
}
// added method
public Bar getBar()
{
return ((Bar)get("bar"));
}
}
// unchanged
class Foo
{
}
// unchanged
class Bar
{
}
I think you should introduce an interface to put a layer of abstraction between the global variable collection and its consumers.
interface GlobalVars {
String get(String key);
}
You should introduce a constructor with limited scope, probably package-private
MyClass(GlobalVars globals, Map<String, String> params) {
// create the object
}
And then provide public static factory methods to use this constructor.
public static MyClass newMyClass(Map<String, String> params) {
return new MyClass(GlobalClass.GLOBAL_VAR, params);
}
With this design you can pass in a mock implementation of GlobalVars in a unit test from within the same package by explicitly invoking the constructor.
Addendum: Since params seems to be a required field, I would definitely make it final and avoid the approach where you add mutators to overwrite them.
private final Map<String, String> params;
Also, make a defensive copy to prevent l33t h4x.
this.params = Collections.unmodifiableMap(params);
Your class should take all of its dependencies in the constructor. It's a good idea to make it impossible to create an invalid or uninitialized instance of classes. Make foo and bar private and final, and set them in the constructor.
A slight variation on your approach would be to have an object of type GLOBALVAR in the class and use that instead of the actual global (that refactoring should be a simple search/replace). You can default the new variable to the actual global variable and provide an override for testing.
This GlobalClass.GLOBALVAR should be chopped up up into logical units. That way it would be easier to make mock objects for the unit tests. For example in my CAD/CAM metal cutting application I have a MaterialList, a SheetSizeList, PartNestingParameters, etc.
I don't have a huge list of variables stuff into one giant AppParameter class. They all hang off a ShopStandards object. For Unit Test involving a specific PartNestingParmeters I will just go ShopStandards.PartNestingParmeters = new MockPartNestingParameterTest114(). The test will run not realizing that the Part Nesting Parameters are a mockup. Plus this save me from having to doing dozens of assignments just to get the ShopStandard setup correctly for the test.
We have even more automated where many of the Mock load from files saved during the test run during initial development.
Since you mention that you have the freedom to modify the class hierarchy.
Change the base MyClass ctor to take in 3 parameters params, foo and bar. Comment out the GlobalVar references and simply cache passed in values
Compile.. this should throw up a bunch of compile errors - no ctor which takes 1 parameter.
Fix each one to pass in GlobalVar.get("foo") and GlobalVar.get("bar"). Get it to build.
Refine: Now minimize hits to the DB by lazy load and caching the foo and bar values. Expose via some property on GlobalVar.

Categories

Resources