![JAR search and dependency download from the Maven repository](/logo.png)
it.tidalwave.geo.location.elmo.impl.ElmoGeoCoderEntityProxy Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* forceTen - open source geography
* Copyright (C) 2007-2012 by Tidalwave s.a.s. (http://www.tidalwave.it)
*
***********************************************************************************************************************
*
* 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.
*
***********************************************************************************************************************
*
* WWW: http://forceten.tidalwave.it
* SCM: https://bitbucket.org/tidalwave/forceten-src
*
**********************************************************************************************************************/
package it.tidalwave.geo.location.elmo.impl;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import org.openide.util.Parameters;
import org.openrdf.elmo.annotations.rdf;
import org.openrdf.elmo.Entity;
import it.tidalwave.util.logging.Logger;
import it.tidalwave.util.NotFoundException;
import it.tidalwave.semantic.LazyPropertyHolder;
import it.tidalwave.openrdf.elmo.ElmoVolatile;
import it.tidalwave.geo.Coordinate;
import it.tidalwave.geo.geocoding.GeoCoder;
import it.tidalwave.geo.geocoding.GeoCoderEntity;
import it.tidalwave.geo.geocoding.GeoCoderEntity.Type;
import it.tidalwave.geo.location.GeoSchema;
import it.tidalwave.geo.location.elmo.GeoVocabulary;
import static it.tidalwave.role.Displayable.Displayable;
import static it.tidalwave.role.MutableDisplayable.MutableDisplayable;
import static it.tidalwave.semantic.SkosConcept.SkosConcept;
import static it.tidalwave.geo.geocoding.GeoCoder.GeoCoder;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
**********************************************************************************************************************/
@rdf(GeoVocabulary.URI_GEO_ENTITY)
public class ElmoGeoCoderEntityProxy extends Support implements GeoCoderEntityProxy
{
private final static String CLASS = ElmoGeoCoderEntityProxy.class.getName();
private final static Logger logger = Logger.getLogger(CLASS);
@rdf(GeoVocabulary.URI_WGS84_LATITUDE) @CheckForNull
private Double latitude;
@rdf(GeoVocabulary.URI_WGS84_LONGITUDE) @CheckForNull
private Double longitude;
@rdf(GeoVocabulary.URI_WGS84_ALTITUDE) @CheckForNull
private Double altitude;
@rdf(GeoVocabulary.URI_LATEST_CHILDREN_QUERY_TIME) @CheckForNull
private XMLGregorianCalendar latestChildrenQueryTime;
@rdf(GeoVocabulary.URI_ROOT) @CheckForNull
private Boolean root; // a wrapper Boolean, so no statements for false // FIXME: use skos:topConceptOf
@rdf(GeoVocabulary.URI_CODE) @CheckForNull
private String code;
@rdf(GeoVocabulary.URI_TYPE)
private String typeAsString;
@rdf(GeoVocabulary.URI_SKOS_IN_SCHEME)
private GeoSchema geoSchema;
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ElmoVolatile
private final LazyPropertyHolder coordinateHolder = new LazyPropertyHolder()
{
@Override @CheckForNull
protected Coordinate create()
{
Coordinate result = null;
if ((latitude != null) && (longitude != null))
{
result = (altitude != null) ? new Coordinate(latitude, longitude, altitude)
: new Coordinate(latitude, longitude);
}
return result;
}
};
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@ElmoVolatile
private final LazyPropertyHolder geoCoderEntityHolder = new LazyPropertyHolder()
{
@Override @Nonnull
protected GeoCoderEntity create()
{
try
{
final QName qName = ElmoGeoCoderEntityProxy.this.as(Entity).getQName();
final GeoCoder geoCoder = geoSchema.getLookup().lookup(GeoCoder);
return geoCoder.findGeoEntityById(qName.getNamespaceURI() + qName.getLocalPart());
}
catch (NotFoundException e)
{
throw new RuntimeException(e); // malfunction
}
}
};
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public GeoCoderEntityProxy getParent()
throws NotFoundException
{
logger.fine("getParent() - %s", this);
//
// The root entity has no parent - in case of offline operation, don't ask anybody.
//
if (Boolean.TRUE.equals(root)) // root can be null or true
{
throw new NotFoundException(String.format("No parent for %s", this));
}
//
// First parent is searched in the local repository. This saves queries to the geocoder and fixes potential
// geocoder bugs (for instance, at 2009-02-12 GeoNames reports that parent of
// http://sws.geonames.org/6540563/ (Recco) is http://sws.geonames.org/3174725/ (Liguria)
// instead of http://sws.geonames.org/3176217/ (Provincia di Genova)
//
try
{
return as(SkosConcept).findBroaders().ofType(GeoCoderEntityProxy).result();
}
catch (NotFoundException e)
{
final GeoCoderEntity gcEntity = geoCoderEntityHolder.get();
assert gcEntity != null : "Null geoCoderEntity";
logger.finer(">>>> getting parent from %s", gcEntity);
final GeoCoderEntity gcParentEntity = gcEntity.getParent();
final GeoCoderEntityProxy gcParentEntityProxy = ElmoGeoCoderEntityProxyFactory.findOrCreate(geoSchema, gcParentEntity);
logger.finer(">>>> parent is %s", gcParentEntityProxy);
as(SkosConcept).addBroader(gcParentEntityProxy);
return gcParentEntityProxy;
}
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public List getChildren()
{
logger.fine("getChildren() - %s", this);
final List result = new ArrayList();
if (latestChildrenQueryTime == null)
{
final GeoCoderEntity gcEntity = geoCoderEntityHolder.get();
assert gcEntity != null : "Null geoCoderEntity for " + this;
logger.finest(">>>> getting children from geoEntity: %s", gcEntity);
for (final GeoCoderEntity gcEntityChild : gcEntity.findChildren().results())
{
final GeoCoderEntityProxy gcEntityChildProxy = ElmoGeoCoderEntityProxyFactory.findOrCreate(geoSchema, gcEntityChild);
as(SkosConcept).addNarrower(gcEntityChildProxy);
result.add(gcEntityChildProxy);
}
latestChildrenQueryTime = Support.toXMLGregorianCalendar(getTimeStamp());
merge(this);
}
else
{
logger.finest(">>>> getting children from narrowers");
result.addAll(as(SkosConcept).findNarrowers().ofType(GeoCoderEntityProxy).results());
}
logger.finer(">>>> returning: %s", result);
return result;
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public GeoCoderEntityProxy findChildByName (final @Nonnull String name)
throws NotFoundException
{
Parameters.notNull("name", name);
//
// If we have previously queried for all the children, we have the result here, so just query getChildren().
// We can't always delegate to getChildren(), because it stores all the children in the repository, while we
// want to be incremental.
//
if (latestChildrenQueryTime != null)
{
for (final GeoCoderEntityProxy gcEntityChildProxy : getChildren())
{
if (name.equals(gcEntityChildProxy.as(Displayable).getDisplayName()))
{
return gcEntityChildProxy;
}
}
}
else
{
final GeoCoderEntity gcEntity = geoCoderEntityHolder.get();
assert gcEntity != null : "Null geoCoderEntity for " + this;
for (final GeoCoderEntity gcEntityChild : gcEntity.findChildren().results())
{
if (name.equals(gcEntityChild.as(Displayable).getDisplayName()))
{
final GeoCoderEntityProxy gcEntityProxyChild =
ElmoGeoCoderEntityProxyFactory.findOrCreate(geoSchema, gcEntityChild);
as(SkosConcept).addNarrower(gcEntityProxyChild);
return gcEntityProxyChild;
}
}
}
throw new NotFoundException(String.format("Child not found: %s for %s", name, this));
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public Coordinate getCoordinate()
throws NotFoundException
{
return NotFoundException.throwWhenNull(coordinateHolder.get(), "No coordinate for " + this);
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public GeoCoderEntity getGeoCoderEntity()
{
final GeoCoderEntity gcEntity = geoCoderEntityHolder.get();
assert gcEntity != null : "Null geoCoderEntity for " + this;
return gcEntity;
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public Type getType()
{
return geoSchema.getLookup().lookup(GeoCoder).typeFromString(typeAsString);
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public String getCode()
{
return (code != null) ? code : "";
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override
public void setBindings (final @Nonnull GeoSchema geoSchema)
{
this.geoSchema = geoSchema;
}
/*******************************************************************************************************************
*
* {@inheritDoc}
*
******************************************************************************************************************/
@Override @Nonnull
public String toString()
{
final QName qName = as(Entity.class).getQName();
return String.format("ElmoGeoCoderEntityProxy@%x[%s (%s; %s; %s) root: %s code: %s type: %s lcqt: %s]",
System.identityHashCode(this),
qName.getNamespaceURI() + qName.getLocalPart(),
latitude, longitude, altitude,
root, code, typeAsString,
latestChildrenQueryTime);
}
/*******************************************************************************************************************
*
*
*
******************************************************************************************************************/
// @Override
protected void init (final @Nonnull GeoCoderEntity gcEntity)
{
as(MutableDisplayable).setDisplayName(gcEntity.as(Displayable).getDisplayName());
// SkosConceptUtils.setDisplayName(this, geoEntity.getLocalName(), Locale.???); FIXME: find the locale for the country
try
{
gcEntity.getParent();
}
catch (NotFoundException e)
{
root = true; // for false, leave it null
}
final Coordinate coordinate = gcEntity.getCoordinate();
if (coordinate != null)
{
latitude = coordinate.getLatitude();
longitude = coordinate.getLongitude();
altitude = coordinate.getAltitude();
}
typeAsString = gcEntity.getTypeAsString();
final String gcEntityCode = gcEntity.getCode();
code = "".equals(gcEntityCode) ? null : gcEntityCode; // here null is good, so no RDF statements are generated
merge(this);
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
private static Date getTimeStamp()
{
// FIXME: retrofit the TimestampProvider in blueMarine Metadata when it will be available in OpenBlueSky
if (Boolean.getBoolean("it.tidalwave.geo.location.elmo.impl.FakeTimeStamp"))
{
return new Date(1260026377000L);
}
return new Date();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy