/* Copyright (c) 2008 Google Inc.
*
* Licensed 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.google.gdata.data.geo.impl;
import com.google.gdata.data.BaseEntry;
import com.google.gdata.data.Extension;
import com.google.gdata.data.ExtensionDescription;
import com.google.gdata.data.ExtensionPoint;
import com.google.gdata.data.ExtensionProfile;
import com.google.gdata.data.geo.Point;
import com.google.gdata.data.geo.PointData;
/**
* Implementation of the PointData interface. Currently only supports
* a non-repeating Point extension. This class uses an {@link ExtensionPoint}
* that is passed in to store the Point extension.
*
*
*/
public class PointDataImpl implements PointData {
private ExtensionPoint extPoint;
/**
* Construct a new implementation of PointData with the given
* extension point as the backing storage for data.
*/
public PointDataImpl(ExtensionPoint extensionPoint) {
this.extPoint = extensionPoint;
}
/**
* Sets the geo-location of the entity based on the lat and long coordinates
* passed in.
*
* @param lat The latitude coordinate, between -90 and 90 degrees.
* @param lon The longitude coordinate, between -180 and 180 degrees.
* @throws IllegalArgumentException if the latitude and longitude coordinates
* are invalid.
*/
public void setGeoLocation(Double lat, Double lon)
throws IllegalArgumentException {
setGeoLocation(new GeoRssWhere(lat, lon));
}
/**
* Sets the geo-location of the entity based on the Point extension.
*
* @param point A point containing the latitude and longitude coordinates.
*/
public void setGeoLocation(Point point) {
setPoint(extPoint, point);
}
/**
* Gets the geo-location of the entity.
* @return a Point that contains the geo-coordinates (latitude and longitude).
*/
public Point getGeoLocation() {
return getPoint(extPoint);
}
public void clearPoint() {
clearPoint(extPoint);
}
/*
* Declare the extensions that are used for storing Point information.
*/
public void declareExtensions(ExtensionProfile extProfile) {
Class<? extends ExtensionPoint> extClass = extPoint.getClass();
// Declare all all Point implementations here so they are parsable
// in the context of extClass.
// Declare our various point extensions, none are repeatable.
declare(extProfile, extClass, W3CPoint.getDefaultDescription(false));
declare(extProfile, extClass, GeoRssPoint.getDefaultDescription(false));
declare(extProfile, extClass, GeoRssWhere.getDefaultDescription(false));
new W3CPoint().declareExtensions(extProfile);
new GeoRssWhere().declareExtensions(extProfile);
}
/**
* Helper method to add the description to the BaseEntry as well as to the
* extension class, so auto extension works properly.
*/
private void declare(ExtensionProfile extProfile,
Class<? extends ExtensionPoint> extClass, ExtensionDescription desc) {
extProfile.declare(extClass, desc);
if (BaseEntry.class.isAssignableFrom(extClass)) {
extProfile.declare(BaseEntry.class, desc);
}
}
/**
* Sets the geo point of the extension passed in. This will first try to
* replace any existing point information. If there is no existing point, then
* it will simply add the point extension.
*
* @param ext The extension point to add the Point to.
* @param point The new point information.
*/
public static void setPoint(ExtensionPoint ext, Point point) {
Point existing = getPointExtension(ext);
if (existing != null) {
Double lat = point != null ? point.getLatitude() : null;
Double lon = point != null ? point.getLongitude() : null;
existing.setGeoLocation(lat, lon);
} else if (point != null) {
ext.setExtension(point);
}
}
/**
* Iterates through all the extension points and finds the first matching
* Point extension.
*
* NOTE(pingc): Made package private for testing. DO NOT USE.
*
* @param ext The extension point to search through.
* @return A point extension point. This includes GeoRssWhere that may only
* contain a box.
*/
static Point getPointExtension(ExtensionPoint ext) {
for (Extension e : ext.getExtensions()) {
if (e instanceof Point) {
return (Point) e;
}
}
return null;
}
/**
* Helper method to retrieve the Box extension point.
* @param ext The containing extension point.
* @return An extension point that implements the Box interface and contain
* box information.
*/
public static Point getPoint(ExtensionPoint ext) {
Point p = getPointExtension(ext);
if (p != null) {
if (p instanceof GeoRssWhere) {
GeoRssWhere geoWhere = (GeoRssWhere)p;
if (geoWhere.hasPoint()) {
return geoWhere;
}
} else {
return p;
}
}
return null;
}
/**
* Removes the first Point extension found on the extension point. If the
* point extension is a GeoRssWhere, it will only remove the GeoRssWhere
* extension if it does not contain a Box/Envelope extension.
*
* @param ext The extension point from which to clear the Box extension.
*/
public static void clearPoint(ExtensionPoint ext) {
Point p = getPointExtension(ext);
if (p != null) {
if (p instanceof GeoRssWhere) {
GeoRssWhere where = (GeoRssWhere)p;
if (where.hasBox()) {
// If the GeoRssWhere has a box, just clear the point, otherwise
// remove the whole thing.
where.clearPoint();
return;
}
}
ext.removeExtension(p);
}
}
}