I'm doing a favor for an engineer friend by making him a program that helps him with the scheduling of his factory's production. Each type of product is broken down to a set of steps (they share a lot of them, but there are a few differences).
The programming issue:
Each time a new production process is registered I display a number of checkboxes representing the before mentioned steps. He can choose which steps he needs added for this particular product. If he checks a checkbox, two (or more) textfields appear where he can add additional information (starting date, duration, comments, etc...). My problem is that this is a lot of individual components and I am unsure how to handle them. Since I will need to have access to all of them at some point (the checkboxes to see if that step is needed and all the textfields for the data) I was thinking of having them all as fields, but that doesn't feel right...
Another approach could be to make a container class that groups the textfields together with the checkbox. Something like this:
ArrayList<MyComponentGroup> group;
for (MyComponentGroup cg : group) {
if (cg.getCheckBox().isSelected()) {
//access and read the data from all the textfields in this object
}
}
What is the Java programming convention or the most commonly used method to handle this situation?
Here's what I would do when dealing with tons of components and similar requirements:
I would model the relationship between options (available through checkbox selections) and the related data to fill (requirements). This model may already be available for you.
I would attempt to use PropertyEditor instances and map them to model elements.
When the time comes to save or use the data filled by the user, I would just walk the model represented on the screen, grab the associated editors and deal with the value of those editors.
I think that the approach that I described above will give you less work and potentially and it will bring more flexibility for your friend.
You'd only pay the initial cost of getting the components relationships/dependencies in a nice model as well as registering the relevant PropertyEditors for visual editing.
One approach is to consistently give each JComponent a unique name. Use something hierarchical to fit the complex process, like "Whites.Rinsecycle.enableCB". For completeness, store this String as a clientProperty in the JComponent. Then you can use that as a key in a large Map to access all the components.
Maybe not the most "elegant" (I'd tend to go with a hierarchy of JPanels with relevant fields) but for a slightly quick and dirty, moderate sized project this is reasonable.
Related
Domain model are
Event (Fun, Sports, Quiz ) has many Problems (Fun problems, Sports, Quiz related problems).
Problem has many solutions (each team uploads a solution), solution has many grade (each Judge posts grade).
Initial goal is to start with one type of event (for example Quiz event) and it has multiple problems and solutions. Judge can grade the solutions.
In future there may be new type of event (Spots event) can come in with different properties & behaviours. For the sports event, problem may have new set of properties & behaviours and solution module should be disabled because for sports event judge can directly update grade.
So do i need to have workflow for each event, to turn on & off a particular module.
want to do as micro services with spring boot with mongodb.
What i done so far
I have
abstract class for Event, Problem, Solution and grade (Based on the event type grading property may change).
Registration domain with Team, Problem and solution as reference property.
How to proceed further and am i do it current ?
I think you can start by modeling an scalable design. In my opinion the starting point is correct as you have to distinguish between Events, Problems, Solutions, Teams and Judges.
Once this is done, I always try to make things as much generic as I can, so when I start to mix all the pieces they can interact independently of their real state. This is, I try to make the interaction between the pieces just by using their interfaces / abstract classes (One problem -> Many Solutions, One Team -> One Solution, etc). I see no information about those properties you talk about, but I suposse they can belong to the generic Problem and just be configured on each specific type of Problem (but not declared).
If you are able to achieve this, you can then create an enumeration for the types (Fun, Sports, Quiz, Spots) so you can configure each type of problem by the relationship Problem-Type.
I don't know how to represent the Problems as I have not enough information on your domain. But what I would do is something like this, so when new types of problems appear in the future I only have to create a new type enumeration value and its relationships:
Undertand it just as an example for making easier for you to understand my words, it's quite far from what the real design would be as I have not enough information about each piece on the puzzle.
Even though, with that as an starting point you can choose to apply some interesting design patterns such as Abstract Factory (if you want to supply the solution as a template for a given problem, so teams have to fill it instead of creating it from scratch) or Strategy Pattern (so you can interact the same way with each Problem and let the behaviour be controlled depending on the ProblemType or any other variable that determines the Problem state).
As a summary:
Try to extract the common factor of each part and how it itneracts with other ones.
Additionally, try to make interaction independently of particular types and properties, exposing as much as you can in the common interfaces (as long as it makes sense, obviously).
If not possible, Abstract Factory is an option, so it lets you make internal relationships aware of implementation details without coupling the external parts.
Once you do that you will be one step closer to making a dynamic model that grows with no efforts meeting your needs.
Wicket has many implementations of AbstractRepeaters: ListView, DataView, GridView, Loop, PropertyListView etc.
Personally, I find it hard to determine which view would be ideal for which scenario. I usually stick to DataView but that's simply because I'm used to it. Maybe GridView would be better for scenario A, a PropertyListView for B, ....
Is anyone aware of a blog or any tutorial where the differences of the views are explained or anyone who can explain which view is best for which use case?
Wicket has a lot of additional, trivial classes, which is causing your confusion. Different components are better for different scenarios, but there are a lot of Wicket components for rare cases that don't add any real complexity.
For example, RequiredTextField is an entire class that is equivalent to:
TextField x = new TextField("text");
x.setRequired(true);
I presume this stems from an older version where setting required was more complicated, but it's still there to cause some confusion.
Many of your repeaters are similar. PropertyListView just wraps the model in a CompoundPropertyModel, making property expressions easier (see below). However, you could easily make this change yourself.
So, here is my quick summary as I have been unable to find an up-to-date blog post as you've described:
RepeatingView - very useful when you do not have a list or you are adding different types of components (and therefore different internal markup).
ListView - useful if you have a List and you're displaying the whole thing. Sadly, it does not work with other sorted collections.
DataView - useful if you are loading from a Database. Additional methods allow you to easily sort, page, and modify the data set.
PropertyListView - useful if you are simply displaying values via a property expression. Allows you to do
item.add(new Label("name"));
instead of
item.add(new Label("name", new PropertyModel<String>(item.getModel(), "name")))
Loop - useful if you want to repeat an Integer number of times instead of a set list of data. This would be equivalent to a ListView whose model object is a List<Integer> filled with integers from 0 to length
GridView - useful for taking a single list (e.g. 21 strings) and using two sets of markup (inner/outer) to display that list in groups (e.g. a 7x3 grid). It assumes, however, that your markup uses certain wicket:id's, which is not well documented. I think you would be better off with a pair of nested RepeatingView components, which accomplish the same thing.
Hope that helps!
The problem described below relates to an inventory tracking Java program. There are multiple classes of inventory item and it is not possible to determine up front what properties of the intentory class are being tracked. Taking two classes for example:
InventoryClassOne {
String name;
Double price
}
InventoryClassTwo {
StockStatus status;
Long Quantity
}.
Storing the data is no problem, I can just define a
class InventoryProperty<T> {
T value;
}
and a
class InventoryClass {
Map<String, InventoryProperty<?>> inventoryPropertyMap;
}
The UI will be developed using the Wicket framework. I want to provide the administrator of the application with a means of adding new InventoryClasses and defining how the data gets laid out (tabular, list, etc...) on a per InventoryClass basis. Has anyone ever solved this type of problem before? What design patterns are available for achieving this. I don’t even know what words to type into Google in order get ideas for how to solve this.
As much as I love Wicket, I really don't think it is the best option for this kind of meta-website.
But if I absolutely had to do it in Wicket, this is what I'd do:
Create a Fragment for each basic UI widget.
On the admin page you create a mapping from each field of your inventory class to a pre-fab fragment. (You'll have to use reflection to query what fields are available.)
When you're constructing your UI page, you create a repeater (a ListView for example, but even a simple repeater will do) which for each entry in your Field->Fragment mapping adds the fragment with a model pointing at the field.
You might need to tweak it a bit, especially with tables but this is the basic idea.
However, and I have to repeat this, you're practically losing most of the advantages of Wicket, even worse, you'll have to put extra effort in to work your way around (or against) Wicket. It just doesn't seem to be worth it.
I'm helping to build a GWT application for a client and rewrote most of the stuff to work better, shorter code, faster, etc. However in all the GUI application I've worked on (not so many really) there comes a flexing point where you just have to put a lot of rules and move logic from the listeners to some common mediator. Then some times this could get an ugly mess so you whatever small think you need to do in the listener.
Let's take an example:
form with 10-20 fields
two exclusive radio control about half of the state of the other fields (enabling, validation, input limits)
three exclusive radio controls control again almost the same fields, but in a different way (affecting calculations, enabling); they are also controlled by the above
4 or so number fields are validated on the fly depending on the previous selections and some real-time data object; they can have upper/lower limits, be enabled/disabled
one drop-down box controls the next 6 or so controls - displaying/hiding them, modifying validators
some checkboxes (shown by the above combo) activate some input fields and also determine their validation algorithm
While everything is up an running, without known bugs, there are a few coding gotchas that really bother me:
code is spread among listeners and some mediator methods.
loading the form with some preset values presents its own challenges: like data objects that might be available or not, data objects that might alter their state and subsequent field behaviour
some fields are having a default value set and this should not be overwritten by automatic filling, but if the data objects are not there (yet) then they will need to be filled eventually when the later become available
form cannot be submitted if any of the fields are not validated
My approach:
identify which fields share a common afair and move code into one place
each radio group shares a single listener implementation between its radios
default form filling is deferred until the live data is available (as much as possible) and as a result it gets called multiple times
each action has a call to a common validator method
the validator runs through all the fields in the form, calls their validators (which highlight all errors) and returns a single boolean
each relevant keypress or mouse action, data change it gets deferred to be called after 250ms from the last call; this means first call just places the validator as a delayed action, subsequent calls reset the timer
Ok, it doesn't make any sense to dwelve into more details but I'm more upset about the fact that there is no clear separation between visual actions (enabling), data actions (setting form field values), field listeners, retrieving form values and live data listeners.
What would be a good approach/pattern (next time maybe) to make sure that MVC get separated and lends itself better to maintenance? I know this is not a typical question but I've read every documentation I could get my hands on and still did not find some helpful answer.
I'd move closer towards MVP than MVC. It's clearly the way Google intends to go, so adopting it will probably mean that you're able to go with the flow rather than fight the current.
How does this affect you? Well, I believe you should accept that a tidier implementation may involve more code: not the 'shorter code' you were hoping for. But, if it's logically structured, efficient code the Google compiler should be able to trim lots out in the compiler optimisation phase.
So, move as much of the logic as you can into the model layer. Test this thoroughly, and verify that the correct level of page reset/tidying happens (all of this can be done with plain JUnit, without any UI). Next, use your Presenter (Activity) to tie the View to the Model: handling the interactions, populating the fields, etc.
you can divide a Huge class in different classes bu dividing the GUI in different JPanels. All the panels are implemented in different classes extending JPanel. Guess that would help you.
The Wicket examples page for TabbedPanel (link) uses separate, distinct classes for each tab (TabPanel1, TabPanel2 and TabPanel3). Is there a reason to not just use three instances of the same class? If yes, what is it? I'm still fairly new to Wicket, but those classes look identical to me.
EDIT: I ran a simple example, using three objects all of class tabPanel. Each one was set to use a different label, and they did display properly.
EDIT AGAIN: After doing more experimentation and reading the later-posted answers, I realized my first example was too simple. Using one class, the tab title can be different but the logic would still be the same. That wouldn't work unless, as someone mentioned, it became a "Swiss Army Knife" class, which is poor design. And that still wouldn't address the markup file.
Wicket is designed to encourage the development of reusable Components. Consider the three different Classes as different components you'll want to use in different pages of your application with entirely different behaviour and content. Say Tab1 for contact information, Tab2 for a map and Tab3 for pictures. You really wouldn't want to create a Swiss-Army-Knife-Panel to manage all of those different purposes. So different panel-classes are used in the example.
Admittedly the example doesn't use the best values - but it might be a better idea if you start with the general principles of wicket (take special care in learning how working with models works) rather than with these special components from the wicket-extension package.
If you'd use three instances of the same class, you'd end up with the same content on each tab... Not very usefull is it?
As you have shown it is possible, and would work well where the display of the panel is controlled by the model.
Lets say you had a component that displayed and address, with an embedded google maps image of the location..
You could create 3 instances of the same "AddressWithMapPanel" passing in a different model to each, with each table being the "Home", "Work", "Other" addresses. There you can then use the tab logic to switch between viewing the different addresses, keeping the same UI changes in a central place but getting different content.