/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.metadata.sql;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;
/**
* A metadata entity which implements (indirectly) metadata
* interfaces like {@link org.opengis.metadata.MetaData},
* {@link org.opengis.metadata.citation.Citation}, etc.
*
* Any call to a method in a metadata interface is redirected toward the
* {@link #invoke} method. This method use reflection in order to find
* the caller's method and class name. The class name is translated into
* a table name, and the method name is translated into a column name.
* Then the information is fetch in the underlying metadata database.
*
* @since 2.1
* @source $URL$
* @version $Id$
* @author Touraïvane
* @author Martin Desruisseaux (IRD)
*/
final class MetadataEntity implements InvocationHandler {
/**
* The identifier used in order to locate the record for
* this metadata entity in the database. This is usually
* the primary key in the table which contains this entity.
*/
private final String identifier;
/**
* The connection to the database. All metadata entities
* created from a single database should share the same source.
*/
private final MetadataSource source;
/**
* Creates a new metadata entity.
*
* @param identifier The identifier used in order to locate the record for
* this metadata entity in the database. This is usually
* the primary key in the table which contains this entity.
* @param source The connection to the table which contains this entity.
*/
public MetadataEntity(final String identifier, final MetadataSource source) {
this.identifier = identifier;
this.source = source;
}
/**
* Invoked when any method from a metadata interface is invoked.
*
* @param proxy The object on which the method is invoked.
* @param method The method invoked.
* @param args The argument given to the method.
*/
public Object invoke(final Object proxy,
final Method method,
final Object[] args)
{
final Class<?> type = method.getDeclaringClass();
if (type.getName().startsWith(source.metadataPackage)) {
if (args!=null && args.length!=0) {
throw new MetadataException("Unexpected argument."); // TODO: localize
}
/*
* The method invoked is a method from the metadata interface.
* Consequently, the information should exists in the underlying
* database.
*/
try {
return source.getValue(type, method, identifier);
} catch (SQLException e) {
throw new MetadataException("Failed to query the database.", e); // TODO: localize
}
} else {
/*
* The method invoked is a method inherit from a parent class,
* like Object.toString() or Object.hashCode(). This information
* is not expected to exists in the database. Forward the call
* to this object object, since they is only one instance by proxy.
* Note: do not forward to the proxy in order to avoid never-ending
* loop.
*/
try {
return method.invoke(this, args);
} catch (IllegalAccessException e) {
throw new MetadataException("Illegal method call.", e); // TODO: localize
} catch (InvocationTargetException e) {
throw new MetadataException("Illegal method call.", e); // TODO: localize
}
}
}
}