problem with setSelectedValue Method for JList - java

i am having troubles when i run the main class for the application. The fact is that the setSelectedValue method doesn't work.
the code for the main class is the following:
DatabaseConnection.getInstance().connect("org.sqlite.JDBC", "jdbc:sqlite:db/Universidad.sqlite");
DatabaseTableManagers managers = DatabaseTableManagers.getInstance();
DataBaseManagerJList.getInstance().setSelectedValue("Alumnos");
system.out.println(DataBaseManagerJList.getInstance().devolver() + "1");
AlumnosTableManager atm = AlumnosTableManager.getInstance();
System.out.println(DataBaseManagerJList.getInstance().devolver() + "2");
CarrerasTableManager ctm = CarrerasTableManager.getInstance();
System.out.println(DataBaseManagerJList.getInstance().devolver() + "3");
managers.add(atm);
System.out.println(DataBaseManagerJList.getInstance().devolver() + "4");
managers.add(ctm);
System.out.println(DataBaseManagerJList.getInstance().devolver() + "5");
DataBaseManagerJFrame dbmf = new DataBaseManagerJFrame();
System.out.println(DataBaseManagerJList.getInstance().devolver() + "6");
dbmf.setVisible(true);
}
}
and i get the following result in console which shows me that the method doesn't set the default value i've put:
null1
null2
null3
null4
null5
null6
the code for the jlist class is the following:
public class DataBaseManagerJList extends JPanel
{
private static final long serialVersionUID = 1L;
private static JList tablas;
DefaultListModel model;
DatabaseTableManagers dtm = DatabaseTableManagers.getInstance();
private static DataBaseManagerJList instance = null;
public static DataBaseManagerJList getInstance()
{
if (instance == null)
{
instance = new DataBaseManagerJList();
}
return instance;
}
public DataBaseManagerJList()
{
model = new DefaultListModel();
ArrayList<String> aux = new ArrayList<String>(dtm.getTableNames());
for(int i =0;i<aux.size();i++)
{
model.addElement(aux.get(i));
}
tablas = new JList(model);
//tablas.setSelectedValue("Alumnos",true);
add(tablas);
}
public String devolver()
{
return (String) tablas.getSelectedValue();
}
public void setSelectedValue(String name)
{
tablas.setSelectedValue(name, true);
}
}

The problem you are describing usually means that the object wasn't found in the list.
The setSelectedValue() method works doing calls to object.equals() (in your case String.equals()), so the probable cause is that the strings contained in aux are capitalized in a different way than the string you are trying to select.
For instace aux may contain the string "alumnos" instead of "Alumnos". There are two alternatives for this, if you don't care about capitalization (then change the string "Alumnos" to whatever is inside aux) if you do care about the capitalization and you still want to use strings, you could simple create a MyString class that extends String and overrides the equals method, something like:
public class MyString extends String {
#Override
public boolean equals(Object obj){
if (obj instanceof String){
String obj2 = (String)obj;
return this.equalsIgnoreCase(obj2);
}
return false;
}
}
Another alternative (perhaps a nicer one) is to create a wrapper object for your list.
public class MyWrapper {
private String payload;
public MyWrapper(String payload){
this.payload = payload;
}
#Override
public String toString(){
return payload;
}
#Override
public boolean equals(Object obj){
if (obj instanceof MyWrapper){
MyWrapper obj2 = (MyWrapper)obj;
return payload.equalsIgnoreCase(obj2.payload);
}
return false;
}
}

Related

Loading hashmap values in another method

I've a method called setupTroop that stores the data through hashmap. How do I go about loading this data in getTroopDetails, so whenever the key has been called, its value gets loaded.
So if the key IW1 gets called, the values 1, "Twisters", 200, 200 are outputted and if any other key gets called it gives the output "No such troop".
private void setupTroop()
{
HashMap<String, troop>Troop= new HashMap<String, troop>();
Troop.put("IW1", new troop(1, "Twisters", 200, 200));
}
public String getForceDetails(String ref)
{
return "\nNo such force";
}
public class troop{
int FleetRef;
String FullName;
int ActivationFee;
int BattleStrength;
public troop(int FRef, String FName, int AFee, int BStrength)
{
FleetRef = FRef;
FullName = FName;
ActivationFee = AFee;
BattleStrength = BStrength;
}
public int getFleetRef()
{
return FleetRef;
}
public String getFullName()
{
return FullName;
}
public int getActivationFee()
{
return ActivationFee;
}
public int BattleStrength()
{
return BattleStrength;
}
It's impossible to return a non string object on a String method. But there is a way of returning a troop if the "IW1" key is called.
The way of doing it is declaring the Troop HashMap outside of the setupTroop method, and then creating it inside the setupTroop method, like this:
HashMap<String, troop> Troop;
//Code you have
private void setupTroop() {
Troop = new HashMap<String, troop>();
Troop.put("IW1", new troop(1, "Twisters", 200, 200));
}
//Other code
public troop getForceDetails(String ref) {
if(ref.equals("IW1") {
return Troop.get(ref);
}
return null;
}
Then in whatever other method you have where you called the getForceDetails() method, you would have
if(getForceDetails("Some string") == null) {
doSomething;
}

Why does com.google.gson.Gson::toJson return an empty object?

A view model that I'm working on has a method like:
public String getModelJson() {
final ItemModel model = this.getModel();
if (model == null) {
return StringUtils.EMPTY;
}
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
return gson.toJson(model);
}
This method relies on com.google.gson.Gson::toJson to serialize a POJO model to a JSON string that can be used in my view. Here's the model code:
public final class ItemModel extends ContentFragmentModel {
#Expose
private String error;
#Expose
private String id;
#Expose
private String name;
public ItemModel(final ContentFragment fragment) {
super(fragment);
}
public String id() {
return this.id;
}
public String name() {
return this.name;
}
#Override
protected String getModelPath() {
return "/path/to/model";
}
}
When I call getModelJson from my view, the method always returns {}, even though I can prove that the model is being loaded correctly; if I rewrite the method like this:
public String getModelJson() {
final ItemModel model = this.getModel();
return model != null ? "{\"name\": \"" + model.getName() + "\"}";
}
...it returns the expected output: {"name": "item name"}, where item name is the name correctly loaded from the fragment.
How can I get the model to serialize correctly?
I realized the problem. Here's the code for the base model class:
public abstract class ContentFragmentModel {
protected String error;
private boolean isValid = false;
public ContentFragmentModel(#NotNull final ContentFragment fragment) {
final String className = this.getClass().getSimpleName();
if (fragment == null) {
this.error = "No content fragment passed to " + className + ".";
return;
}
final String fragmentModelPath = FragmentUtil.getFragmentModelPath(
fragment
);
if (!fragmentModelPath.equals(this.getModelPath())) {
this.error = "Invalid content fragment passed to " + className + ".";
return;
}
this.loadElements(fragment);
this.isValid = true;
}
public #NotNull String getError() {
return StringUtils.defaultIfBlank(this.error, StringUtils.EMPTY);
}
public boolean isValid() {
return this.isValid;
}
protected abstract String getModelPath();
}
Notice that the base model class AND the model class have a member called error. In the base class, this member is protected. In the extended class, it's private. This apparently works in Java - the member in the child class hides the parent member - but this weird usage of class inheritance seems to break com.google.gson.Gson::toJson. There is no mention of this in the docs for that method so I'm adding a post here to hopefully save some poor soul a couple hours if they run into the same issue I had.
The fix for me was just to remove the error member from the extending class. I found that it wasn't even really used for anything, so I just deleted it. If you are running into this with a member that can't be simply deleted, you might try renaming it so it doesn't collide with the member in the base class.

Removing duplicates when parsing Json in JAVA, Hashset not working

I've got a problem I am currently tring to parse a Json file and remove duplicate from it so i thought that i would store it in a Hashset of my Class that hold information but it doesnt remove duplicate.
Can you explain me if I did something wrong of if there is something that I don't understand?
here is a sample of my Code:
try {
FileReader f = new FileReader("E:\\JavaDev\\src\\main\\resources\\annonces.json");
JsonReader jsonReader = new JsonReader(f);
Gson gson = new Gson();
Appartement[] res2 = new Appartement[0];
res2 = gson.fromJson(jsonReader, res2.getClass());
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
System.out.println(test.size());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
My Appartment look like this:
(getter and setter are removed here to have smaller code)
public class Appartement {
private String id;
private Double surface;
private String marketingType;
private Integer roomCount;
private String propertyType;
private Boolean furnished;
private Boolean newBuild;
private String zipCode;
private Double price;
}
I tried converting my json directly in a Hashset but I've got an error: java.lang.OutOfMemoryError: Java heap space
HashSet<Appartement> mySet = gson.fromJson(jsonReader, HashSet.class);
I verified that there is duplicate in the Json file.
Would apreciate some help here.
You must override equals method of your Appartment class,
See here: Object equal method, if you don't override its default equal method, it actually compared the reference of the object,
public class Appartement {
private String id;
....
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Appartement)) return false;
return this.id.equals(((Appartement)obj.id));
}
#Override
public int hashCode() {
return 123123131311; //replace to your own hashcode.
}
}
Joshua, Effective Java
You must override hashCode() in every class that overrides equals().
Failure to do so will result in a violation of the general contract
for Object.hashCode(), which will prevent your class from functioning
properly in conjunction with all hash-based collections, including
HashMap, HashSet, and Hashtable.
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
You must make sure that Apartment's hashcode and equals method are overridden and you return true from equals method for same Appartement. (based on its properties) otherwise Objects.equals will be called
You need to override equals method (requiring appropriate equality checking) and hascode method in your Appartement.class
import java.util.*;
public class HelloWorld{
public static void main(String []args){
System.out.println("Hello World");
Appartement[] res2 = {(new HelloWorld()).new Appartement("1"), (new HelloWorld()).new Appartement("2"), (new HelloWorld()).new Appartement("3"),(new HelloWorld()).new Appartement("1") };
Set<Appartement> test = new HashSet<Appartement>(Arrays.asList(res2));
System.out.println(test.size());
}
public class Appartement {
private String id;
private Double surface;
private String marketingType;
private Integer roomCount;
private String propertyType;
private Boolean furnished;
private Boolean newBuild;
private String zipCode;
private Double price;
public Appartement(String id){
this.id=id;
}
#Override
public boolean equals (Object other)
{
if (!(other instanceof Appartement))
return false;
Appartement ob = (Appartement) other;
return this.id.equals(ob.id) ;
}
#Override
public int hashCode ()
{
return Arrays.hashCode(new String[]{id});
}
}
}

Detecting Class of an object implementing an interface

I'm writing a game, as part of this players should be able to click on various GUI items and see further details on a specific area of the GUI. I'm mangaing this through an interface Detailable which is implemented by suitable game obects and sends the appropriate information to the JPanel
There are also containers (all of which implement Detailable) that contain other (Detailable implementing) objects. The goal being it is possible to click on a container and, amongst its stats, see its contents which can then be in turn clicked on to see their stats, etc.
The problem I am having is in writing the addToContents(Detailable d) method of my containers. Each container as an ArrayList<String> of the "type" of container - wardrobe, bookcase, etc. I want to be able to add only certain classes to a given container - so a container with a type of "bookcase" will only accept objects of class Book or Curio for example.
What I currently have is:
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
But this feels like the wrong way of doing it. Is there a better way? Ideally, for sake of easy code, I'd have something like (pseudocode)
Constructor:
private ArrayList<Class> classesAccepted = <list of classes>
addToContents:
if (classesAccepted.contains(d.getClass()){
add the thingie to contents
return true
}
else{
return false;
}
but I can't seem to find a way of adding a list of classes to the constructor - of translating the ArrayList of class names to an ArrayList of references to the actual class.
Containers are currently read from a JSON so comprise two classes:
public class FurnitureType {
private String name;
private List<String> type;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
//plus getters for all the above
}
public class Furniture implements Detailable, ListSelectionListener{
private String name;
private List<String> types;
private int cost;
private String description;
private int comfortBonus;
private int capacity;
private ArrayList<Detailable> contents;
private transient DetailPanel dp = null;
public Furniture (FurnitureType type){
this.name=type.getName();
this.types = type.getType();
this.cost = type.getCost();
this.description = type.getDescription();
this.comfortBonus = type.getComfortBonus();
this.capacity = type.getCapacity();
this.contents = new ArrayList();
}
//appropriate getters
public boolean addToContents(Detailable d){
if(this.types.contains("bookcase") && d.getClass().getName().equals("Book")){
//do some stuff
//I know "Book" isn't the right syntax, this is just to demo
return true;
}
else if(this.types.contains("bookcase") && d.getClass().getName().equals("Curio")){
//other stuff
return true;
}
//etc
else{
return false;
}
}
#Override
public String toString(){
return description;
}
#Override
public Icon getBigPic() {
return null;
}
#Override
public JComponent getStats() {
Object [] objectContents = contents.toArray();
JList contentList = new JList(objectContents);
contentList.setPreferredSize(new Dimension (400, 300));
contentList.setFixedCellHeight(50);
contentList.addListSelectionListener(this);
contentList.setCellRenderer(new CustomCellRenderer());
//the CustomCellRenderer class simply makes long descriptions into multiline cells
return contentList;
}
#Override
public void addPanel(DetailPanel dp) {
this.dp = dp;
}
#Override
public void valueChanged(ListSelectionEvent lse) {
Detailable d = contents.get(lse.getFirstIndex());
dp.updatePanel(d);
}
You can actually use a Map as shown below:
private static Map<String, List<Class<? extends Detailable>>>
bookcaseContainer = new HashMap<>();
static {
//load the bookcaseContainer Map from properties/database
bookcaseContainer.put("bookcase", list1);
bookcaseContainer.put("wardrobe", list2);
}
if(bookcaseContainer.get("bookcase") != null &&
bookcaseContainer.get("bookcase").contains(d.getClass())) {
//do something here
} else if(bookcaseContainer.get("wardrobe") != null &&
bookcaseContainer.get("wardrobe").contains(d.getClass())) {
//do something here
}
If I understand your question correctly, you are looking for something like this
ArrayList <Class<? extends Detailable>> acceptedClasses = new ArrayList<>();
acceptedClasses.add(Bookcase.class);
acceptedClasses.add(OtherAcceptable.class);
and then do something akin to
boolean test =
acceptedClasses.stream().anyMatch(clazz -> aClass.isInstance(detailableInstance));
to check if the instance is of an acceptable type

How to change the html of a HTMLPanel

I want do declare a Subclass of an HTMLPanel.
In its constructor I want to give it a few paramters to construct the containing html.
Because I have to call the super-constructor as first statement, I have to change the html later in the constructor.
How can I do this?
public class MyHTMLPanel extends HTMLPanel
{
public MyHTMLPanel(String id, int anotherParameter)
{ super("");
String html=""
// ... some code th construct the html
//??? this.setHtml(html);
}
}
You can find below an example I used and worked well for me.
I don't remember why I don't sub-class HTMLPanel, whether a good reason or not.
You will notice a mechanism to randomize the html ids in case you include several objects of the same type in a single page.
public abstract class HtmlPanelBase extends Composite
{
private String _dynPostfix = "";
protected final String id(final String staticId) { return staticId + _dynPostfix; }
private final String wrapId(final String id) { return "id=\"" + id + "\""; }
private final String wrapDynId(final String refId) { return wrapId(id(refId)); }
private String _htmlAsText = null;
public String getHtmlAsText() { return _htmlAsText; }
abstract protected String htmlPanelBundleHtmlText();
abstract protected List<String> idList();
protected HTMLPanel _holder = null;
private HTMLPanel createHtmlPanel(final boolean defineGloballyUniqueIds)
{
// Referent HTML panel text containing the reference id's.
_htmlAsText = htmlPanelBundleHtmlText();
if (defineGloballyUniqueIds)
{
// List of id's in the HTML Panel reference page to replace with dynamic/unique id's.
final List<String> refIdList = idList();
// Replace the reference id's with dynamic/unique id's.
for (String refId : refIdList)
_htmlAsText = _htmlAsText.replace(wrapId(refId), wrapDynId(refId));
}
// Return the HTMLPanel containing the globally unique id's.
return new HTMLPanel(_htmlAsText);
}
public HtmlPanelBase(final boolean defineGloballyUniqueIds)
{
setup(defineGloballyUniqueIds);
initWidget(_holder);
}
private void setup(final boolean defineGloballyUniqueIds)
{
if (defineGloballyUniqueIds)
_dynPostfix = "_" + UUID.uuid().replace("-", "_");
_holder = createHtmlPanel(defineGloballyUniqueIds);
}
}
And now how you could sub-class from the above base:
public class HtmlPanelTemplate extends HtmlPanelBase
{
private final static boolean _defineGloballyUniqueIds = false;
private final static int _numIdCapacity = 40;
public HtmlPanelTemplate()
{
super(_defineGloballyUniqueIds);
setup();
}
#Override
protected String htmlPanelBundleHtmlText()
{
return YourClientBundle.INSTANCE.getYourFileHtml().getText();
}
#Override
protected List<String> idList()
{
final List<String> idList = new ArrayList<String>(_numIdCapacity);
return idList;
}
private void setup()
{
}
}
You don't need to subclass HTMLPanel. You can create a simple Composite widget:
public class myPanel extends Composite {
private HTMLPanel panel = new HTMLPanel();
public myPanel(String id, int anotherParameter) {
// set HTML to panel based on your parameters
initWidget(panel);
}
}
htmlPanel.getElement().setInnerHTML(...)
Don't know whether this works in derived class' constructor. But setting up a class for specific content text isn't really a good solution.

Categories

Resources