I have a set of classes that implement a particular interface and I have a set of checkboxes. I want to throw an error if no checkboxes are selected. If atleast one or more checkboxes are selected, then it should create objects associated with that checkbox.
This is how I done.
interface U { ... }
class A implements U { ... }
class B implements U { ... }
class C implements U { ... }
class Main {
//....
//....
public void findSelectedCheckBoxesAndCreateObjects() {
if(!(checkboxA.isSelected() || checkboxB.isSelected() || checkboxC.isSelected()) {
System.out.println("No checkboxes selected");
return;
}
//if any selected, create associated object
if(checkboxA.isSelected()) new A(file);
if(checkboxB.isSelected()) new B(file);
if(checkboxC.isSelected()) new C(file);
}
}
Now I have 3 problems.
This is just a sample code. Original has 8 checkboxes and classes with more coming.
I can't keep adding || checkboxD.isSelected() every time I have a new class for checking it.
Same thing. I can't keep adding if(checkboxD.isSelected()) new D(file); for every class.
It is very inelegant. Can I have some kind of loop that removes the redundant code?
Please give me your suggestions.
Thank you.
You should use a collection structure to hold your checkboxes and those related classes.
Using a Map you could do something like this:
Map <JCheckBox,Class<U>> uCheck = new HashMap<JCheckBox,Class<U>>();
// add your checkboxes and U-classes to the map
uCheck.put(checkBoxA, A.class);
Now, it's quite easy to get a collection of the classes that need to be instantiated based on the checkbox status:
public Collection<Class<U>> getEnabledClasses(<JCheckBox,Class<U>> checkMap) {
List<Class<U>> result = new LinkedList<Class<U>>();
for (Map.Entry<JCheckBox,Class<U>> entry:checkMap.entrySet()) {
if (entry.getKey().isSelected()) {
result.add(entry.getValue());
}
}
}
Now, a call to getEnabledUs(uCheck) returns a collection of the selected classes. If the collection is empty, there's no selection, hence nothing to do.
for (Class<U> u:getEnabledClasses(...)) {
Constructor<U> cons = u.getConstructor(...);
U instance = cons.newInstance(fileparameter);
instance.doSomething(...);
}
That should get you started.
(*) Disclaimer: this is non-tested code. Rather pseudo-code with crisp detail only where needed.
Related
I'm trying to do a swing application which adds names to an ArrayList and then displays it in Jcombobox.I already did the window and everything but I can't seem to get the hang off detecting duplicate names.
I tried
btnnext.addActionListener(new ActionListener() {
Override
public void actionPerformed(ActionEvent e) {
if(checkDuplicate(names)==true)
{
names.add(txtname.getText());
txtname.setText("");
}
else {
JOptionPane.showMessageDialog(null,"DUPLICATE! do not add");
}
}
});
public static boolean checkDuplicate(ArrayList<String> list) {
HashSet set = new HashSet();
for (int i = 0; i < list.size(); i++) {
boolean val = set.add(list.get(i));
if (val == false) {
return val;
}
}
return true;
}
It only says that I have duplicate when I already add it to the ArrayList and when I get the message I can't add anything else.
input example:
test
test
and then it stops accepting new Strings and only displays the message DUPLICATE! do not add
As I said in my comment:
This happens because you are basically creating a Set view of your ArrayList every time you call checkDuplicate rather than comparing the item you're trying to add with the existing list. In other words your checkDuplicate is written such that it only returns true when a duplicate already exists within the list. You need to compare the new item with the list instead. Step through your logic carefully either with a debugger or by manually writing down the values of your variables and you will see the problem.
You could simply change this line:
if(checkDuplicate(names)==true)
to this:
if(!names.contains(txtname.getText()))
You don't really need checkDuplicate since it's "reinventing the wheel" so to speak. ArrayList already provides a contains method that you can use to your advantage.
I'm currently working on a project to make a simple 2d platformer in Java for uni, and the way we've been suggested to handle levels is to create an abstract level class, and then other classes implementing it for each individual level, so:
abstract class GameLevel {}
class Level1 extends GameLevel {}
class Level2 extends GameLevel {}
etc...
And then in my main class, I have a variable to keep track of the current level number, and code to move on to the next level, which essentially is:
public void goNextLevel() {
world.stop();
if (level == FINAL_LEVEL) {
// win code
} else {
level++;
world = new Level/*next level number*/();
}
}
And I was wondering if there was a way to take the variable containing the level number and add it on to the end of the class call, to save having to have a stack of if else statements.
Thanks for any help in advance
edit: The reason I'm not keen on putting all of it in one class and then using a variable in that to change the level is that each level has to have a relatively large number of entities, which each take a few lines to set up, and adding all of the levels in one file would lead to hundreds of lines of code which would be difficult to maintain
You would do so:
try {
final Class<?> clazz = Class.forName("your.package.Level" + levelInteger);
final Constructor<?> ctor = clazz.getConstructor();
final GameLevel level = (GameLevel) ctor.newInstance();
System.out.println(level.getClass().getName());
} catch (final Exception e) {
e.printStackTrace();
}
Source and explanation: https://stackoverflow.com/a/6094602/8160563
Assuming that there in only ever one object of each LevelN class, the simplest thing to do would be to store them into an array
GameLevel[] levels = new GameLevel[5];
levels[0] = new LevelOne();
levels[1] = new LevelTwo();
And then have a little helper method to retrieve them
GameLevel getNextLevel(int currentLevel) {
return levels[currentLevel];
}
Suppose I have something as follows where DataImporter is a utility to retrieve data from the file system and has child data importers within it for retrieving data from the sub folders based on the category string:
List<String> categories = getCategories();
boolean doesChildImporterExist = false;
for (String category : categories)
{
DataImporter childDataImporter=importer.getChild(category);
if (childDataImporter != null)
{
doesChildImporterExist = true;
populateImportedData(childDataImporter.importData());
}
}
if(!doesChildImporterExist)
populateImportedData(importer.importData());
I know the other option is to construct a List of child data importers and check for its size, if it is 0 or not and based on that import the data using the desired importer. However, I'm trying to understand what is wrong with using the boolean flag here?
Assume that the code above is within a method and using Java 1.7.
When you use a boolean flag in a method as a branch decider (not the best terminology),
you are actually taking the functionality of two different methods and smashing them into one method.
Often,
the better solution is to have a method for the shared functionality and a second method for the super set functionality.
For example:
public DataImporter doYourCategoryStuff()
{
List<String> categories = getCategories();
... blah including the for loop.
return theDataImporter;
}
public void doAllTheStuffs()
{
final DataImporter theDataImporter;
theDataImporter.doYourCategorStuff();
populateImportedData(theDataImporter.importData());
}
Edit
More to the point in your code.
In your code,
the boolean flag indicates "I did something to a child importer and need to update parent importer".
In this case you are smashing "identify things to update" and "do the update" together;
split them.
Consider something like this:
Set<DataImporter> updateSet = new HashSet<>();
for (category for loop)
{
final DataImporter child = importer.getChild(category);
if (child != null)
{
updateSet.add(child);
updateSet.add(importer);
}
}
for (final DataImporter current : updateSet)
{
current.importData();
}
Even though the add(importer) (the parent) may be called multiple times,
the set will only ever contain one instance of each DataImporter.
This should be reasonable even if you don't implement hashCode and equals on DataImporter, since the parent reference will always be the same.
I am hoping to filter an ArrayList of custom model objects down to those matching user-selected values.
The user can filter the different fields of the model object in any manner...
If they select multiple values for the same field (e.g. choosing breakfast and dinner for the "category" field) objects matching any of the selections should be returned. If they simultaneously filter using the "protein" field and choose "chicken" only chicken breakfast and dinner meals should be returned.
I am currently using Guava and Collections2.filter(...), but can't seem to combine the AND/OR logic properly.
Any guidance would be appreciated! :)
Edit: Adding code snippet as an indication that I'm not looking for "moral support"
Collection<FieldAcceptanceLogItem> objectFilter = allLogItems;
for (final Filter filter : mFilters) {
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
#Override
public boolean apply(#javax.annotation.Nullable FieldAcceptanceLogItem input) {
if (filter.getCategory().equalsIgnoreCase(getString(R.string.sublocation))) {
return input.getSublocation().equalsIgnoreCase(filter.getTitle());
}
else if (filter.getCategory().equalsIgnoreCase(getString(R.string.technology))) {
return input.getTechnology().equalsIgnoreCase(filter.getTitle());
}
else { //(filter.getCategory().equalsIgnoreCase(getString(R.string.component)))
return input.getComponent().equalsIgnoreCase(filter.getTitle());
}
}
});
}
So it looks like you want the intersection of sublocation, technology, and component. I moved a couple of things around that should highlight what you're trying to tackle:
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
#Override
public boolean apply(#javax.annotation.Nullable FieldAcceptanceLogItem input) {
return SublocationFilters.from(mFilters).contains(input.getLocation())
&& TechnologyFilters.from(mFilters).contains(input.getTechnology())
&& ComponentFilters.from(mFilters).contains(input.getComponent());
});
SublocationFilters.from(...) will give you all of the sublocation filters
TechnologyFilters.from(...) will give you all of the tech filters
ComponentFilters.from(...) will give you all of the component filters
contains(...) is just a convinient method for doing "filter_1 OR filter_2 OR... filter_n"
If you do want to follow that pattern though, I'd recommend doing something more like this as it is less to write tests for:
new CategoryFilter(mFilters, getString(R.string.component))
.contains(input.getComponent());
Im developing a system that stores courses that participants can apply to.
I'm presenting the enrollments in a JTree in the courseadministratorGUI.
My problem is that, for every enrollment it's adding a new courseNode.
Been trying for many hours, and hope I can now get some advice that will point me in the correct direction.
Thank you.
private void updateJTree() {
for (Category cat : catcontrol.getAllCategoriesList()) {
category = new DefaultMutableTreeNode(cat);
for (Course c : ccontrol.getAllCourses()) {
if (cat.getIdCategory() == c.getIdCategory()) {
for (Enrollment e : econtrol.getAllEnrollments()) {
if (e.getIdCourse() == c.getIdCourse()) {
if (cat.getIdCategory() == c.getIdCategory() && e.getCourse().equals(c)) {
root.add(category);
}
if (c.getIdCourse() == e.getIdCourse()) {
course = new DefaultMutableTreeNode(c);
category.add(course);
enrollment = new DefaultMutableTreeNode(e.getParticipant().getFirstNames());
course.add(enrollment);
}
}
}
}
}
}
jTree1.setModel(new DefaultTreeModel(root));
jTree1.addTreeSelectionListener(this);
jTree1.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
}
I am not sure I understand the question, but... why "for every enrollment it's adding a new courseNode"? Because you're telling it to. Right here:
course = new DefaultMutableTreeNode(c);
category.add(course);
enrollment = new DefaultMutableTreeNode(e.getParticipant().getFirstNames());
course.add(enrollment);
Add course, then add an enrollment. Always in pairs. Now I don't know the structure of your data, but I dare say that is not what you want. Can you describe in more detail what Enrollment is (one person? list of people? something else?), and what getParticipant() returns, and what do you want to appear in the tree?
One more comment - you do realise that these two if statements check the same thing, right? You can get rid of the inner one, since it's not doing anything. Or, more likely, rewrite to do something useful (however, as I said, I am not too sure what it is you want to do).
if (e.getIdCourse() == c.getIdCourse()) {
// ...
if (c.getIdCourse() == e.getIdCourse()) {