Package com.esri.gpt.catalog.lucene

Source Code of com.esri.gpt.catalog.lucene.Locator$Candidate

/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. 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.esri.gpt.catalog.lucene;
import com.esri.gpt.framework.collection.StringAttribute;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ApplicationConfiguration;
import com.esri.gpt.framework.context.ApplicationContext;
import com.esri.gpt.framework.http.HttpClientRequest;
import com.esri.gpt.framework.util.Val;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
* Locator.
*/
public class Locator {

  /** geolocator service URL **/
  protected String url;

  /**
   * Creates new instance of the locator.
   * @return locator
   * @throws IllegalArgumentException if "lucene.locatorClass" parameter is invalid
   */
  public static Locator newInstance() {
    ApplicationContext appCtx = ApplicationContext.getInstance();
    ApplicationConfiguration appCfg = appCtx.getConfiguration();

    String locatorClassName = appCfg.getCatalogConfiguration().getParameters().getValue("lucene.locatorClass");

    if (Val.chkStr(locatorClassName).length() == 0) {
      return new Locator();
    } else {
      try {
        Class locatorClass = Class.forName(locatorClassName);
        return (Locator) locatorClass.newInstance();
      } catch (Exception ex) {
        throw new IllegalArgumentException("Invalid lucene.locatorClass parameter: " + locatorClassName);
      }
    }
  }

  /**
   * Finds candidates.
   * @param text address text
   * @return array of candidates
   * @throws IOException if accessing geolocator service fails
   * @throws ParseException if parsing address text fails
   */
  public Candidate[] find(String text) throws IOException, ParseException {
    String address = null, city = null, state = null, zip = null;

    LinkedList<String> elements = new LinkedList<String>();
    elements.addAll(Arrays.asList(Val.chkStr(text).split(",")));

    if (elements.size() >= 3) {
      zip = elements.removeLast();
      state = elements.removeLast();
      city = elements.removeLast();
    } else if (elements.size() == 2) {
      state = elements.removeLast();
      city = elements.removeLast();
    } else {
      city = elements.removeLast();
    }
    // all the rest is just address
    address = elements.toString();

    return find(address, city, state, zip);
  }

  /**
   * Finds best candidate from the array of candidates. Uses {@link Locator.ScoreComparator}.
   * @param candidates array of candidates
   * @return best candidate or <code>null</code> if no candidates can be found
   */
  public Candidate findBestCandidate(Candidate[] candidates) {
    return findBestCandidate(candidates, new ScoreComparator());
  }

  /**
   * Finds best candidate from the array of candidates.
   * @param candidates array of candidates
   * @param comparator comparator
   * @return best candidate or <code>null</code> if no candidates can be found
   */
  public Candidate findBestCandidate(Candidate[] candidates, Comparator<Candidate> comparator) {
    Candidate bestCandidate = null;
    if (candidates != null) {
      for (Locator.Candidate candidate : candidates) {
        if (comparator.compare(bestCandidate, candidate) > 0) {
          bestCandidate = candidate;
        }
      }
    }
    return bestCandidate;
  }

  /**
   * Creates instance of the locator.
   */
  protected Locator() {
    ApplicationContext appCtx = ApplicationContext.getInstance();
    ApplicationConfiguration appCfg = appCtx.getConfiguration();
    this.url = appCfg.getInteractiveMap().getLocatorUrl();
  }

  /**
   * Finds all candidates for the address.
   * @param address address
   * @param city city
   * @param state state
   * @param zip zip
   * @return array of candidates
   * @throws IOException if accessing geolocator service fails
   */
  protected Candidate[] find(String address, String city, String state, String zip) throws IOException {

    ArrayList<Candidate> candidates = new ArrayList<Candidate>();

    address = Val.chkStr(address);
    city = Val.chkStr(city);
    state = Val.chkStr(state);
    zip = Val.chkStr(zip);

    String requestUrl = this.makeQueryUrl(address, city, state, zip);

    HttpClientRequest client = HttpClientRequest.newRequest();
    client.setUrl(requestUrl);
    String sResponse = Val.chkStr(client.readResponseAsCharacters());

    if (sResponse.length() > 0) {
      try {

        JSONObject jso = new JSONObject(sResponse);
        JSONArray candidatesArr = jso.getJSONArray("candidates");
        for (int i = 0; i < candidatesArr.length(); i++) {
          JSONObject candidateObj = candidatesArr.getJSONObject(i);
          String candidateAddress = candidateObj.getString("address");
          JSONObject candidateLocation = candidateObj.getJSONObject("location");
          long candidateScore = candidateObj.getLong("score");
          JSONObject candidateAttributes = candidateObj.getJSONObject("attributes");
          double candidateX = candidateLocation.getDouble("x");
          double candidateY = candidateLocation.getDouble("y");
          StringAttributeMap attributes = new StringAttributeMap();
          JSONArray names = candidateAttributes.names();
          for (int n = 0; n < (names != null ? names.length() : 0); n++) {
            String name = names.getString(n);
            String value = candidateAttributes.getString(name);
            attributes.add(new StringAttribute(name, value));
          }

          Candidate candidate = new Candidate();
          candidate.setAddress(candidateAddress);
          candidate.setLocation(new double[]{candidateX, candidateY});
          candidate.setScore(candidateScore);
          candidate.setAttributes(attributes);

          candidates.add(candidate);
        }

      } catch (JSONException ex) {
        throw new IOException("Error reading response: "+ex.getMessage());
      }
    }

    return candidates.toArray(new Candidate[candidates.size()]);
  }

  /**
   * Makes query URL.
   * @param address address
   * @param city city
   * @param state state
   * @param zip zip
   * @return query url
   */
  protected String makeQueryUrl(String address, String city, String state, String zip) {
    StringBuilder query = new StringBuilder();
    if (address.length()>0) {
      if (query.length() > 0) {
        query.append("&");
      }
      query.append("Address=" + encode(address));
    }
    if (city.length()>0) {
      if (query.length() > 0) {
        query.append("&");
      }
      query.append("City=" + encode(city));
    }
    if (state.length()>0) {
      if (query.length() > 0) {
        query.append("&");
      }
      query.append("State=" + encode(state));
    }
    if (zip.length()>0) {
      if (query.length() > 0) {
        query.append("&");
      }
      query.append("Zip=" + encode(zip));
    }
    if (query.length() > 0) {
      query.append("&");
    }
    query.append("f=pjson");

    return url + "/findAddressCandidates?" + query;
  }

  /**
   * Encodes string.
   * @param s string to encode
   * @return encoded string
   */
  private String encode(String s) {
    try {
      return URLEncoder.encode(s, "UTF-8");
    } catch (UnsupportedEncodingException ex) {
      return s;
    }
  }

  /**
   * Score comparator.
   */
  public static class ScoreComparator implements Comparator<Candidate> {

    public int compare(Candidate o1, Candidate o2) {
      if (o1 == null && o2 == null) {
        return 0;
      }
      if (o1 == null) {
        return 1;
      }
      if (o2 == null) {
        return -1;
      }
      if (o1.getScore() == o2.getScore()) {
        return 0;
      }
      return o1.getScore() < o2.getScore() ? 1 : -1;
    }
  };

  /**
   * Candidate.
   */
  public static class Candidate {

    private String address;
    private double[] location;
    private long score;
    private StringAttributeMap attributes;

    /**
     * Gets address.
     * @return the address
     */
    public String getAddress() {
      return address;
    }

    /**
     * Sets address.
     * @param address the address to set
     */
    void setAddress(String address) {
      this.address = address;
    }

    /**
     * Gets point.
     * @return the point
     */
    public double[] getLocation() {
      return location;
    }

    /**
     * Sets point
     * @param point the point to set
     */
    void setLocation(double[] point) {
      this.location = point;
    }

    /**
     * Gets score.
     * @return the score
     */
    public long getScore() {
      return score;
    }

    /**
     * Sets score.
     * @param score the score to set
     */
    void setScore(long score) {
      this.score = score;
    }

    /**
     * Gets attributes.
     * @return the attributes
     */
    public StringAttributeMap getAttributes() {
      return attributes;
    }

    /**
     * Sets attributes.
     * @param attributes the attributes to set
     */
    void setAttributes(StringAttributeMap attributes) {
      this.attributes = attributes;
    }
  }
}
TOP

Related Classes of com.esri.gpt.catalog.lucene.Locator$Candidate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.