geo/src/main/java/org/netbeans/html/geo/spi/GLProvider.java
author Jaroslav Tulach <jtulach@netbeans.org>
Wed, 27 Aug 2014 18:44:16 +0200
branchGeoSPI
changeset 845 0a7a5a880e6d
parent 844 cdc17834e71c
child 847 ef06d881d758
permissions -rw-r--r--
Referencing innerclasses directly. Only then links in Javadoc show up.
     1 /**
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
    31  *
    32  * If you wish your version of this file to be governed by only the CDDL
    33  * or only the GPL Version 2, indicate your decision by adding
    34  * "[Contributor] elects to include this software in this distribution
    35  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    36  * single choice of license, a recipient has the option to distribute
    37  * your version of this file under either the CDDL, the GPL Version 2 or
    38  * to extend the choice of license to its licensees as provided above.
    39  * However, if you add GPL Version 2 code and therefore, elected the GPL
    40  * Version 2 license, then the option applies only if the new code is
    41  * made subject to such option by the copyright holder.
    42  */
    43 
    44 package org.netbeans.html.geo.spi;
    45 
    46 import net.java.html.BrwsrCtx;
    47 import net.java.html.geo.Position;
    48 import net.java.html.geo.Position.Handle;
    49 import net.java.html.geo.Position.Coordinates;
    50 import org.netbeans.html.context.spi.Contexts;
    51 import org.openide.util.lookup.ServiceProvider;
    52 
    53 /** SPI for those who wish to provide their own way of obtaining geolocation.
    54  * Subclass this class, implement its method and register it into the system.
    55  * You can either use {@link ServiceProvider} to register globally, or 
    56  * one can register into {@link BrwsrCtx} (via 
    57  * {@link Contexts.Builder#register(java.lang.Class, java.lang.Object, int) context builder}).
    58  * <p>
    59  * There is default system provider (used as a fallback) based on 
    60  * <a href="http://www.w3.org/TR/geolocation-API/">
    61  * W3C's Geolocation</a> specification - if you are running inside a
    62  * browser that supports such standard and you are satisfied with its
    63  * behavior, you don't have to register anything.
    64  * <p>
    65  * The provider serves two purposes: 
    66  * <ol>
    67  *   <li>
    68  *     It handles a geolocation request and creates a "watch" to represent it -
    69  *     to do so implement the {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) start} 
    70  *     method and the {@link #stop(java.lang.Object) stop} method.
    71  *   </li>
    72  *   <li>
    73  *     Once the location is found, the provider needs to 
    74  *     {@link #callback(org.netbeans.html.geo.spi.GLProvider.Callback, long, java.lang.Object, java.lang.Exception) call back}
    75  *     with appropriate location information which can be extracted
    76  *     later via {@link #latitude(java.lang.Object)} {@link #longitude(java.lang.Object)}, and
    77  *     other methods in this that also need to be implemented.
    78  *   </li>
    79  * </ol>
    80  * <p>
    81  * The provider is based on a 
    82  * <a href="http://wiki.apidesign.org/wiki/Singletonizer" target="_blank">singletonizer</a> 
    83  * pattern (applied twice)
    84  * and as such one is only required to subclass just the {@link GLProvider} 
    85  * and otherwise has freedom choosing what classes to use
    86  * to represent coordinates and watches. For example if it is enough to use
    87  * an array for coordinates and a long number for a watch, one can do:
    88  * <pre>
    89  * <b>public final class</b> MyGeoProvider extends {@link GLProvider}&lt;Double[], Long&gt; {
    90  *   <em>// somehow implement the methods</em>
    91  * }
    92  * </pre>
    93  *
    94  * @author Jaroslav Tulach
    95  * @param <Watch> your choosen type to represent one query (one time) or watch (repeated) request -
    96  *   this type is used in {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) start}
    97  *   and {@link #stop(java.lang.Object) stop} methods.
    98  * 
    99  * @param <Coords> your choosen type to represent geolocation coordinates -
   100  *   use in many methods in this class like {@link #latitude(java.lang.Object)} and
   101  *   {@link #longitude(java.lang.Object)}.
   102  * 
   103  * @since 1.0
   104  */
   105 public abstract class GLProvider<Coords,Watch> {
   106     /** Start obtaining geolocation.
   107      * When the client {@link Handle#start() requests location} (and
   108      * your provider is found) this method should initialize the request or 
   109      * return <code>null</code> to give chance to another provider.
   110      * 
   111      * @param c the callback to {@link #callback(org.netbeans.html.geo.spi.GLProvider.Callback, long, java.lang.Object, java.lang.Exception) use when location is found} -
   112      *    keep it, you'll need it later
   113      * @param oneTime one time request vs. repeated requests
   114      *    - mimics value provided in {@link Handle#Handle(boolean) constructor}
   115      * @param enableHighAccuracy mimics value of
   116      *    {@link Handle#setHighAccuracy(boolean)}
   117      * @param timeout mimics value of
   118      *    {@link Handle#setTimeout(long)}
   119      * @param maximumAge mimics value of 
   120      *    {@link Handle#setMaximumAge(long)}
   121      * 
   122      * @return an object representing the request (so it can be {@link #stop(java.lang.Object) stopped} later)
   123      *   or <code>null</code> if this provider was unable to start the request
   124      */
   125     protected abstract Watch start(
   126         Callback c, 
   127         boolean oneTime, boolean enableHighAccuracy, 
   128         long timeout, long maximumAge
   129     );
   130     
   131     /** Called when a geolocation request should be stopped.
   132      * 
   133      * @param watch the watch returned when {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) starting}
   134      *   the request
   135      */
   136     protected abstract void stop(Watch watch);
   137 
   138     /** Invoke this method when your provider obtained request location.
   139      * This single method is used for notification of success (when <code>ex</code>
   140      * argument is <code>null</code> and <code>position</code> is provided) or 
   141      * a failure (when <code>ex</code> argument is non-<code>null</code>).
   142      * A successful requests leads in call to {@link Handle#onLocation(net.java.html.geo.Position)}
   143      * while an error report leads to call to {@link Handle#onError(java.lang.Exception)}.
   144      * 
   145      * @param c the callback as provided when {@link #start(org.netbeans.html.geo.spi.GLProvider.Callback, boolean, boolean, long, long) starting}
   146      *   the request
   147      * @param timestamp milliseconds since epoch when the location has been obtained
   148      * @param position your own, internal, representation of geolocation
   149      *   coordinates - will be passed back to other methods of this class
   150      *   like {@link #latitude(java.lang.Object)} and {@link #longitude(java.lang.Object)}.
   151      *   Can be <code>null</code> if <code>ex</code> is non-<code>null</code>
   152      * @param ex an exception to signal an error - should be <code>null</code>
   153      *   when one notifies the successfully obtained <code>position</code>
   154      */
   155     protected final void callback(
   156         Callback c,
   157         long timestamp, Coords position,
   158         Exception ex
   159     ) {
   160         if (ex == null) {
   161             c.onLocation(new Position(timestamp, new CoordImpl<Coords>(position, this)));
   162         } else {
   163             c.onError(ex);
   164         }
   165     }
   166 
   167     /** Extracts value for {@link Coordinates#getLatitude()}.
   168      * @param coords your own internal representation of coordinates.
   169      * @return geographic coordinate specified in decimal degrees.
   170      */
   171     protected abstract double latitude(Coords coords);
   172     
   173     /** Extracts value for {@link Coordinates#getLatitude()}.
   174      * @param coords your own internal representation of coordinates.
   175      * @return geographic coordinate specified in decimal degrees.
   176      */
   177     protected abstract double longitude(Coords coords);
   178     
   179     /** Extracts value for {@link Coordinates#getLatitude()}.
   180      * The accuracy attribute denotes the accuracy level of the latitude 
   181      * and longitude coordinates.
   182      * 
   183      * @param coords your own internal representation of coordinates.
   184      * @return accuracy in meters
   185      */
   186     protected abstract double accuracy(Coords coords);
   187     
   188     /** Extracts value for {@link Coordinates#getAltitude()}.
   189      * Denotes the height of the position, specified in meters above the ellipsoid.
   190      * 
   191      * @param coords your own internal representation of coordinates.
   192      * @return value in meters, may return null, if the information is not available
   193      */
   194     protected abstract Double altitude(Coords coords);
   195     
   196     /** Extracts value for {@link Coordinates#getAltitudeAccuracy()} -
   197      * the altitude accuracy is specified in meters. 
   198      * 
   199      * @param coords your own internal representation of coordinates.
   200      * @return value in meters; may return null, if the information is not available
   201      */
   202     protected abstract Double altitudeAccuracy(Coords coords);
   203     
   204     /** Extracts value for {@link Coordinates#getHeading()}.
   205      * Denotes the magnitude of the horizontal component of the 
   206      * device's current velocity and is specified in meters per second.
   207      * 
   208      * @param coords your own internal representation of coordinates.
   209      * @return may return null, if the information is not available 
   210      */
   211     protected abstract Double heading(Coords coords);
   212     
   213     /** Extracts value for {@link Coordinates#getSpeed()}.
   214      * Denotes the magnitude of the horizontal component of the 
   215      * device's current velocity and is specified in meters per second.
   216      * 
   217      * @param coords your own internal representation of coordinates.
   218      * @return may return null, if the information is not available
   219      */
   220     protected abstract Double speed(Coords coords);
   221     
   222     /** A callback interface used by {@link GLProvider} to notify back
   223      * results of its findings.
   224      */
   225     public abstract class Callback {
   226         /** Restricted constructor.
   227          * @throws IllegalStateException most of the time
   228          */
   229         protected Callback() {
   230             if (!getClass().getName().equals("net.java.html.geo.Position$Handle$JsH")) {
   231                 throw new IllegalStateException();
   232             }
   233         }
   234 
   235         /** Initiates a geolocation request. 
   236          * 
   237          * @param oneTime one time request vs. repeated requests
   238          *    - mimics value provided in {@link Handle#Handle(boolean) constructor}
   239          * @param enableHighAccuracy mimics value of
   240          *    {@link Handle#setHighAccuracy(boolean)}
   241          * @param timeout mimics value of
   242          *    {@link Handle#setTimeout(long)}
   243          * @param maximumAge mimics value of 
   244          *    {@link Handle#setMaximumAge(long)}
   245          * @return an object representing the request (so it can be {@link #stop(java.lang.Object) stopped} later)
   246          *   or <code>null</code> if this provider was unable to start the request
   247          */
   248         protected final Watch start(boolean oneTime, boolean enableHighAccuracy, long timeout, long maximumAge) {
   249             return GLProvider.this.start(this, oneTime, enableHighAccuracy, timeout, maximumAge);
   250         }
   251   
   252         /** Stops the watch request.
   253          * @param w the watch
   254          */
   255         protected final void stop(Watch w) {
   256             GLProvider.this.stop(w);
   257         }
   258         
   259         /** Called when a position is successfully obtained.
   260          * 
   261          * @param p the position
   262          */
   263         protected abstract void onLocation(Position p);
   264         
   265         /** Called on an error during obtaining of the position.
   266          * @param ex exception describing the error
   267          */
   268         protected abstract void onError(Exception ex);
   269     }
   270 }