// BridgeDb,
// An abstraction layer for identifier mapping services, both local and online.
// Copyright 2006-2009 BridgeDb developers
//
// 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 org.bridgedb.rdb;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bridgedb.IDMapperException;
import org.bridgedb.Xref;
/** {@inheritDoc} */
class SimpleGdbImpl2 extends SimpleGdbImplCommon
{
private static final int GDB_COMPAT_VERSION = 2; //Preferred schema version
private final SimpleGdb.QueryLifeCycle qBackpage = new SimpleGdb.QueryLifeCycle(
"SELECT backpageText FROM datanode " +
" WHERE id = ? AND code = ?"
);
/**
* get Backpage info. In Schema v2, this was not stored in
* the attribute table but as a separate column, so this is treated
* as a special case. This method is called by <pre>getAttribute (ref, "Backpage")</pre>
* @param ref the entity to get backpage info for.
* @return Backpage info as string
* @throws IDMapperException when database is unavailable
*/
private String getBpInfo(Xref ref) throws IDMapperException
{
final QueryLifeCycle pst = qBackpage;
synchronized (pst)
{
try {
pst.init();
pst.setString (1, ref.getId());
pst.setString (2, ref.getDataSource().getSystemCode());
ResultSet r = pst.executeQuery();
String result = null;
if (r.next())
{
result = r.getString(1);
}
return result;
} catch (SQLException e) { throw new IDMapperException (e); } //Gene not found
finally {pst.cleanup(); }
}
}
/**
* Opens a connection to the Gene Database located in the given file.
* A new instance of this class is created automatically.
* @param dbName The file containing the Gene Database.
* @param con An existing SQL Connector.
* @param props PROP_RECREATE if you want to create a new database (possibly overwriting an existing one)
* or PROP_NONE if you want to connect read-only
* @throws IDMapperException when the database could not be created or connected to
*/
public SimpleGdbImpl2(String dbName, String connectionString) throws IDMapperException
{
super (dbName, connectionString);
if(dbName == null) throw new NullPointerException();
checkSchemaVersion();
}
/**
* look at the info table of the current database to determine the schema version.
* @throws IDMapperException when looking up the schema version failed
*/
private void checkSchemaVersion() throws IDMapperException
{
int version = 0;
try
{
ResultSet r = getConnection().createStatement().executeQuery("SELECT schemaversion FROM info");
if(r.next()) version = r.getInt(1);
}
catch (SQLException e)
{
//Ignore, older db's don't even have schema version
}
if(version != GDB_COMPAT_VERSION)
{
throw new IDMapperException ("Implementation and schema version mismatch");
}
}
private static final Map<String, String> ATTRIBUTES_FROM_BACKPAGE;
static
{
ATTRIBUTES_FROM_BACKPAGE = new HashMap<String, String>();
ATTRIBUTES_FROM_BACKPAGE.put ("Chromosome", "<TH>Chr:<TH>([^<]*)<");
ATTRIBUTES_FROM_BACKPAGE.put ("Description", "<TH>Description:<TH>([^<]*)<");
ATTRIBUTES_FROM_BACKPAGE.put ("Synonyms", "<TH>Synonyms:<TH>([^<]*)<");
ATTRIBUTES_FROM_BACKPAGE.put ("Symbol", "<TH>(?:Gene Symbol|Metabolite):<TH>([^<]*)<");
ATTRIBUTES_FROM_BACKPAGE.put ("BrutoFormula", "<TH>Bruto Formula:<TH>([^<]*)<");
}
/** {@inheritDoc} */
public Set<String> getAttributes(Xref ref, String attrname)
throws IDMapperException
{
Set<String> result = new HashSet<String>();
final QueryLifeCycle pst = qAttribute;
if (ATTRIBUTES_FROM_BACKPAGE.containsKey(attrname))
{
String bpInfo = getBpInfo(ref);
if (bpInfo != null)
{
Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get (attrname));
Matcher matcher = pat.matcher(bpInfo);
if (matcher.find())
{
result.add (matcher.group(1));
}
}
}
synchronized (pst)
{
try {
pst.init();
pst.setString (1, ref.getId());
pst.setString (2, ref.getDataSource().getSystemCode());
pst.setString (3, attrname);
ResultSet r = pst.executeQuery();
if (r.next())
{
result.add (r.getString(1));
}
return result;
} catch (SQLException e) { throw new IDMapperException ("Xref:" + ref + ", Attribute: " + attrname, e); } // Database unavailable
finally {pst.cleanup(); }
}
}
/** {@inheritDoc} */
public Map<String, Set<String>> getAttributes(Xref ref)
throws IDMapperException
{
Map<String, Set<String>> result = new HashMap<String, Set<String>>();
final QueryLifeCycle pst = qAllAttributes;
String bpInfo = getBpInfo(ref);
if (bpInfo != null)
{
for (String attrname : ATTRIBUTES_FROM_BACKPAGE.keySet())
{
Pattern pat = Pattern.compile(ATTRIBUTES_FROM_BACKPAGE.get (attrname));
Matcher matcher = pat.matcher(bpInfo);
if (matcher.find())
{
Set<String> attrSet = new HashSet<String>();
attrSet.add (matcher.group(1));
result.put (attrname, attrSet);
}
}
}
synchronized (pst)
{
try {
pst.init();
pst.setString (1, ref.getId());
pst.setString (2, ref.getDataSource().getSystemCode());
ResultSet r = pst.executeQuery();
if (r.next())
{
String key = r.getString(1);
String value = r.getString(2);
if (result.containsKey (key))
{
result.get(key).add (value);
}
else
{
Set<String> valueSet = new HashSet<String>();
valueSet.add (value);
result.put (key, valueSet);
}
}
return result;
} catch (SQLException e) { throw new IDMapperException ("Xref:" + ref, e); } // Database unavailable
finally {pst.cleanup(); }
}
}
}