Morphia arrays and CRUD example

This is an example for future reference and I'm not going to comment futher on it than what's already in the comments.

Location.java:
01.package experiment.morphia;
02. 
03.import org.bson.types.ObjectId;
04. 
05.import com.google.code.morphia.annotations.Entity;
06.import com.google.code.morphia.annotations.Id;
07. 
08.@Entity
09.public class Location
10.{
11.    @Id
12.    private ObjectId    id;
13. 
14.    private Integer stars;
15.    private String    street;
16.    private String    city;
17.    private String    state;
18.    private String    zipcode;
19.    private String    country;
20. 
21.    public Location() {}
22. 
23.    public Location( Integer stars, String street, String city, String state, String zipcode, String county )
24.    {
25.        this.stars   = stars;
26.        this.street  = street;
27.        this.city    = city;
28.        this.state   = state;
29.        this.zipcode = zipcode;
30.        this.country = county;
31.    }
32. 
33.    public ObjectId getId() { return this.id; }
34.    public void setId( ObjectId id ) { this.id = id; }
35. 
36.    public Integer getStars() { return this.stars; }
37.    public void setStars( Integer stars ) { this.stars = stars; }
38.    public String getStreet() { return this.street; }
39.    public void setStreet( String street ) { this.street = street; }
40.    public String getCity() { return this.city; }
41.    public void setCity( String city ) { this.city = city; }
42.    public String getState() { return this.state; }
43.    public void setState( String state ) { this.state = state; }
44.    public String getZipcode() { return this.zipcode; }
45.    public void setZipcode( String zipcode ) { this.zipcode = zipcode; }
46.    public String getCountry() { return this.country; }
47.    public void setCountry( String country ) { this.country = country; }
48. 
49.    public String toString()
50.    {
51.        String string = "";
52. 
53.        if( this.id != null )
54.            string = "[" + this.id + "] ";
55. 
56.        if( this.stars != 1 )
57.            string += this.stars + " stars  ";
58.        else
59.            string += this.stars + " star  ";
60. 
61.        string += this.street + "  "
62.                + this.city + " ";
63. 
64.        if( this.state != null )
65.            string += this.state + "  ";
66. 
67.        string += this.country + "  "
68.                + this.zipcode;
69. 
70.        return string;
71.    }
72.}
Hotel.java:
01.package experiment.morphia;
02. 
03.import java.util.ArrayList;
04. 
05.import org.bson.types.ObjectId;
06. 
07.import com.google.code.morphia.annotations.Embedded;
08.import com.google.code.morphia.annotations.Entity;
09.import com.google.code.morphia.annotations.Id;
10. 
11.@Entity( noClassnameStored=true )
12.public class Hotel
13.{
14.    @Id
15.    private ObjectId    id;
16. 
17.    private String        name;
18.    private int            stars;
19. 
20.    public Hotel() {}
21. 
22.    public Hotel( String name, int stars )
23.    {
24.        this.name = name;
25.        this.stars = stars;
26.    }
27. 
28.    @Embedded
29.    private ArrayList< Location >    locations;
30. 
31.    public ObjectId getId() { return id; }
32.    public void setId( ObjectId id ) { this.id = id; }
33. 
34.    public String getName() { return name; }
35.    public void setName( String name ) { this.name = name; }
36. 
37.    public int getStars() { return stars; }
38.    public void setStars( int stars ) { this.stars = stars; }
39. 
40.    public ArrayList< Location > getLocations() { return locations; }
41.    public void setLocations( ArrayList< Location > locations ) { this.locations = locations; }
42. 
43.    public String toString()
44.    {
45.        String string = this.name + ", " + this.stars + " stars " + "[" + this.id + "]\n";
46. 
47.        for( Location location : this.locations )
48.            string += "    " + location.toString() + "\n";
49. 
50.        return string;
51.    }
52.}
HotelDao.java:
01.package experiment.morphia;
02. 
03.import java.util.List;
04. 
05.import util.Implementor;
06. 
07.import com.google.code.morphia.Datastore;
08.import com.google.code.morphia.dao.BasicDAO;
09. 
10./**
11. * Do database stuff here...
12. */
13.@Implementor( HotelDao.class )
14.public class HotelDao extends BasicDAO< Hotel, String >
15.{
16.    /* The Datastore is a wrapper around the MongoDB Java driver and is used to manage
17.     * entities in MongoDB.
18.     */
19.    Datastore datastore; // inject this manually for now...
20. 
21.    public HotelDao()
22.    {
23.        super( HotelTest.getMongo(), HotelTest.getMorphia(), "hotels" );
24.        this.datastore = HotelTest.getDatastore();
25.    }
26. 
27.    public Hotel create( Hotel hotel )
28.    {
29.        this.datastore.save( hotel );
30.        return hotel;
31.    }
32. 
33.    public List< Hotel > read()
34.    {
35.        return this.datastore.find( Hotel.class ).asList();
36.    }
37. 
38.    public List< Hotel > read( String query, String value )
39.    {
40.        if( query == null && value == null )
41.            return this.datastore.find( Hotel.class ).asList();
42. 
43.        return this.datastore.find( Hotel.class, query, value ).asList();
44.    }
45. 
46.    public List< Hotel > read( String query, Integer value )
47.    {
48.        if( query == null && value == null )
49.            return this.datastore.find( Hotel.class ).asList();
50. 
51.        return this.datastore.find( Hotel.class, query, value ).asList();
52.    }
53. 
54.    public void update( Hotel hotel )
55.    {
56.        this.datastore.merge( hotel );
57.    }
58. 
59.    public void remove( Hotel hotel )
60.    {
61.        this.datastore.delete( hotel );
62.    }
63.}
HotelManager.java:
01.package experiment.morphia;
02. 
03.import java.util.List;
04. 
05.import util.Implementor;
06.import util.ServiceLocator;
07. 
08./**
09. * Do business logic here...
10. */
11.@Implementor( HotelManager.class )
12.public class HotelManager
13.{
14.    private HotelDao hotelDao = ServiceLocator.get( HotelDao.class );
15. 
16.    public Hotel create( Hotel hotel )
17.    {
18.        return hotelDao.create( hotel );
19.    }
20. 
21.    public List< Hotel > read()
22.    {
23.        return hotelDao.read();
24.    }
25. 
26.    public List< Hotel > read( String query, String value )
27.    {
28.        return hotelDao.read( query, value );
29.    }
30. 
31.    public List< Hotel > read( String query, Integer value )
32.    {
33.        return hotelDao.read( query, value );
34.    }
35. 
36.    public void update( Hotel hotel )
37.    {
38.        hotelDao.update( hotel );
39.    }
40. 
41.    public void delete( Hotel hotel )
42.    {
43.        hotelDao.remove( hotel );
44.    }
45.}
HotelService.java:
01.package experiment.morphia;
02. 
03.import java.util.List;
04. 
05.import util.ServiceLocator;
06. 
07./**
08. * Do web service here (except that this isn't a web service, but a squirrel cage)...
09. */
10.public class HotelService
11.{
12.    private HotelManager hotelManager = ServiceLocator.get( HotelManager.class );
13. 
14.    public Hotel create( Hotel hotel )
15.    {
16.        return this.hotelManager.create( hotel );
17.    }
18. 
19.    public List< Hotel > read()
20.    {
21.        return this.hotelManager.read();
22.    }
23. 
24.    public List< Hotel > read( String query, String value )
25.    {
26.        return this.hotelManager.read( query, value );
27.    }
28. 
29.    public List< Hotel > read( String query, Integer value )
30.    {
31.        return this.hotelManager.read( query, value );
32.    }
33. 
34.    public void update( Hotel hotel )
35.    {
36.        this.hotelManager.update( hotel );
37.    }
38. 
39.    public void delete( Hotel hotel )
40.    {
41.        this.hotelManager.delete( hotel );
42.    }
43.}
HotelTest.java:
001.package experiment.morphia;
002. 
003.import java.net.UnknownHostException;
004.import java.util.ArrayList;
005.import java.util.List;
006.import java.util.Random;
007. 
008.import org.apache.log4j.Logger;
009. 
010.import util.ServiceLocator;
011. 
012.import com.google.code.morphia.Datastore;
013.import com.google.code.morphia.Morphia;
014.import com.mongodb.BasicDBObject;
015.import com.mongodb.DB;
016.import com.mongodb.DBCollection;
017.import com.mongodb.Mongo;
018.import com.mongodb.MongoException;
019. 
020.@SuppressWarnings( "unused" )
021.public class HotelTest
022.{
023.    public static Logger log = Logger.getLogger( HotelTest.class );
024. 
025.    private static Mongo        mongodb;
026.    private static DB           database;
027.    private static Morphia      morphia;
028.    private static Datastore    datastore;
029. 
030.    private static final String DATABASE_NAME   = "hotels";
031.    private static final String HOTEL_NAME      = "Hotel Hyatt";
032.    private static final String COLLECTION_NAME = Hotel.class.getSimpleName();
033. 
034.    public static Mongo getMongo() { return mongodb; }
035.    public static Morphia getMorphia() { return morphia; }
036.    public static Datastore getDatastore() { return datastore; }
037. 
038.    /**
039.     * Initialize MongoDB and Morphia for our purposes.
040.     */
041.    private static void initializeMongoAndMorphia()
042.    {
043.        try
044.        {
045.            mongodb = new Mongo( "localhost", 27017 );
046.        }
047.        catch( UnknownHostException e )
048.        {
049.            log.error( "MongoDB host not found" );
050.        }
051.        catch( MongoException e )
052.        {
053.            log.error( "Error attempting MongoDB connection for hotels", e );
054.        }
055. 
056.        database  = mongodb.getDB( DATABASE_NAME );
057.        morphia   = new Morphia();
058.        datastore = morphia.createDatastore( mongodb, DATABASE_NAME );
059. 
060.        database.dropDatabase();    // drop any fodder left in from last time...
061.        morphia.map( Hotel.class ).map( Location.class );
062.    }
063. 
064.    /**
065.     * Clean up the document we put in here last time (works assuming the hotel name hasn't
066.     * changed) so that we start fresh.
067.     *
068.     * @param key field name ("name").
069.     * @param value hotel name.
070.     */
071.    private static void deleteDocumentFromCollection( String key, String value )
072.    {
073.        DBCollection collection = database.getCollection( COLLECTION_NAME );
074. 
075.        try
076.        {
077.            BasicDBObject dbo = new BasicDBObject();
078. 
079.            dbo.append( key, value );
080.            collection.remove( dbo );
081.        }
082.        catch( MongoException e )
083.        {
084.            log.debug( "Ignored: " + e.getMessage() );
085.        }
086.    }
087. 
088.    public static void main( String[] args )
089.    {
090.        initializeMongoAndMorphia();
091. 
092.        HotelService service = new HotelService();
093. 
094.        // CREATE
095. 
096.        /* Create a random number of hotel chains and put them into the database.
097.         */
098.        Long   milliseconds = System.currentTimeMillis();
099.        Random generator    = new Random( milliseconds );
100.        int    hotelsCount  = HotelFodder.getHotelCount();
101. 
102.        // always ensure we've got at least one hotel chain...
103.        int which = generator.nextInt( hotelsCount );
104. 
105.        if( which == 0 )
106.            which = 1;
107. 
108.        if( which == 1 )
109.            System.out.println( "Creating a hotel chain..." );
110.        else
111.            System.out.println( "Creating " + which + " hotel chains..." );
112. 
113.        while( which > 0 )
114.        {
115.            Hotel h = service.create( HotelFodder.newHotel() );
116.            which--;
117.        }
118. 
119.        /* If I move the stars to the individual locations, I query this way:
120.         * > db.Hotel.find( { "locations" : { $elemMatch : { "stars" : { $gt : 2 } } } } ).count();
121.         * However, this still gives me back the whole Hotel document including the lesser-star
122.         * hotel locations.
123.         *
124.         * This came up as I was assigning stars to locations instead of hotel chains. I stopped
125.         * short of extending this change to what's going on here since it's isn't relevant and I
126.         * don't want to continue to play with it.
127.         */
128. 
129.        // READ
130.        List< Hotel > fourStarChains = service.read( "stars >", 2 );
131. 
132.        System.out.println( "Looking for 3-star or better hotels..." );
133. 
134.        Hotel h_c = null;
135. 
136.        int count = 0;
137. 
138.        for( Hotel hc : fourStarChains )
139.        {
140.            System.out.println( hc );
141.            count++;
142.        }
143. 
144.        if( count == 0 )
145.            System.out.println( "(There were no 3-star or better hotels.)" );
146.    }
147.}
HotelTuple.java:
01.package experiment.morphia;
02. 
03.public class HotelTuple
04.{
05.    String hotelName;
06.    Integer stars;
07. 
08.    public HotelTuple( String name, Integer stars )
09.    {
10.        this.hotelName = name;
11.        this.stars = stars;
12.    }
13.}
HotelFodder.java:
001.package experiment.morphia;
002. 
003.import java.util.ArrayList;
004.import java.util.Random;
005. 
006.public class HotelFodder
007.{
008.    private static boolean                 once = false;
009.    private static Random                  generator1;
010.    private static Random                  generator2;
011.    private static Random                  generator3;
012.    private static ArrayList< Location >   locations;
013.    private static ArrayList< HotelTuple > hotelNamesAndStars;
014. 
015.    private static void initializeAddresses()
016.    {
017.        locations = new ArrayList< Location >();
018. 
019.        locations.add( new Location( 2, "3222 South 525 West", "Bountiful", "UT", "84101", "US" ) );
020.        locations.add( new Location( 2, "59, rue Albert Premier", "Bezons", null, "95057", "FR" ) );
021.        locations.add( new Location( 4, "Miquelallee Straß, 23", "Frankfurt", null, "65936", "DE" ) );
022.        locations.add( new Location( 1, "1313 Mockingbird Lane", "Mockingbird Heights", "CA", "06660", "US" ) );
023.        locations.add( new Location( 5, "12345 Bedford Drive", "Beverly Hills", "CA", "90210", "US" ) );
024.        locations.add( new Location( 4, "1778 Oregon Avenue", "Provo", "UT", "84606", "US" ) );
025.        locations.add( new Location( 4, "23, rue du Puits", "Pagny-la-Blanche-Côte", null, "55010", "FR" ) );
026.        locations.add( new Location( 4, "48 Cicada Drive", "Boise", "ID", "83702", "US" ) );
027.        locations.add( new Location( 5, "5, Boulevard des Capucines", "Paris", null, "75008", "FR" ) );
028.    }
029. 
030.    private static void initializeHotelNamesAndStars()
031.    {
032.        hotelNamesAndStars = new ArrayList< HotelTuple >();
033. 
034.        hotelNamesAndStars.add( new HotelTuple( "Hyatt Hotel",        generator3.nextInt( 5 ) + 1 ) );
035.        hotelNamesAndStars.add( new HotelTuple( "Bayside Arms",       generator3.nextInt( 5 ) + 1 ) );
036.        hotelNamesAndStars.add( new HotelTuple( "Hotel California",   generator3.nextInt( 5 ) + 1 ) );
037.        hotelNamesAndStars.add( new HotelTuple( "Bates Motel",        0 ) );
038.        hotelNamesAndStars.add( new HotelTuple( "Purple Hives",       generator3.nextInt( 5 ) + 1 ) );
039.        hotelNamesAndStars.add( new HotelTuple( "Sofitel",            generator3.nextInt( 5 ) + 1 ) );
040.        hotelNamesAndStars.add( new HotelTuple( "Novotel",            generator3.nextInt( 5 ) + 1 ) );
041.        hotelNamesAndStars.add( new HotelTuple( "Marriott Courtyard", generator3.nextInt( 5 ) + 1 ) );
042.        hotelNamesAndStars.add( new HotelTuple( "Holiday Inn",        generator3.nextInt( 5 ) + 1 ) );
043.        hotelNamesAndStars.add( new HotelTuple( "Embassey Suites",    generator3.nextInt( 5 ) + 1 ) );
044.    }
045. 
046.    public static void initializeFodder()
047.    {
048.        Long milliseconds = System.currentTimeMillis();
049. 
050.        if( once )
051.            return;
052. 
053.        generator1 = new Random( milliseconds );
054.        generator2 = new Random( milliseconds + 89 );
055.        generator3 = new Random( milliseconds + 76 );
056. 
057.        initializeAddresses();
058.        initializeHotelNamesAndStars();
059.        once = true;
060.    }
061. 
062.    public static int getLocationCount()
063.    {
064.        initializeFodder();
065. 
066.        return locations.size();
067.    }
068. 
069.    public static int getHotelCount()
070.    {
071.        initializeFodder();
072. 
073.        return hotelNamesAndStars.size();
074.    }
075. 
076.    /**
077.     * Generate a new hotel chain with a random name, stars and set of locations.
078.     *
079.     * @return one new Hotel chain.
080.     */
081.    public static Hotel newHotel()
082.    {
083.        initializeFodder();
084. 
085.        int locationCount = getLocationCount();
086.        int hotelCount    = getHotelCount();
087. 
088.        HotelTuple tuple = hotelNamesAndStars.get( generator1.nextInt( hotelCount ) );
089.        Hotel      hotel = new Hotel( tuple.hotelName, tuple.stars );
090. 
091.        ArrayList< Location > as = new ArrayList< Location >();
092. 
093.        // always ensure we've got at least one location in a hotel chain...
094.        int howMany = generator2.nextInt( locationCount );
095. 
096.        if( howMany == 0 )
097.            howMany = 1;
098. 
099.        int next = generator3.nextInt( locationCount );
100. 
101.        while( howMany > 0 )
102.        {
103.            if( next < 0 )
104.                next = locationCount - 1;
105. 
106.            Location location = locations.get( next );
107.            as.add( location );
108.            howMany--;
109.            next--;
110.        }
111. 
112.        hotel.setLocations( as );
113. 
114.        return hotel;
115.    }
116. 
117.    public static void main( String[] args )
118.    {
119.        Hotel hotel = newHotel();
120.        System.out.println( hotel.toString() );
121.    }
122.}