import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import jdbm.InverseHashView;
import jdbm.PrimaryStoreMap;
import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.SecondaryKeyExtractor;
import jdbm.SecondaryTreeMap;
import jdbm.Serializer;
import jdbm.SerializerInput;
import jdbm.SerializerOutput;
import jdbm.helper.Serialization;
/**
* Demonstrates more advanced usage of JDBM:
* Secondary maps, 1:N relations.
*
* @author Jan Kotek
*
*/
public class Persons2 {
static class Person implements Serializable{
/** field used for person identification (primary key)**/
String name;
/** persisted with Person (embedded field in JPA terms) **/
Address adress;
/** N:1 relation */
Person father;
/** constructor, getters and setters are excluded for simplicity */
public Person(String name, Address adress,Person father) {
super();
this.name = name;
this.adress = adress;
this.father = father;
}
public String toString(){
return "Person["+name+"]";
}
public int hashCode() {
return name == null? 0 : name.hashCode();
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || !(obj instanceof Person))
return false;
Person other = (Person) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
static class Address implements Serializable{
String streetName;
String town;
String country;
public Address(String streetName, String town, String country) {
super();
this.streetName = streetName;
this.town = town;
this.country = country;
}
}
/** dao object which handles Person persistence */
static class PersonDao implements Serializer<Person>{
/**
* This is map in which persons are inserted in.
* Key is number assigned by store (recordId).
* You should prefer recordId as primary index, it is more flexible.
*/
PrimaryStoreMap<Long,Person> persons;
/** Inverse view on person, it helps to find recordId which belongs to person */
InverseHashView< Long, Person> personsInverse;
/**
* Secondary view on persons, which identifies person by name.
* This map is readonly, it is autoupdated by JDBM as primary map changes.
* Key is name, value is recordId ( key from primary map),
* third parameter is Person (value from primary map)
*/
SecondaryTreeMap<String, Long, Person> personsByName;
/**
* Secondary view on persons, which identifies person its town
* This map is readonly, it is autoupdated by JDBM as primary map changes.
* Key is town name extracted from primary table,
* value is recordId ( key from primary map),
* third parameter is town from (value from primary map)
*/
SecondaryTreeMap<String, Long, Person> personsByTown;
public PersonDao(RecordManager recman) {
persons = recman.storeMap("persons",this);
personsInverse = persons.inverseHashView("personsInverse");
personsByName = persons.secondaryTreeMap("personsByName",
new SecondaryKeyExtractor<String, Long, Person>() {
public String extractSecondaryKey(Long key, Person value) {
return value.name;
}});
personsByTown = persons.secondaryTreeMap("personsByTown",
new SecondaryKeyExtractor<String, Long, Person>() {
public String extractSecondaryKey(Long key, Person value) {
if(value.adress == null)
return null;
return value.adress.town;
}});
}
public Person personByRecordId(Long recid){
return persons.get(recid);
}
public Person personByName(String name){
if(!personsByName.containsKey(name))
return null;
Iterator<Long> iter = personsByName.get(name).iterator();
if(iter.hasNext())
return personsByName.getPrimaryValue(iter.next());
else
return null;
}
public Iterable<Person> personsByTown(String name){
List<Person> ret = new ArrayList<Person>();
for(Long l: personsByTown.get(name)){
ret.add(personsByTown.getPrimaryValue(l));
}
return ret;
}
public void insertPerson(Person person){
Long recid = personsInverse.findKeyForValue(person);
if(recid == null)
persons.putValue(person);
else
persons.put(recid, person);
}
public Person deserialize(SerializerInput in) throws IOException, ClassNotFoundException {
String name = in.readObject();
Address address = in.readObject();
Person father = persons.get(in.readObject());
Person p = new Person(name,address,father);
return p;
}
public void serialize(SerializerOutput out, Person obj)
throws IOException {
out.writeObject(obj.name);
out.writeObject(obj.adress);
out.writeObject(findOrPersistPerson(obj.father));
}
protected Long findOrPersistPerson(Person person){
if(person == null)
return null;
Long recid = personsInverse.findKeyForValue(person);
if(recid == null)
recid = persons.putValue(person);
return recid;
}
}
public static void main(String[] args) throws IOException {
//init Record Manager and dao
RecordManager recman = RecordManagerFactory.createRecordManager("persons2");
PersonDao dao = new PersonDao(recman);
//create a few persons
Person patrick = new Person("Patrick Moore",
new Address("First street", "Athlone","Ireland"),
null);
Person jack = new Person("Jack Moore",
new Address("First street", "Athlone","Ireland"),
patrick);
Person paul = new Person("Paul Moore",
new Address("Shop street", "Galway","Ireland"),
patrick);
//now store all this stuff
dao.insertPerson(jack);
dao.insertPerson(patrick);
dao.insertPerson(paul);
System.out.println("Number of persons: "+dao.persons.size());
System.out.println("Persons with name Patrick Moore: "+dao.personByName("Patrick Moore"));
System.out.println("Persons living in Galway: "+dao.personsByTown("Galway"));
System.out.println("Father of Paul Moore: "+dao.personByName("Paul Moore").father);
}
}