Here is my dilemma:
I have a dto class for marshaling back and forth from/to XML.
Here is the trick: Because of the number of dto classes our project deals with that are collections with a plural outter tag, I decided to create a delegate collection that allows me to take one of these classes and effortlessly turn them into a Collection and get the convenience that comes with it (iteration, add, etc.).
In our project we have marshaling tests to flush out annotation errors and such.
Below is my trouble code.
Problem:
Depending on the marshaler, if I extend this QuickCollection I get the below error.
When the object is unmarshaled to xml using CXF as a response to a webservice request, it fails. Exact error:
com.sun.istack.SAXException2: unable to marshal type "java.lang.String" as an element because it is missing an #XmlRootElement annotation
When it's marshaled/unmarshaled with JAXB in test it's fine.
When This same QuickCollection is used to marshal in results from 3rd parties using spring RestOperations and works fine
the mind screw:
When I remove the inheritance and manage the collection as a private member it all just works!
This makes not a stitch of sense to me as I am literally returning the exact data type in both situations.
Below is all relevant code.
This is the Inherited delegate class.
public class QuickCollection<T> implements Collection<T> {
// to be set if needed after instantiation. To behave like a normal collection, we set it to something safe
protected Collection<T> delegate = Collections.emptySet();
public QuickCollection() {
}
public QuickCollection(Collection<T> delegate) {
this.delegate = delegate;
}
#Override
public int size() {
return delegate.size();
}
#Override
public boolean isEmpty() {
return delegate.isEmpty();
}
#Override
public boolean contains(Object o) {
return delegate.contains(o);
}
#Override
public Iterator<T> iterator() {
return delegate.iterator();
}
#Override
public Object[] toArray() {
return delegate.toArray();
}
#Override
public <T> T[] toArray(T[] a) {
return delegate.toArray(a);
}
#Override
public boolean add(T t) {
return delegate.add(t);
}
#Override
public boolean remove(Object o) {
return delegate.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return delegate.containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
return delegate.addAll(c);
}
#Override
public boolean removeAll(Collection<?> c) {
return delegate.removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return delegate.retainAll(c);
}
#Override
public void clear() {
delegate.clear();
}
#Override
public String toString() {
return "" + delegate.toString();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
QuickCollection that = (QuickCollection) o;
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
return true;
}
#Override
public int hashCode() {
return delegate != null ? delegate.hashCode() : 0;
}
}
Here is the child DTO class
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlType(name = "BuddyCodes")
#XmlRootElement(name = "BuddyCodes")
public class BuddyCodes extends QuickCollection<String> implements Xml {
private Long accountId;
private Date expirationDate;
public BuddyCodes() {
super.delegate = new HashSet<String>();
}
public BuddyCodes(Long accountId, Set<String> codes, Date expirationDate) {
super(codes);
this.accountId = accountId;
this.expirationDate = expirationDate;
super.delegate = new HashSet<String>();
}
public BuddyCodes(Long accountId, Date expirationDate) {
this.accountId = accountId;
this.expirationDate = expirationDate;
super.delegate = new HashSet<String>();
}
#Override
public String toXml() {
String retVal;
try {
retVal = StringUtils.toXml(this);
}
catch (JAXBException e) {
retVal = e.toString();
}
return retVal;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public Set<String> getCodes() {
return (Set<String>) super.delegate;
}
#XmlElement(name = "code")
public void setCodes(Set<String> codes) {
super.delegate = codes;
}
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BuddyCodes that = (BuddyCodes) o;
if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) return false;
if (delegate != null ? !super.delegate.equals(that.delegate) : that.delegate != null) return false;
if (expirationDate != null ? !expirationDate.equals(that.expirationDate) : that.expirationDate != null)
return false;
return true;
}
#Override
public int hashCode() {
int result = accountId != null ? accountId.hashCode() : 0;
result = 31 * result + (expirationDate != null ? expirationDate.hashCode() : 0);
result = 31 * result + (super.delegate != null ? super.delegate.hashCode() : 0);
return result;
}
#Override
public String toString() {
return "BuddyCodes{" +
"accountId=" + accountId +
"codes=" + super.delegate +
", expirationDate=" + expirationDate +
'}';
}
}
And it doesn't work. I get the error.
Now, here is the child class after removing the inheritance and it works!!!
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.*;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
/**
* #author christian.bongiorno
* Date: 10/3/11
* Time: 6:11 PM
*/
#XmlAccessorType(XmlAccessType.PROPERTY)
#XmlType(name = "BuddyCodes")
#XmlRootElement(name = "BuddyCodes")
public class BuddyCodes implements Xml {
private Long accountId;
private Date expirationDate;
private Set<String> delegate;
public BuddyCodes() {
delegate = new HashSet<String>();
}
public BuddyCodes(Long accountId, Set<String> codes, Date expirationDate) {
this.accountId = accountId;
this.expirationDate = expirationDate;
delegate = new HashSet<String>();
}
public BuddyCodes(Long accountId, Date expirationDate) {
this.accountId = accountId;
this.expirationDate = expirationDate;
delegate = new HashSet<String>();
}
#Override
public String toXml() {
String retVal;
try {
retVal = StringUtils.toXml(this);
}
catch (JAXBException e) {
retVal = e.toString();
}
return retVal;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public Set<String> getCodes() {
return delegate;
}
#XmlElement(name = "code")
public void setCodes(Set<String> codes) {
delegate = codes;
}
public Date getExpirationDate() {
return expirationDate;
}
public void setExpirationDate(Date expirationDate) {
this.expirationDate = expirationDate;
}
public boolean add(String s) {
return delegate.add(s);
}
public int size() {
return delegate.size();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BuddyCodes that = (BuddyCodes) o;
if (accountId != null ? !accountId.equals(that.accountId) : that.accountId != null) return false;
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null) return false;
if (expirationDate != null ? !expirationDate.equals(that.expirationDate) : that.expirationDate != null)
return false;
return true;
}
#Override
public int hashCode() {
int result = accountId != null ? accountId.hashCode() : 0;
result = 31 * result + (expirationDate != null ? expirationDate.hashCode() : 0);
result = 31 * result + (delegate != null ? delegate.hashCode() : 0);
return result;
}
}
Why does the inheritance matter at all???
I haven't figured this out but, I have another DTO in a similar layout (BuddyTypes BuddyType). BuddyType has 2 members: Long and String. Both are annoted as XmlElement. This one works just fine.
It seems the problem that the members of the set making up the delegate are not annotated in my problem case and I don't know how to annotate a parent member. As an inherited class, it wouldn't make sense to have some sort of default name/annotation. But, I tried this madness and the annotation is ignored -- I have seen parent member annotations ignored before so this isn't new.
I don't know if it's possible, but I need to annotate a parent member.
A bit out of the box: try Simple XML library instead of JAXB. My experience with it is the best.
Related
I want to store following data structure in a DB
private Map<String, Map<Long, SafeTimeAndReponse>> mapStringToMap;
I tried now several ways of implementations with several different error messages.
I tried it with a class which extends TreeMap, no success.
private HashMap<String, CopyExtrendsTreeMap<Long, SafeTimeAndReponse>> mapStringToMap;
I used Map and HashMap, no success.
private HashMap<String, TreeMap<Long, SafeTimeAndReponse>> mapStringToMap;
private Map<String, Map<Long, SafeTimeAndReponse>> mapStringToMap;
I changed the annotation in different ways and got always different error messages. So no matter what I did, it was wrong.
So instead of I give you now all attempts i tried, I copy my current classes and hope very much that someone can help.
The current Error with that is:
Caused by: org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.algotest.AlgoTest.exvDB.mapStringToMap
But as I said, I already got rid of it and just landed at others, so I don't even know if I am at the wrong or right way.
How you can help me:
Please just tell me how I can store that above mentioned data structure.
I use SpringBoot 1.5.4, Hibernate 5 and H2 DB
exvDB
#Entity
public class exvDB {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long exvDB_id;
#OneToMany(cascade = CascadeType.ALL)
private Map<String, Map<Long, SafeTimeAndReponse>> mapStringToMap;
public exvDB(Map<String, Map<Long, SafeTimeAndReponse>> mapStringToMap) {
this.mapStringToMap= mapStringToMap;
}
public exvDB() {
}
public Map<String, Map<Long, SafeTimeAndReponse>> getMapStringToMap()() {
return mapStringToMap;
}
public void setMapStringToMap(Map<String, Map<Long, SafeTimeAndReponse>> mapStringToMap) {
this.mapStringToMap= mapStringToMap;
}
public Long getExvDB_id() {
return exvDB_id;
}
public void setExvDB_id(Long exvDB_id) {
this.exvDB_id = exvDB_id;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
exvDB poloDB = (exvDB) o;
return exvDB_id != null ? exvDB_id.equals(poloDB.exvDB_id) : poloDB.exvDB_id == null;
}
#Override
public int hashCode() {
return exvDB_id != null ? exvDB_id.hashCode() : 0;
}
}
ExvDBRepo
#Repository
public interface ExvDBRepo extends CrudRepository<exvDB, Long> {
}
SafeTimeAndReponse
#Entity
public class SafeTimeAndReponse {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long safeTimeAndResponse_id;
private String firstResponse;
private String secondResponse;
private long timeEnd;
private long timePlus15;
private long timePlus30;
public SafeTimeAndReponse(String firstResponse, String secondResponse, long timeEnd, long timePlus15, long timePlus30) {
this.firstResponse = firstResponse;
this.secondResponse = secondResponse;
this.timeEnd = timeEnd;
this.timePlus15 = timePlus15;
this.timePlus30 = timePlus30;
}
public long getTimeEnd() {
return timeEnd;
}
public void setTimeEnd(long timeEnd) {
this.timeEnd = timeEnd;
}
public SafeTimeAndReponse() {
}
public String getFirstResponse() {
return firstResponse;
}
public void setFirstResponse(String firstResponse) {
this.firstResponse = firstResponse;
}
public long getTimePlus15() {
return timePlus15;
}
public void setTimePlus15(long timePlus15) {
this.timePlus15 = timePlus15;
}
public long getTimePlus30() {
return timePlus30;
}
public void setTimePlus30(long timePlus30) {
this.timePlus30 = timePlus30;
}
public Long getSafeTimeAndResponse_id() {
return safeTimeAndResponse_id;
}
public void setSafeTimeAndResponse_id(Long safeTimeAndResponse_id) {
this.safeTimeAndResponse_id = safeTimeAndResponse_id;
}
public String getSecondResponse() {
return secondResponse;
}
public void setSecondResponse(String secondResponse) {
this.secondResponse = secondResponse;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SafeTimeAndReponse that = (SafeTimeAndReponse) o;
if (timeEnd != that.timeEnd) return false;
if (timePlus15 != that.timePlus15) return false;
if (timePlus30 != that.timePlus30) return false;
if (safeTimeAndResponse_id != null ? !safeTimeAndResponse_id.equals(that.safeTimeAndResponse_id) : that.safeTimeAndResponse_id != null)
return false;
if (firstResponse != null ? !firstResponse.equals(that.firstResponse) : that.firstResponse != null)
return false;
return secondResponse != null ? secondResponse.equals(that.secondResponse) : that.secondResponse == null;
}
#Override
public int hashCode() {
int result = safeTimeAndResponse_id != null ? safeTimeAndResponse_id.hashCode() : 0;
result = 31 * result + (firstResponse != null ? firstResponse.hashCode() : 0);
result = 31 * result + (secondResponse != null ? secondResponse.hashCode() : 0);
result = 31 * result + (int) (timeEnd ^ (timeEnd >>> 32));
result = 31 * result + (int) (timePlus15 ^ (timePlus15 >>> 32));
result = 31 * result + (int) (timePlus30 ^ (timePlus30 >>> 32));
return result;
}
}
Thank you very much in advance!
Hello folks this may be dumb question but as a beginner am struggling with this how to group values based on id in list, Now let me clarify you briefly am having set of objects like this :
ID:1,UserID:330
ID:2,UserID:303
ID:3,UserID:090
ID:1,UserID:302
ID:2,UserID:306
How my list should look like is(Json Format):
[{"ID":1,"UserID":[330,302]},{"ID":2,"UserID":[303,306]},{"ID":3,"UserID":[090]}]
Now let me post what i have tried so far:
final List<Integer>list=new ArrayList<>();
final List<SpareReturnModel>lisobj=new ArrayList<>();
int duplicate=0;
for(int i=0;i<tView.getSelected().size();i++){
Object o= tView.getSelected().get(i).getValue();
SpareReturnModel asset=(SpareReturnModel) o;
int flag=asset.getFlag();
if(flag==2) {
int warehouseid = asset.getWareHouseID();
asset.setWareHouseID(warehouseid);
int partid = asset.getSerialNoID();
list.add(partid);
}
else {
Log.d("s","no value for header");
}
if(duplicate!=asset.getWareHouseID()){
asset.setParlist(list);
asset.setWareHouseID(asset.getWareHouseID());
lisobj.add(asset);
list.clear();
}
duplicate=asset.getWareHouseID();
}
Gson gson=new Gson();
//this will convert list to json
String value=gson.toJson(listobj);
SpareReturn Model Class:
public class SpareReturnModel {
private Integer SerialNoID;
private String SerialNumber;
private List<Integer>parlist;
public List<Integer> getParlist() {
return parlist;
}
public void setParlist(List<Integer> parlist) {
this.parlist = parlist;
}
public Integer getFlag() {
return flag;
}
public void setFlag(Integer flag) {
this.flag = flag;
}
private Integer flag;
public Integer getWareHouseID() {
return WareHouseID;
}
public void setWareHouseID(Integer wareHouseID) {
WareHouseID = wareHouseID;
}
private Integer WareHouseID;
public Integer getSerialNoID() {
return SerialNoID;
}
public void setSerialNoID(Integer serialNoID) {
SerialNoID = serialNoID;
}
public String getSerialNumber() {
return SerialNumber;
}
public void setSerialNumber(String serialNumber) {
SerialNumber = serialNumber;
}
}
Can someone let me know how to achieve this am struggling with this.
I simplify your class to make solution clearer:
public class SpareReturnModel implements Comparable<SpareReturnModel> {
private Integer id;
private String userId;
public SpareReturnModel(Integer id, String userId) {
this.id = id;
this.userId = userId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
#Override
public int compareTo(SpareReturnModel other) {
return this.getId().compareTo(other.getId());
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SpareReturnModel model = (SpareReturnModel) o;
if (id != null ? !id.equals(model.id) : model.id != null) return false;
return userId != null ? userId.equals(model.userId) : model.userId == null;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (userId != null ? userId.hashCode() : 0);
return result;
}
}
and add JsonSpareReturnModel
public class JsonSpareRuturnModel implements Comparable<JsonSpareRuturnModel> {
private final List<SpareReturnModel> modelList;
private final Integer id;
public JsonSpareRuturnModel(List<SpareReturnModel> modelList) {
this.modelList = modelList;
this.id = modelList.get(0).getId();
}
private final String toJson() {
return String.format("{\"ID\":%s,\"UserID\":%s}", id, formatUserIdList());
}
private String formatUserIdList() {
StringBuilder builder = new StringBuilder("[");
Iterator<SpareReturnModel> modelIterator = modelList.iterator();
while (modelIterator.hasNext()) {
builder.append(modelIterator.next().getUserId());
if (modelIterator.hasNext()) {
builder.append(",");
}
}
builder.append("]");
return builder.toString();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JsonSpareRuturnModel that = (JsonSpareRuturnModel) o;
return id != null ? id.equals(that.id) : that.id == null;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
#Override
public int compareTo(JsonSpareRuturnModel other) {
return this.id.compareTo(other.id);
}
#Override
public String toString() {
return toJson();
}
if you need to group by user id you need to sort your models according to id's
and place them to json format model:
public class Main {
public static void main(String[] args) {
List<SpareReturnModel> models = new ArrayList<>(Arrays.asList(
new SpareReturnModel(1, "330"),
new SpareReturnModel(2, "303"),
new SpareReturnModel(3, "090"),
new SpareReturnModel(1, "302"),
new SpareReturnModel(2, "306")
));
Map<Integer, List<SpareReturnModel>> groupById = new HashMap<>();
for (SpareReturnModel model : models) {
List<SpareReturnModel> listById = groupById.get(model.getId());
if (listById == null) {
groupById.put(model.getId(), new ArrayList<>(Arrays.asList(model)));
} else {
listById.add(model);
}
}
List<JsonSpareRuturnModel> jsonList = new ArrayList<>();
for (Map.Entry<Integer, List<SpareReturnModel>> pair : groupById.entrySet()) {
jsonList.add(new JsonSpareRuturnModel(pair.getValue()));
}
System.out.println(jsonList);
final String expected = "[{\"ID\":1,\"UserID\":[330,302]}, {\"ID\":2,\"UserID\":[303,306]}, {\"ID\":3,\"UserID\":[090]}]";
System.out.println(jsonList.toString().equals(expected));
}
}
I am trying to create a HashMap, that adds objects to a line, if they are not already present in this line. This is how I check it:
if (!waiting.containsKey(p)) {
waiting.put(current, p);
current++;
}
Where p is our object, which is stored with an Integer. However, when I run this code. It will store the same object several times under different integers, how can this be prevented?
thats because you call containsKey with the object and not the key:
parameter must be an Integer key
Integer lKey = 0;
if(!waiting.containsKey(lKey)){
waiting.put(current, p);
current++;
}
if your object has an identifier use this identifier for the map.
if(!waiting.containsKey(p.getId())){
waiting.put(p.getId(), p);
current++;
}
otherwise use containsValue():
if(!waiting.containsValue(p)){
waiting.put(current, p);
current++;
}
but then you have to overwrite the equals method.
If you want to use an object as a key, you can override the equals() and hashCode() methods to return and compare the id of the object.
Driver.java
import java.util.HashMap;
import java.util.Map;
public class Driver {
public static void main(String[] args) {
Map<MyObject, Integer> map = new HashMap<MyObject, Integer>();
map.put(new MyObject(1000L, "One"), 1);
map.put(new MyObject(1001L, "Two"), 2);
map.put(new MyObject(1002L, "Three"), 3);
Long id = 1001L;
System.out.println(contains(map, id)); // true
System.out.println(get(map, id)); // 2
}
public static <T, U> boolean contains(Map<T, U> map, T obj) {
return map.containsKey(obj);
}
public static boolean contains(Map<MyObject, Integer> map, Long id) {
return contains(map, new MyObject(id, ""));
}
public static <T, U> U get(Map<T, U> map, T obj) {
return map.get(obj);
}
public static Integer get(Map<MyObject, Integer> map, Long id) {
return get(map, new MyObject(id, ""));
}
}
MyObject.java
public class MyObject {
private Long id;
private String name;
protected Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
protected String getName() {
return name;
}
protected void setName(String name) {
this.name = name;
}
public MyObject(Long id, String name) {
this.id = id;
this.name = name;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
MyObject other = (MyObject) obj;
if (id == null) {
if (other.id != null) return false;
} else if (!id.equals(other.id)) return false;
return true;
}
#Override
public String toString() {
return "MyObject { id : " + id + ", name : " + name + "}";
}
}
I'm looking for a suggestion.
I have a Person class with String firstName and String lastName
When i'm tying to insert the list values with the same String like :
set.add(new Person("firstName","lastName"))
set.add(new Person("firstName","lastName"))
The set doesn`t filter the objects and they still getting in the set.
There is any suggestion to create set list without overriding the equales and hashcode functions?
Maybe with guava or some groovy list?
Thanks,
Or.
In Guava there's an Equivalence class designed to such things. Create your own Equivalence class like this one:
import com.google.common.base.Equivalence;
import com.google.common.base.Objects;
public class PersonEquivalence extends Equivalence<Person> {
#Override
protected boolean doEquivalent(Person p1, Person p2) {
return Objects.equal(p1.getFistName(), p2.getFistName())
&& Objects.equal(p1.getLastName(), p2.getLastName());
}
#Override
protected int doHash(Person person) {
return Objects.hashCode(person.getFistName(), person.getLastName());
}
}
And then this code
Set<Equivalence.Wrapper<Person>> set = Sets.newHashSet();
PersonEquivalence personEquivalence = new PersonEquivalence();
set.add(personEquivalence.wrap(new Person("Joe", "Doe")));
set.add(personEquivalence.wrap(new Person("Joe", "Doe")));
set.add(personEquivalence.wrap(new Person("Jane", "Doe")));
System.out.println(set);
prints
[PersonEquivalence#8813f2.wrap(Person{firstName=Jane, lastName=Doe}),
PersonEquivalence#8813f2.wrap(Person{firstName=Joe, lastName=Doe})]
Of course it's a bit verbose, but you can create ForwardingSet to automatically wrap and unwrap Persons for you.
You can create a TreeSet with your own Comparator.
Set<Person> set = new TreeSet<Person>(new Comparator<Person>() {
#Override
public int compare(Person p1, Person p2) {
// Your own compare logic
}
});
You can't, without violating the contract of Set. Either don't use a Set, or wrap the Person in another class that implements equals and hashcode based on the inner Person (see the other answer for a way to do this in Guava).
Here's a rough attempt at my map suggestion.
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class PeopleCarrier implements Iterable<Person>{
private Map<PersonKey, Person> storage = new HashMap<PersonKey, Person>();
public void add(Person p) {
PersonKey pk = new PersonKey(p);
storage.put(pk, p);
}
public boolean contains(Person p) {
return storage.containsKey(new PersonKey(p));
}
#Override
public Iterator<Person> iterator() {
return new Iterator<Person>() {
private Iterator<PersonKey> i = storage.keySet().iterator();
#Override
public void remove() {
throw new UnsupportedOperationException();
}
#Override
public Person next() {
return storage.get(i.next());
}
#Override
public boolean hasNext() {
return i.hasNext();
}
};
}
private class PersonKey {
private String firstname;
private String lastname;
public PersonKey(Person p) {
this.firstname = p.getFirstname();
this.lastname = p.getLastname();
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result
+ ((firstname == null) ? 0 : firstname.hashCode());
result = prime * result
+ ((lastname == null) ? 0 : lastname.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof PersonKey))
return false;
PersonKey other = (PersonKey) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (firstname == null) {
if (other.firstname != null)
return false;
} else if (!firstname.equals(other.firstname))
return false;
if (lastname == null) {
if (other.lastname != null)
return false;
} else if (!lastname.equals(other.lastname))
return false;
return true;
}
private PeopleCarrier getOuterType() {
return PeopleCarrier.this;
}
}
}
I have a DropDownChoice :
DropDownChoice timePeriod = new DropDownChoice("timePeriod", Arrays.asList(new TimePeriod(1, "Weekly"), new TimePeriod(2, "Bi-Weekly"), new TimePeriod(3, "Semi-Monthly"), new TimePeriod(4, "Monthly"), new TimePeriod(5, "Yearly")), new IChoiceRenderer() {
private static final long serialVersionUID = 10102L;
#Override
public String getIdValue(Object object, int index) {
return ((TimePeriod) object).getId() + "";
}
#Override
public Object getDisplayValue(Object object) {
return ((TimePeriod) object).getPeriodType();
}
});
timePeriod.setNullValid(false);
My question is:
How to set the selected index to 2 or any other?
How to remove first default blank option?
Thank you.
You should be able to set the selected index by using a PropertyModel instead of hard-coding the values of the dropdown. I can't test at the moment, but it would be something like
String timePeriodValue = "Bi-Weekly";
DropDownChoice timePeriod = new DropDownChoice("timePeriod",
new PropertyModel(this, "timePeriodValue"),
Arrays.asList(/* your options */),
new IChoiceRenderer() {
// ...
// Again, this is pseudocode only
As a bonus, the very act of setting a default value should eliminate the blank option problem.
DropDownChoice has a constructor which accepts the default value.
Or in your code you can add timePeriod.setModel(Model.of(new TimePeriod(2, "Bi-Weekly")))
I guess TimePeriod has proper #equals() and #hashCode() implementations.
About the blank option: see org.apache.wicket.markup.html.form.AbstractSingleSelectChoice.isNullValid()
Lord Torgamus and martin-g thank you both of you. I did a small test. And it is working perfectly. As Lord Torgamus indicated,
#SuppressWarnings({ "unchecked", "rawtypes", "serial" })
public class MyPage extends WebPage {
public MyPage() {
add(new MyForm("form"));
}
private class MyForm extends Form {
public MyForm(String id) {
super(id);
setOutputMarkupPlaceholderTag(true);
setModel(new Model(new FormModel()));
final DropDownChoice timePeriod = new DropDownChoice("timePeriod", new PropertyModel(getModel(), "timePeriod"), Arrays.asList(new TimePeriod(1, "Weekly"), new TimePeriod(2, "Bi-Weekly"), new TimePeriod(3, "Semi-Monthly"), new TimePeriod(4, "Monthly"), new TimePeriod(5, "Yearly")), new IChoiceRenderer() {
private static final long serialVersionUID = 10102L;
#Override
public String getIdValue(Object object, int index) {
return ((TimePeriod) object).getId() + "";
}
#Override
public Object getDisplayValue(Object object) {
return ((TimePeriod) object).getPeriodType();
}
});
timePeriod.setNullValid(false);
add(timePeriod);
timePeriod.setOutputMarkupPlaceholderTag(true);
timePeriod.add(new AjaxFormComponentUpdatingBehavior("onChange") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
MyForm form = (MyForm) timePeriod.getParent();
FormModel formModel = (FormModel) form.getModelObject();
formModel.setTimePeriod(new TimePeriod(4, "Monthly"));
form.setModel(new Model(formModel));
target.addComponent(form);
}
});
}
#Override
public void onSubmit() {
System.out.println(getModelObject());
}
}
private class FormModel implements Serializable {
private TimePeriod timePeriod = new TimePeriod(2, "Bi-Weekly");
public FormModel() {
}
public TimePeriod getTimePeriod() {
return timePeriod;
}
public void setTimePeriod(TimePeriod timePeriod) {
this.timePeriod = timePeriod;
}
#Override
public String toString() {
return "FormModel [timePeriod=" + timePeriod + "]";
}
}
private class TimePeriod implements Serializable {
private int id;
private String periodType;
public TimePeriod(int id, String periodType) {
super();
this.id = id;
this.periodType = periodType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPeriodType() {
return periodType;
}
public void setPeriodType(String periodType) {
this.periodType = periodType;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + id;
result = prime * result + ((periodType == null) ? 0 : periodType.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TimePeriod other = (TimePeriod) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (id != other.id)
return false;
if (periodType == null) {
if (other.periodType != null)
return false;
} else if (!periodType.equals(other.periodType))
return false;
return true;
}
private LoginPage getOuterType() {
return LoginPage.this;
}
#Override
public String toString() {
return "TimePeriod [id=" + id + ", periodType=" + periodType + "]";
}
}
}
The above code is provided for other users as it might be helpful and I wrote it for testing purpose so all the classes are written in one .java file although it is not advisable.
Thank you.