001package de.deepamehta.geomaps.model;
002
003import de.deepamehta.core.JSONEnabled;
004import de.deepamehta.core.RelatedTopic;
005import de.deepamehta.core.Topic;
006import de.deepamehta.core.model.TopicModel;
007import de.deepamehta.core.service.CoreService;
008import de.deepamehta.core.util.DeepaMehtaUtils;
009
010import org.codehaus.jettison.json.JSONObject;
011
012import java.util.HashMap;
013import java.util.Iterator;
014import java.util.List;
015import java.util.Map;
016import java.util.logging.Logger;
017
018
019
020/**
021 * A geomap model: a collection of Geo Coordinate topic models.
022 * <p>
023 * Features:
024 * - load from DB (by constructor).
025 * - Serialization to JSON.
026 */
027public class Geomap implements Iterable<TopicModel>, JSONEnabled {
028
029    // ---------------------------------------------------------------------------------------------- Instance Variables
030
031    protected Topic geomapTopic;
032    protected Map<Long, TopicModel> geoCoords = new HashMap();
033
034    protected CoreService dm4;
035
036    private Logger logger = Logger.getLogger(getClass().getName());
037
038    // ---------------------------------------------------------------------------------------------------- Constructors
039
040    /**
041     * Loads a topicmap from the DB.
042     */
043    public Geomap(long geomapId, CoreService dm4) {
044        logger.info("Loading geomap " + geomapId);
045        // Note: a Geomap is not a DeepaMehtaObject. So the JerseyResponseFilter's automatic
046        // child topic loading is not applied. We must load the child topics manually here.
047        this.geomapTopic = dm4.getTopic(geomapId).loadChildTopics();
048        this.dm4 = dm4;
049        //
050        fetchGeoCoordinates();
051    }
052
053    // -------------------------------------------------------------------------------------------------- Public Methods
054
055    public long getId() {
056        return geomapTopic.getId();
057    }
058
059    // ### TODO: needed?
060    public boolean containsTopic(long geoCoordId) {
061        return geoCoords.get(geoCoordId) != null;
062    }
063
064    // ---
065
066    @Override
067    public JSONObject toJSON() {
068        try {
069            return new JSONObject()
070                .put("info", geomapTopic.toJSON())
071                .put("topics", DeepaMehtaUtils.toJSONArray(geoCoords.values()));
072        } catch (Exception e) {
073            throw new RuntimeException("Serialization failed (" + this + ")", e);
074        }
075    }
076
077    @Override
078    public Iterator<TopicModel> iterator() {
079        return geoCoords.values().iterator();
080    }
081
082    @Override
083    public String toString() {
084        return "geomap " + getId();
085    }
086
087    // ------------------------------------------------------------------------------------------------- Private Methods
088
089    private void fetchGeoCoordinates() {
090        for (Topic geoCoord : fetchGeoCoordinates(geomapTopic)) {
091            geoCoords.put(geoCoord.getId(), geoCoord.getModel());
092        }
093    }
094
095    private List<RelatedTopic> fetchGeoCoordinates(Topic geomapTopic) {
096        return DeepaMehtaUtils.loadChildTopics(geomapTopic.getRelatedTopics("dm4.geomaps.geotopic_mapcontext",
097            "dm4.core.default", "dm4.topicmaps.topicmap_topic", "dm4.geomaps.geo_coordinate"));
098    }
099}