/* 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.ExtensionDescription;
import com.google.gdata.data.ValueConstruct;
import com.google.gdata.data.geo.Box;
import com.google.gdata.data.geo.Namespaces;
import com.google.gdata.data.geo.Point;
/**
* A georss:box that contains 2 points, like:
* <georss:box>42.943 -71.032 43.039 -69.856</georss:box>
*
*
*/
public class GeoRssBox extends ValueConstruct implements Box {
static final String NAME = "box";
private Point lowerLeft;
private Point upperRight;
/**
* Constructs an empty georss:box element.
*/
public GeoRssBox() {
this(null, null);
}
/**
* Constructs a georss:box element with the given set of points.
*/
public GeoRssBox(Double lowerLat, Double lowerLon,
Double upperLat, Double upperLon) {
this(new GeoRssPoint(lowerLat, lowerLon),
new GeoRssPoint(upperLat, upperLon));
}
/**
* Constructs a georss:box element with the given bounding points.
*/
public GeoRssBox(Point lowerLeft, Point upperRight) {
super(Namespaces.GEO_RSS_NAMESPACE, NAME, null);
if (lowerLeft == null && upperRight == null) {
setRequired(false);
}
setGeoLocation(lowerLeft, upperRight);
}
/**
* Constructs a georss:box element by copying the data from the given box.
* Will call the {@link #GeoRssBox(Point, Point)} constructor with the parts
* of the passed in box, or with nulls if the box itself is null.
*/
public GeoRssBox(Box box) {
this(box == null ? null : box.getLowerLeft(),
box == null ? null : box.getUpperRight());
}
/**
* Returns the suggested extension description with configurable
* repeatability.
*/
public static ExtensionDescription getDefaultDescription(boolean repeatable) {
ExtensionDescription desc = new ExtensionDescription();
desc.setExtensionClass(GeoRssBox.class);
desc.setNamespace(Namespaces.GEO_RSS_NAMESPACE);
desc.setLocalName(NAME);
desc.setRepeatable(repeatable);
return desc;
}
/**
* Returns the suggested extension description and is repeatable.
*/
public static ExtensionDescription getDefaultDescription() {
return getDefaultDescription(true);
}
/**
* Gets the lower left point.
*/
public Point getLowerLeft() {
return lowerLeft;
}
/**
* Gets the upper right point.
*/
public Point getUpperRight() {
return upperRight;
}
/*
* Sets the geo location based on the given points.
*/
public void setGeoLocation(Point lowerLeft, Point upperRight) {
if (lowerLeft != null && upperRight != null) {
if (lowerLeft.getLatitude() > upperRight.getLatitude()) {
throw new IllegalArgumentException(
"'lowerLeft' must be below 'upperRight'.");
}
} else if (lowerLeft != null || upperRight != null) {
throw new IllegalArgumentException(
"'lowerLeft' and 'upperRight' must either both be null or non-null.");
}
this.lowerLeft = lowerLeft;
this.upperRight = upperRight;
super.setValue(toString());
}
/*
* Overriding toString to generate the string representation of the point.
*/
@Override
public String toString() {
if (lowerLeft != null && upperRight != null) {
return lowerLeft.getLatitude() + " " + lowerLeft.getLongitude()
+ " " + upperRight.getLatitude() + " " + upperRight.getLongitude();
}
return null;
}
/*
* Overriding setValue to parse the string into two latlong pairs, and then
* set those values. Will throw illegal argument exceptions if the format
* isn't correct.
*/
@Override
public void setValue(String v) {
Point lower = null;
Point upper = null;
if (v != null) {
v = v.trim();
String[] values = v.split(" ");
if (values.length != 4) {
throw createInvalidValueException();
}
lower = getPoint(values[0], values[1]);
upper = getPoint(values[2], values[3]);
}
// This will also call super.setValue so we don't call it here.
setGeoLocation(lower, upper);
}
/*
* Converts a pair of strings into a point object.
*/
private Point getPoint(String latStr, String lonStr) {
try {
Double lat = Double.valueOf(latStr);
Double lon = Double.valueOf(lonStr);
return new GeoRssPoint(lat, lon);
} catch (NumberFormatException e) {
throw createInvalidValueException();
}
}
/**
* Helper to generate the nice error message when given illegal values.
*/
private IllegalArgumentException createInvalidValueException() {
return new IllegalArgumentException(
"Format of a georss:box is \"latitude longitude latitude longitutde\","
+ " where the first pair is the lower left point, and the second pair"
+ " is the upper right point. All values must be doubles, separated"
+ " by spaces.");
}
}