2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
6 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7 * Other names may be trademarks of their respective owners.
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]"
29 * The Original Software is NetBeans. The Initial Developer of the Original
30 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
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.
43 package net.java.html.geo;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
47 import org.netbeans.html.geo.impl.JsG;
49 /** Class that represents a geolocation position provided as a callback
50 * to {@link Handle#onLocation(net.java.html.geo.Position)} method. The
51 * class getters mimic closely the structure of the position object as
52 * specified by <a href="http://www.w3.org/TR/2012/PRgeolocationAPI20120510/">
53 * W3C's Geolocation API</a>.
55 * @author Jaroslav Tulach <jtulach@netbeans.org>
57 public final class Position {
58 static final Logger LOG = Logger.getLogger(Position.class.getName());
59 private final long timestamp;
60 private final Coordinates coords;
62 Position(Object position) {
63 Object obj = JsG.get(position, "timestamp");
64 timestamp = obj instanceof Number ? ((Number)obj).longValue() : 0L;
65 coords = new Coordinates(JsG.get(position, "coords"));
68 /** The actual location of the position.
69 * @return non-null coordinates
71 public Coordinates getCoords() {
75 /** The time when the position has been recorded.
76 * @return time in milliseconds since era (e.g. Jan 1, 1970).
78 public long getTimestamp() {
82 /** Actual location of a {@link Position}.
83 * Mimics closely <a href="http://www.w3.org/TR/2012/PRgeolocationAPI20120510/">
84 * W3C's Geolocation API</a>.
86 public static final class Coordinates {
87 private final Object data;
89 Coordinates(Object data) {
93 public double getLatitude() {
94 return ((Number)JsG.get(data, "latitude")).doubleValue(); // NOI18N
97 public double getLongitude() {
98 return ((Number)JsG.get(data, "longitude")).doubleValue(); // NOI18N
101 public double getAccuracy() {
102 return ((Number)JsG.get(data, "accuracy")).doubleValue(); // NOI18N
105 public Double getAltitude() {
106 return (Double)JsG.get(data, "altitude"); // NOI18N
109 public Double getAltitudeAccuracy() {
110 return (Double)JsG.get(data, "altitudeAccuracy"); // NOI18N
113 public Double getHeading() {
114 return (Double)JsG.get(data, "heading"); // NOI18N
117 public Double getSpeed() {
118 return (Double)JsG.get(data, "speed"); // NOI18N
120 } // end of Coordinates
122 /** Rather than subclassing this class directly consider using {@link OnLocation}
123 * annotation. Such annotation will generate a subclass for you automatically
124 * with two static methods <code>createQuery</code> and <code>createWatch</code>
125 * which can be used to obtain instance of this class.
127 public static abstract class Handle {
128 private final boolean oneTime;
129 private boolean enableHighAccuracy;
130 private long timeout;
131 private long maximumAge;
134 /** Creates new instance of this handle.
136 * @param oneTime <code>true</code> if the handle represents one time
137 * <em>query</em>. <code>false</code> if it represents a <em>watch</em>
139 protected Handle(boolean oneTime) {
141 this.oneTime = oneTime;
144 /** Callback from the implementation when a (new) position has been
145 * received and identified
146 * @param p the position
147 * @throws Throwable if an exception is thrown, it will be logged by the system
149 protected abstract void onLocation(Position p) throws Throwable;
151 /** Callback when an error occurs.
152 * @param ex the exception describing what went wrong
153 * @throws Throwable if an exception is thrown, it will be logged by the system
155 protected abstract void onError(Exception ex) throws Throwable;
157 /** Check whether the location API is supported.
158 * @return true, if one can call {@link #start}.
160 public final boolean isSupported() {
161 return JsG.hasGeolocation();
164 /** Turns on high accuracy mode as specified by the
165 * <a href="http://www.w3.org/TR/2012/PRgeolocationAPI20120510/">
166 * W3C's Geolocation API</a>. By default the mode is disabled.
167 * @param enable <code>true</code> or <code>false</code>
169 public final void setHighAccuracy(boolean enable) {
170 this.enableHighAccuracy = enable;
173 /** The amount of milliseconds to wait for a result.
174 * By default infinity.
175 * @param timeout time in milliseconds to wait for a result.
177 public final void setTimeout(long timeout) {
178 this.timeout = timeout;
181 /** Sets maximum age of cached results which are acceptable to be
182 * returned. By default maximum age is set to zero.
183 * @param age time in milliseconds of acceptable cached results
185 public final void setMaximumAge(long age) {
186 this.maximumAge = age;
189 /** Initializes the <em>query</em> or <em>watch</em> request(s) and
190 * returns immediately. Has no effect if the query has already been
191 * started. If a problem appears while starting the system,
192 * it is immediately reported via the {@link #onError(java.lang.Exception)}
193 * callback. For example, if the {@link #isSupported()} method
194 * returns <code>false</code> an IllegalStateException is created
195 * and sent to the {@link #onError(java.lang.Exception) callback} method.
197 public final void start() {
198 if (handle != null) {
203 if (!isSupported()) {
204 throw new IllegalStateException("geolocation API not supported");
207 } catch (Exception ex) {
210 } catch (Throwable thr) {
211 LOG.log(Level.INFO, "Problems delivering onError report", thr);
216 /** Stops all pending requests. After this call no further callbacks
217 * can be obtained. Does nothing if no query or watch was in progress.
219 public final void stop() {
228 private final class JsH extends JsG {
232 public void onLocation(Object position) {
233 if (handle != this) {
240 Handle.this.onLocation(new Position(position));
241 } catch (Throwable ex) {
242 LOG.log(Level.SEVERE, null, ex);
247 public void onError(Object error) {
248 if (handle != this) {
255 Handle.this.onError(new Exception());
256 } catch (Throwable ex) {
257 LOG.log(Level.SEVERE, null, ex);
262 watch = start(oneTime, enableHighAccuracy, timeout, maximumAge);
265 protected final void stop() {