ingo@219: package de.intevation.flys.client.server;
ingo@219: 
ingo@219: import java.util.ArrayList;
ingo@219: import java.util.List;
ingo@219: 
ingo@219: import org.w3c.dom.Document;
ingo@219: import org.w3c.dom.Element;
ingo@219: import org.w3c.dom.NodeList;
ingo@219: 
ingo@1367: import org.apache.log4j.Logger;
ingo@1367: 
ingo@219: import com.google.gwt.user.server.rpc.RemoteServiceServlet;
ingo@219: 
ingo@219: import de.intevation.artifacts.common.ArtifactNamespaceContext;
ingo@219: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@219: 
ingo@219: import de.intevation.artifacts.httpclient.exceptions.ConnectionException;
ingo@219: import de.intevation.artifacts.httpclient.http.HttpClient;
ingo@219: import de.intevation.artifacts.httpclient.http.HttpClientImpl;
ingo@219: 
ingo@219: import de.intevation.flys.client.shared.exceptions.ServerException;
ingo@219: import de.intevation.flys.client.client.services.DistanceInfoService;
ingo@219: import de.intevation.flys.client.shared.model.DistanceInfoObject;
ingo@219: import de.intevation.flys.client.shared.model.DistanceInfoObjectImpl;
ingo@219: 
ingo@219: 
ingo@219: /**
ingo@219:  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
ingo@219:  */
ingo@219: public class DistanceInfoServiceImpl
ingo@219: extends      RemoteServiceServlet
ingo@219: implements   DistanceInfoService
ingo@219: {
ingo@1367:     private static final Logger logger =
ingo@1367:         Logger.getLogger(DistanceInfoServiceImpl.class);
ingo@1367: 
ingo@219:     public static final String ERROR_NO_DISTANCEINFO_FOUND =
ingo@219:         "error_no_distanceinfo_found";
ingo@219: 
ingo@219:     public static final String XPATH_DISTANCES = "art:distances/art:distance";
ingo@219: 
ingo@219: 
ingo@229:     public DistanceInfoObject[] getDistanceInfo(
ingo@229:         String locale,
ingo@229:         String river)
ingo@219:     throws ServerException
ingo@219:     {
ingo@1367:         logger.info("DistanceInfoServiceImpl.getDistanceInfo");
ingo@219: 
raimund@1425:         String url  = getServletContext().getInitParameter("server-url");
raimund@1425: 
ingo@219:         Document doc = XMLUtils.newDocument();
ingo@219: 
ingo@219:         XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
ingo@219:             doc,
ingo@219:             ArtifactNamespaceContext.NAMESPACE_URI,
ingo@219:             ArtifactNamespaceContext.NAMESPACE_PREFIX);
ingo@219: 
ingo@219:         Element riverEl = ec.create("river");
ingo@219: 
ingo@219:         riverEl.setTextContent(river);
ingo@219: 
ingo@219:         doc.appendChild(riverEl);
ingo@219: 
ingo@229:         HttpClient client = new HttpClientImpl(url, locale);
ingo@219: 
ingo@219:         try {
ingo@219:             Document result = client.callService(url, "distanceinfo", doc);
ingo@219: 
ingo@1367:             logger.debug("Extract distance info objects now.");
ingo@219:             DistanceInfoObject[] objects = extractDistanceInfoObjects(result);
ingo@219: 
ingo@219:             if (objects != null && objects.length > 0) {
ingo@219:                 return objects;
ingo@219:             }
ingo@219:         }
ingo@219:         catch (ConnectionException ce) {
ingo@1367:             logger.error(ce, ce);
ingo@219:         }
ingo@219: 
ingo@219:         throw new ServerException(ERROR_NO_DISTANCEINFO_FOUND);
ingo@219:     }
ingo@219: 
ingo@219: 
ingo@219:     /**
ingo@219:      * Extracts all distance info objects from <i>result</i> document.
ingo@219:      *
ingo@219:      * @param result The document retrieved by the server.
ingo@219:      *
ingo@219:      * @return a list of DistanceInfoObjects.
ingo@219:      */
ingo@219:     protected DistanceInfoObject[] extractDistanceInfoObjects(Document result)
ingo@219:     throws    ServerException
ingo@219:     {
sascha@569:         NodeList list = result.getElementsByTagName("distance");
ingo@219: 
ingo@219:         if (list == null || list.getLength() == 0) {
ingo@1367:             logger.warn("No distance info found.");
ingo@219:             throw new ServerException(ERROR_NO_DISTANCEINFO_FOUND);
ingo@219:         }
ingo@219: 
ingo@219:         int num = list.getLength();
ingo@1367:         logger.debug("Response contains " + num + " objects.");
ingo@219: 
ingo@219:         List<DistanceInfoObject> objects =
ingo@219:             new ArrayList<DistanceInfoObject>(num);
ingo@219: 
ingo@219:         for (int i = 0; i < num; i++) {
sascha@569:             DistanceInfoObject obj = buildDistanceInfoObject(
sascha@569:                 (Element)list.item(i));
ingo@219: 
ingo@219:             if (obj != null) {
ingo@219:                 objects.add(obj);
ingo@219:             }
ingo@219:         }
ingo@219: 
ingo@1367:         logger.debug("Retrieved " + objects.size() + " distances.");
ingo@219: 
ingo@219:         return (DistanceInfoObject[])
ingo@219:             objects.toArray(new DistanceInfoObject[num]);
ingo@219:     }
ingo@219: 
ingo@219: 
ingo@219:     /**
ingo@219:      * Extracts information for a single distance info object and intializes an
ingo@219:      * DistanceInfoObject with them.
ingo@219:      *
ingo@219:      * @param node The node that contains the information.
ingo@219:      *
ingo@219:      * @return a valid DistanceInfoObject.
ingo@219:      */
sascha@569:     protected DistanceInfoObject buildDistanceInfoObject(Element node) {
ingo@219: 
sascha@569:         String desc      = node.getAttribute("description").trim();
sascha@569:         String from      = node.getAttribute("from").trim();
sascha@569:         String to        = node.getAttribute("to").trim();
sascha@569:         String riverside = node.getAttribute("riverside").trim();
sascha@569:         String bottom    = node.getAttribute("bottom").trim();
sascha@569:         String top       = node.getAttribute("top").trim();
sascha@567: 
sascha@569:         if (desc.length() > 0 && from.length() > 0) {
sascha@569:             try {
sascha@569:                 Double f  = new Double(from);
sascha@569:                 Double t  = to    .length() > 0 ? new Double(to)     : null;
sascha@569:                 Double b  = bottom.length() > 0 ? new Double(bottom) : null;
sascha@569:                 Double tp = top   .length() > 0 ? new Double(top)    : null;
sascha@567: 
sascha@567:                 return new DistanceInfoObjectImpl(desc, f, t, riverside, b, tp);
ingo@219:             }
ingo@219:             catch (NumberFormatException nfe) {
ingo@1367:                 logger.warn(nfe.getLocalizedMessage());
ingo@219:             }
ingo@219:         }
ingo@219: 
ingo@1367:         logger.warn("Invalid distance info object found.");
ingo@219: 
ingo@219:         return null;
ingo@219:     }
ingo@219: }
ingo@219: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :