<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package usda.weru.gis;

import org.locationtech.jts.geom.Geometry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.geotools.data.DataStore;
import org.geotools.data.DefaultRepository;
import org.geotools.feature.NameImpl;
import org.opengis.feature.Feature;
import org.opengis.feature.GeometryAttribute;
import org.opengis.feature.type.Name;

/**
 *
 * @author Joseph A. Levin &lt;joelevin@weru.ksu.edu&gt;
 */
public class GISData extends DefaultRepository {

    private static final Logger LOGGER = Logger.getLogger(GISData.class.getName());
    private static GISData c_instance;
    private List&lt;GISLookup&lt;?&gt;&gt; c_lookups;
    private Map&lt;Name, Integer&gt; c_sortLayers;

    private GISData() {
        //TODO: actually use a config file to load gis data
        
        try {
            MapData.prepareGISData(this);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "Unable to initilize GISData", e);
        }
    }

    public static synchronized GISData getInstance() {
        if (c_instance == null) {
            c_instance = new GISData();
        }

        return c_instance;
    }

    // if 'lookup.supports(c)' is true, then it is guaranteed that 'lookup' is of
    // type 'T'.
    @SuppressWarnings({"unchecked", "rawtypes"})
    public &lt;T&gt; GISLookup&lt;T&gt; getLookup(Class&lt;T&gt; c) {

        synchronized (c) {
            List&lt;GISLookup&lt;T&gt;&gt; temp = new LinkedList&lt;&gt;();

            for (GISLookup lookup : lookups()) {
                if (lookup.supports(c)) {
                    temp.add(lookup);
                }
            }

            if (temp.size() == 1) {
                return temp.get(0);
            } else if (temp.size() &gt; 1) {
                return new MergedGISLookup&lt;T&gt;(c, temp);
            } else {
                return null;
            }
        }
    }

    // ServiceLoader won't let us specify the type of a GISLookup
    @SuppressWarnings("rawtypes")
    private synchronized void initLookups() {
        c_lookups = new LinkedList&lt;GISLookup&lt;?&gt;&gt;();
        ServiceLoader&lt;GISLookup&gt; loader = ServiceLoader.load(GISLookup.class);
        Iterator&lt;GISLookup&gt; i = loader.iterator();
        while (i.hasNext()) {
            c_lookups.add(i.next());
        }
    }

    private synchronized List&lt;GISLookup&lt;?&gt;&gt; lookups() {
        if (c_lookups == null) {
            initLookups();
        }
        return c_lookups;
    }

    @Override
    public Set&lt;Name&gt; getNames() {
        Set&lt;Name&gt; names = super.getNames();
        //System.out.println("layer names in gisdata:"+names);
        List&lt;Name&gt; temp = new ArrayList&lt;Name&gt;();

        temp.addAll(0, names);
        Collections.sort(temp, new LayerSorter());
        return new LinkedHashSet&lt;Name&gt;(temp);
    }

    // 'getInstance().getLookup(o.getClass())' will always return a GISLookup&lt;O&gt;
    @SuppressWarnings("unchecked")
    public static &lt;O&gt; Geometry getGeometry(O o) throws IllegalArgumentException {
        if (o == null) {
            return null;
        }

        GISLookup&lt;O&gt; lookup = (GISLookup&lt;O&gt;) getInstance().getLookup(o.getClass());

        if (lookup == null) {
            throw new IllegalArgumentException(String.format(
                    "No GISLookup implementations found for class: %s", o.getClass()));
        }

        List&lt;Feature&gt; features = lookup.lookup(o);
        if (features == null || features.isEmpty()) {
            return null;
        }

        Feature firstFeature = features.get(0);

        GeometryAttribute attribute = firstFeature.getDefaultGeometryProperty();
        if (attribute == null) {
            return null;
        }

        Object value = attribute.getValue();
        if (value == null) {
            return null;
        }

        if (value instanceof Geometry) {
            return (Geometry) value;
        }

        return null;
    }

    public void register(String id, DataStore dataStore) throws IOException {
        register(id, dataStore, -1);
    }

    public void register(String id, DataStore dataStore, int sortLayer) throws IOException {
        if (c_sortLayers == null) {
            c_sortLayers = new HashMap&lt;Name, Integer&gt;();
        }
        if (dataStore != null) {
            c_sortLayers.put(new NameImpl(id), sortLayer);
        } else {
            c_sortLayers.remove(new NameImpl(id));
        }

        super.register(id, dataStore);
        for (GISLookup&lt;?&gt; lookup : lookups()) {
            lookup.register(id, dataStore);
        }
    }

    private class LayerSorter implements Comparator&lt;Name&gt; {

        @Override
        public int compare(Name o1, Name o2) {
            int i1 = c_sortLayers.get(o1);
            int i2 = c_sortLayers.get(o2);

            return i1 - i2;
        }
    }
}
</pre></body></html>