/*
* EuroCarbDB, a framework for carbohydrate bioinformatics
*
* Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
* A copy of this license accompanies this distribution in the file LICENSE.txt.
*
* This program 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.
*
* Last commit: $Rev: 1313 $ by $Author: glycoslave $ on $Date:: 2009-06-29 #$
*/
package org.eurocarbdb.dataaccess;
// stdlib imports
import java.lang.reflect.Method;
import java.util.Date;
// 3rd party imports
import org.apache.log4j.Logger;
// eurocarb imports
import org.eurocarbdb.util.StringUtils;
import org.eurocarbdb.util.XmlSerialiser;
import org.eurocarbdb.dataaccess.EntityManager;
import org.eurocarbdb.dataaccess.core.Taxonomy;
import org.eurocarbdb.dataaccess.core.Evidence;
import org.eurocarbdb.dataaccess.core.Reference;
import org.eurocarbdb.dataaccess.exception.EurocarbException;
// static imports
import static org.eurocarbdb.util.Version.date2version;
/**
* Provides a default implementation of the {@link EurocarbObject}
* interface, which is supported by every Eurocarb data access
* object (DAO). Key methods that may need to be overridden in
* sub-classes are:
*<ol>
* <li>{@link #getIdentifierClass()} and {@link #getId()} -- various
* UI and reflection-based generic strategies rely on these methods.
* Any class that is the base class for other classes (eg: such as
* {@link Evidence} and {@link Reference}) will *have* to override
* these methods if the subclasses are potentially
* {@link EntityManager#lookup looked up} by their superclass +
* superclass ID.<br/>
* It's never a bad idea to override {@link #getId()}
* to point at your class's main ID getter as it saves a reflection-
* based lookup, and is completely dependent on the convention for
* there to be a getYourClassNameId() method.
* </li>
* <li>{@link #validate()} -- this is called by {@link EntityManager}</li>s
* during any persistence operation. The default implementation of this
* method does nothing, but subclasses should override it to check that
* essential properties and associations have been set.
*</ol>
*
* @author mjh
*/
public class BasicEurocarbObject implements EurocarbObject
{
static Logger log = Logger.getLogger( BasicEurocarbObject.class );
/* getCanonicalId *//******************************************
*
* This default implementation returns
* <code>{@link getType()} + "_" + {@link getId()}</code>.
*/
public String getCanonicalId()
{
return getType() + "_" + getId();
}
/**
* {@inheritDoc}
*
* Currently a work in progress.
*
* @see Version
*/
public String getVersion()
{
if ( this instanceof Contributed )
{
Date d = ((Contributed) this).getDateEntered();
return date2version( d );
}
return "";
}
/* getId *//***************************************************
*<p>
* {@inheritDoc}
*</p>
*<p>
* Default implementation attempts to determine object id by
* reflection based on the class' name according to the basic
* convention that canonic id accessors are usually named
* <tt>'get' + <class-name> + 'Id'</tt>. This is sufficient
* for most basic data objects.
*</p>
*/
public int getId()
{
String method_name = "get" + this.getClass().getSimpleName() + "Id";
Throwable problem = null;
try
{
Method method = this.getClass().getMethod( method_name );
if ( method == null ) throw new NoSuchMethodException();
Object raw_id = method.invoke( this );
return (Integer) raw_id;
}
catch ( NoSuchMethodException no_method )
{
log.fatal( "Couldn't locate a method with name '"
+ method_name
+ "'"
);
problem = no_method;
}
catch ( SecurityException security_crap )
{
log.fatal( "Security exception raised while attempting to accessing "
+ "method with name '"
+ method_name
+ "'"
);
problem = security_crap;
}
catch ( Exception some_other_invocation_problem )
{
log.fatal( "Exception raised while invoking method '"
+ method_name
+ "'"
);
problem = some_other_invocation_problem;
}
throw new RuntimeException( problem );
}
/* getType *//*************************************************
*
* Returns this object's <em>type</em>. For example, "reference"
* for a Reference object, "biological_context" for a BiologicalContext
* object.
*
* @see #getCanonicalId()
* @see #getIdentifierClass()
* @see StringUtils#toUnderscoreCase(String)
*/
public String getType()
{
return StringUtils.toUnderscoreCase(
this.getIdentifierClass().getSimpleName() );
}
/**
*<p>
* {@inheritDoc}
*</p>
*<p>
* The default implementation returns the current class.
*</p>
*/
@SuppressWarnings("unchecked")
public <T extends EurocarbObject> Class<T> getIdentifierClass()
{
return (Class<T>) this.getClass();
}
/*
/-**
* Default implementation of object equality comparison for
* Eurocarb objects -- <em>sub-classes should provide their own
* implementation of this method as much as possible</em>. This default
* implementation uses the method {@link #getCanonicalId}
* to compare equality.
*-/
public boolean equals2( Object other )
{
if ( other == this )
return true;
if ( other == null )
return false;
if ( ! (other instanceof EurocarbObject) )
return false;
EurocarbObject that = (EurocarbObject) other;
if ( this.getCanonicalId() != that.getCanonicalId() )
return false;
return true;
}
public boolean equals( Object other )
{
return EqualsBuilder.reflectionEquals( this, other );
}
/-**
* Default implementation of object hashCode for
* Eurocarb objects -- <em>sub-classes should provide their own
* implementation of this method as necessary</em>. This default
* implementation uses the method {@link #getCanonicalId}
* to compute hashCode.
*-/
public int hashCode()
{
return this.getCanonicalId().hashCode();
}
*/
public String toString()
{
return "["
+ getIdentifierClass().getSimpleName()
+ "="
+ getId()
+ "]";
}
/**
* {@inheritDoc}
*
* The default implementation does nothing.
*/
public void validate() throws EurocarbException
{
/*
log.warn(
"Validate method for "
+ this.getClass()
+ " not yet implemented -- write one!" );
*/
// does nothing by default
}
} // end class