/*
* This file or a portion of this file is licensed under the terms of
* the Globus Toolkit Public License, found in file GTPL, or at
* http://www.globus.org/toolkit/download/license.html. This notice must
* appear in redistributions of this file, with or without modification.
*
* Redistributions of this Software, with or without modification, must
* reproduce the GTPL in: (1) the Software, or (2) the Documentation or
* some other similar material which is provided with the Software (if
* any).
*
* Copyright 1999-2004 University of Chicago and The University of
* Southern California. All rights reserved.
*/
package org.griphyn.vdl.directive;
import java.io.*;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.MissingResourceException;
import edu.isi.pegasus.common.util.Currently;
import org.griphyn.vdl.parser.*;
import org.griphyn.vdl.dbdriver.*;
import org.griphyn.vdl.dbschema.*;
import org.griphyn.vdl.classes.Definitions;
import org.griphyn.vdl.classes.Definition;
import org.griphyn.vdl.classes.Derivation;
import org.griphyn.vdl.util.Logging;
import org.xml.sax.InputSource;
/**
* This class parses VDL XML specifications and stores
* them to database backend.
*
* @author Jens-S. Vöckler
* @author Yong Zhao
* @version $Revision$
*
* @see org.griphyn.vdl.parser.VDLxParser
* @see org.griphyn.vdl.parser.DefinitionHandler
*/
public class Define extends Directive implements DefinitionHandler
{
/**
* This determines the behavior: insert mode (false) or update mode (true)
*/
private boolean m_overwrite;
/**
* This variable keeps the stream to print rejects onto, may be null.
*/
private Writer m_rejects = null;
/**
* Counts the number of successful database manipulations.
*/
private int m_count = 0;
/**
* Counts the rejected manipulations.
*/
private int m_rejected = 0;
/**
* database manipulator.
*/
private DatabaseSchema m_dbschema = null;
/**
* If enabled, collapses the names of DVs that were processed.
*/
private java.util.Set m_derivations = null;
/**
* Constructor
*/
public Define()
throws IOException, MissingResourceException
{
super();
}
/**
* Constructor, set database schema instance
* @param dbs the database schema instance
*/
public Define(DatabaseSchema dbs)
throws IOException, MissingResourceException
{
m_dbschema = dbs;
}
/**
* set database schema
* @param dbs the database schema instance
*/
public void setDatabaseSchema(DatabaseSchema dbs)
{
m_dbschema = dbs;
}
/**
* Closes the associated database backend and invalidates the schema.
*/
public void close()
throws SQLException
{
if ( m_dbschema != null ) m_dbschema.close();
m_dbschema = null;
}
/**
* Returns the remembered derivations.
*
* @return all remembered derivations, an empty set if none
* were found, or <code>null</code> if remembering was off.
* @see #setDerivationMemory( boolean )
*/
public Set getDerivationMemory()
{
return m_derivations;
}
/**
* Toggles the remembering of derivations that were processed.
*
* @param on is true to enable derivation memory
* @see #getDerivationMemory()
*/
public void setDerivationMemory( boolean on )
{
if ( on ) {
// enable remembering derivations
if ( m_derivations == null ) m_derivations = new java.util.HashSet();
} else {
// disable remembering derivations
m_derivations = null;
}
}
/**
* Insert definitions into database, if a definition already
* exists in the database, then it is rejected. This method
* does not keep track of rejected ones.
*
* @param reader the reader to vdlx source
* @return true if insersion is successful
*/
public boolean insertVDC(Reader reader)
{
return updateVDC(reader, null, false);
}
/**
* Insert definitions into database, if a definition already
* exists in the database, then it is rejected. This method
* keeps track of rejected ones.
*
* @param reader the reader to vdlx source
* @param writer writer to output the rejected definitions
* @return true if insersion is successful
*/
public boolean insertVDC(Reader reader, Writer writer)
{
return updateVDC(reader, writer, false);
}
/**
* Insert definitions into database, if a definition already
* exists in the database, then overwrite it. This method
* does not keep track of overwritten ones.
*
* @param reader the reader to vdlx source
* @return true if update is successful
*/
public boolean updateVDC(Reader reader)
{
return updateVDC(reader, null, true);
}
/**
* Insert definitions into database, if a definition already
* exists in the database, then overwrite it. This method
* keeps track of overwritten ones.
*
* @param reader the reader to vdlx source
* @param writer writer to output the overwritten definitions
* @return true if update is successful
*/
public boolean updateVDC(Reader reader, Writer writer)
{
return updateVDC(reader, writer, true);
}
/**
* Insert definitions into database, if a definition already
* exists in the database, then either update the definition or
* reject the definition.
*
* @param reader the reader to vdlx source
* @param writer writer to output the overwritten/rejected definitions
* @return true if update is successful
*/
public boolean updateVDC(Reader reader, Writer writer, boolean overwrite)
{
m_rejects = writer;
m_overwrite = overwrite;
m_count = m_rejected = 0;
org.griphyn.vdl.parser.VDLxParser parser =
new org.griphyn.vdl.parser.VDLxParser(m_props.getVDLSchemaLocation());
return parser.parse( new InputSource(reader), this );
}
/**
* This method implements the interface defined in DefinitionHandler
* to save definition to database backend.
*
* @param d is the Definition that is ready to be stored.
* @return true, if new version was stored and database modified,
* false, if the definition was rejected for any reason.
*/
public boolean store( Definition d )
{
boolean result = false;
VDC vdc = (VDC)m_dbschema;
// NEW: remember all DVs we came across
if ( m_derivations != null && d instanceof Derivation )
m_derivations.add( d.shortID() );
try {
if ( m_rejects == null ) {
// rely on saveDefinition to do "the right thing"
result = vdc.saveDefinition( d, m_overwrite );
} else {
// Is the Definition already in the database?
if ( vdc.containsDefinition(d) ) {
if ( m_overwrite ) {
// this is time-consuming and ineffective
Definition old = vdc.loadDefinition( d.getNamespace(),
d.getName(),
d.getVersion(),
d.getType() );
old.toXML( m_rejects, " " );
result = vdc.saveDefinition( d, true );
} else {
// skip, if not forced to overwrite, but save rejects
d.toXML( m_rejects, " " );
}
} else {
// not found, insert unconditionally
result = vdc.saveDefinition( d, true );
}
}
} catch ( SQLException sql ) {
// database problems
for ( int i=0; sql != null; ++i ) {
m_logger.log( "database", 0, "SQL error " + i + ": " +
sql.getErrorCode() + ": " + sql.getMessage() );
sql = sql.getNextException();
}
m_logger.log( "database", 0, "ignoring SQL exception(s)" );
} catch ( Exception e ) {
m_logger.log( "database", 0, "caught " + e + ", ignoring" );
result = false;
}
if ( result ) m_count++;
else m_rejected++;
return result;
}
/**
* return the number of successfully saved definitions
*/
public int getNumberSaved()
{
return m_count;
}
/**
* return the number of rejected definitions
*/
public int getNumberRejected()
{
return m_rejected;
}
}