com.ifactory.service.weather.photo.PhotoService.java Source code

Java tutorial

Introduction

Here is the source code for com.ifactory.service.weather.photo.PhotoService.java

Source

/**
 * Copyright 2013 iFactory Lab Ltd.
 * 
 * Min Kim (minsikzzang@gmail.com)
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.ifactory.service.weather.photo;

import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.BasicDBList;
import com.mongodb.DBCursor;
import com.mongodb.CommandFailureException;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.lang.Math;
// import com.mongodb.ServerAddress;
// db.photos.ensureIndex({"geo.coordinates":"2d"})

class PhotoService {
    private static String PHOTO_COLLECTION = "photos";
    private static double UNAVAILABLE_LATITUDE = 91;
    private static double UNAVAILABLE_LONGITUDE = 181;
    private static double DEFAULT_RADIUS = 0.001;
    private static int DEFAULT_LIMIT = 10;
    private int weatherId;
    // To directly connect to a single MongoDB server (note that this will not 
    // auto-discover the primary even if it's a member of a replica set:
    /**
    MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
    // or, to connect to a replica set, with auto-discovery of the primary, supply a seed list of members
    MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017),
                                    new ServerAddress("localhost", 27018),
                                    new ServerAddress("localhost", 27019)));
                                    */
    private MongoClient mongoClient;
    private String dbName;
    private double lat = UNAVAILABLE_LATITUDE;
    private double lng = UNAVAILABLE_LONGITUDE;
    private double radius = DEFAULT_RADIUS;
    private boolean growable = false;
    private int limit = DEFAULT_LIMIT;
    private String origin = "http://api.ifactory-lab.com/assets/";

    public PhotoService(String host, int port, String dbName, String origin) throws UnknownHostException {
        this.weatherId = -1;
        this.mongoClient = new MongoClient(host, port);
        this.dbName = dbName;
        this.origin = origin;
    }

    public PhotoService geoCoord(double lat, double lng, double radius) {
        this.lat = lat;
        this.lng = lng;
        this.radius = radius;
        return this;
    }

    public PhotoService weatherId(int weatherId) {
        this.weatherId = weatherId;
        return this;
    }

    public PhotoService growable(boolean growable) {
        this.growable = growable;
        return this;
    }

    public PhotoService limit(int limit) {
        this.limit = limit;
        return this;
    }

    public String getOrigin() {
        return this.origin;
    }

    public void close() {
        this.mongoClient.close();
    }

    public boolean add(Photo photo) {
        DB db = mongoClient.getDB(this.dbName);
        DBCollection coll = db.getCollection(PHOTO_COLLECTION);

        BasicDBList geo = new BasicDBList();
        geo.add(photo.getLatitude());
        geo.add(photo.getLongitude());

        BasicDBObject query = new BasicDBObject("name", photo.getName()).append("day", photo.getDay())
                .append("weather", photo.getWeatherId()).append("timestamp", photo.getTimestamp())
                .append("geo", new BasicDBObject("type", "Point").append("coordinates", geo));

        try {
            coll.insert(query);
        } catch (MongoException e) {
            return false;
        }

        return true;
    }

    private BasicDBObject setGeoCoord(double lat, double lng, double radius) {
        BasicDBObject query = new BasicDBObject();
        BasicDBList geo = new BasicDBList();
        geo.add(lat);
        geo.add(lng);
        BasicDBList center = new BasicDBList();
        center.add(geo);
        center.add(radius);
        query.append("geo.coordinates", new BasicDBObject("$within", new BasicDBObject("$center", center)));
        return query;
    }

    public ArrayList<Photo> get() {
        DB db = mongoClient.getDB(this.dbName);
        DBCollection coll = db.getCollection(PHOTO_COLLECTION);
        BasicDBObject query = null;
        DBCursor cursor = null;
        ArrayList<Photo> photoList = new ArrayList();
        int weatherClassMin = -1;
        int weatherClassMax = -1;
        double rad = this.radius;

        while (true) {
            // If latitude and longitude were given, append geo search query
            if (this.lat != UNAVAILABLE_LATITUDE && this.lng != UNAVAILABLE_LONGITUDE) {
                query = setGeoCoord(this.lat, this.lng, rad);
            } else {
                query = new BasicDBObject();
            }

            // It the weather Id has given, append weather search query
            if (this.weatherId > 0) {
                if (weatherClassMin == -1 && weatherClassMax == -1) {
                    query.append("weather", this.weatherId);
                } else {
                    System.out.println("query with weatherClassMin(" + weatherClassMin + ") and weatherClassMax("
                            + weatherClassMax + ")");
                    query.append("weather",
                            new BasicDBObject("$gte", weatherClassMin).append("$lte", weatherClassMax));
                    System.out.println(query.toString());
                }
            }

            try {
                cursor = coll.find(query).limit(this.limit);
                if (cursor.count() > 0) {
                    System.out.println(
                            "photo found(lat: " + this.lat + ", lng: " + this.lng + ", radius: " + rad + ")");
                    break;
                } else if (this.growable == false || rad >= UNAVAILABLE_LATITUDE) {
                    if (rad >= UNAVAILABLE_LATITUDE) {
                        rad = this.radius / 2;
                        if (weatherClassMin == -1 && weatherClassMax == -1) {
                            // In this case, there is no proper photos by the given weather.
                            // Let's find any photos bound for same weather class.
                            weatherClassMin = ((int) this.weatherId / 100) * 100;
                            weatherClassMax = (((int) this.weatherId / 100) + 1) * 100;
                            System.out.println("weatherClassMin and weatherClassMax exist");
                        } else if (this.weatherId > 0) {
                            this.weatherId = 0;
                            System.out.println("weatherid goes to zero");
                            continue;
                        } else {
                            break;
                        }
                    } else {
                        break;
                    }
                }
            } catch (CommandFailureException e) {
                cursor = null;
                break;
            }

            rad = rad * 2;
        }

        try {
            while (cursor != null && cursor.hasNext()) {
                DBObject obj = cursor.next();
                Photo.Builder b = new Photo.Builder((String) obj.get("name"),
                        ((Number) obj.get("weather")).intValue());

                ArrayList<Double> coord = ((ArrayList<Double>) ((DBObject) obj.get("geo")).get("coordinates"));
                b.geoCoord(coord.get(0), coord.get(1)).day(((Boolean) obj.get("day")).booleanValue())
                        .timestamp(((Number) obj.get("timestamp")).longValue()).origin(this.origin);

                photoList.add(b.build());
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return photoList;
    }
}