org.apache.jena.sdb.graph.PrefixMappingSDB Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-sdb Show documentation
Show all versions of jena-sdb Show documentation
SDB is a persistence layer for use with Apache Jena that uses an SQL database to store triples/quads.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jena.sdb.graph;
import static java.lang.String.format;
import static org.apache.jena.sdb.sql.SQLUtils.quoteStr ;
import static org.apache.jena.sdb.sql.SQLUtils.sqlStr ;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.jena.sdb.sql.RS ;
import org.apache.jena.sdb.sql.ResultSetJDBC ;
import org.apache.jena.sdb.sql.SDBConnection ;
import org.apache.jena.sdb.sql.SDBExceptionSQL ;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.shared.impl.PrefixMappingImpl ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** A prefix mapping that is backed by a database table
*/
public class PrefixMappingSDB extends PrefixMappingImpl
{
// Use DatasetPrefixStorage as move to Per-graph prefix mappings. (schema change)
// See PrefixMappingPersistent
static private Logger log = LoggerFactory.getLogger(PrefixMappingSDB.class) ;
static public final String prefixTableName = "Prefixes" ;
static public final int prefixColWidth = 50 ; // Minimum
static public final int uriColWidth = 500 ; // Minimum
// TODO Per-graph prefix mappings.
// TODO: Encode capital letters in prefix names.
// new design needed : safe failures of other updates.
// We are an in-memory prefix mapping except the update operations
// are also applied to the table.
/* Roughly:
CREATE TABLE Prefixes (,
-- Each column should be:
-- Case sensitive, UTF8 characters, not NULL
-- MySQL: BINARY CHARACTER SET utf8 NOT NULL default '',",
prefix VARCHAR ,
uri TEXT or VARCHAR ,
PRIMARY KEY (prefix) ,
)
*/
private SDBConnection connection = null ;
private String graphName ;
public PrefixMappingSDB(String graphURI, SDBConnection sdb)
{
super() ;
graphName = graphURI ;
connection = sdb ;
readPrefixMapping() ;
}
@Override
protected void set(String prefix, String uri)
{
// Delete old one if present.
String x = get(prefix) ;
if ( x != null )
{
if(x.equals(uri))
// Already there - no-op (thanks to Eric Diaz for pointing this out)
return;
removeFromPrefixMap(prefix, x) ;
}
// Persist
insertIntoPrefixMap(prefix, uri) ;
// Set caches
super.set(prefix, uri) ;
}
@Override
protected String get(String prefix)
{
String x = super.get(prefix) ;
if ( x != null )
return x ;
x = readFromPrefixMap(prefix) ;
return x ;
}
@Override
public PrefixMapping removeNsPrefix(String prefix)
{
String uri = super.getNsPrefixURI(prefix) ;
if ( uri != null )
removeFromPrefixMap(prefix, uri) ;
super.removeNsPrefix(prefix) ;
return this ;
}
// Super class implementation loops and calls setNsPrefix calls set() for each entry.
//@Override
//public PrefixMapping setNsPrefixes(PrefixMapping arg0)
// Super class implementation will suffice.
// It (creates a map copy and) loops on each entry.
//@Override
//public PrefixMapping setNsPrefixes(Map arg0)
// -------- Worker implementations
private void readPrefixMapping()
{
ResultSetJDBC rsx = null ;
try {
String sqlStmt = "SELECT prefix, uri FROM "+prefixTableName ;
rsx = connection.execSilent(sqlStmt) ;
if ( rsx == null || rsx.get() == null )
return ;
ResultSet rs = rsx.get() ;
while(rs.next())
{
String p = rs.getString("prefix") ;
p = decode(p) ;
String v = rs.getString("uri") ;
// Load in-memory copy.
super.set(p, v) ;
}
} catch (SQLException ex)
{ throw new SDBExceptionSQL("Failed to get prefixes", ex) ; }
finally
{
RS.close(rsx) ;
}
}
private String readFromPrefixMap(String prefix)
{
ResultSetJDBC rsx = null ;
try {
String sqlStmt = sqlStr(
"SELECT uri FROM "+prefixTableName,
" WHERE prefix = "+quoteStr(prefix)
) ;
rsx = connection.execQuery(sqlStmt) ;
ResultSet rs = rsx.get() ;
String uri = null ;
while(rs.next())
{
String v = rs.getString("uri") ;
uri = v ;
if ( rs.next() )
log.warn("Multiple prefix mappings for '"+prefix+"'") ;
break ;
}
return uri ;
} catch (SQLException ex)
{ throw new SDBExceptionSQL(format("Failed to read prefix (%s)", prefix), ex) ; }
finally { RS.close(rsx) ; }
}
private void insertIntoPrefixMap(String prefix, String uri)
{
// Only called from set()
// Assumes not present in the persistent table.
try {
prefix = encode(prefix) ;
String sqlStmt = sqlStr(
"INSERT INTO "+prefixTableName,
" VALUES ("+quoteStr(prefix)+", "+quoteStr(uri)+")"
) ;
connection.execUpdate(sqlStmt) ;
} catch (SQLException ex)
{
throw new SDBExceptionSQL(format("Failed to set prefix (%s,%s)", prefix, uri), ex) ;
}
}
private void removeFromPrefixMap(String prefix, String uri)
{
try {
prefix = encode(prefix) ;
String sqlStmt = sqlStr(
"DELETE FROM "+prefixTableName+" WHERE",
" prefix = "+quoteStr(prefix) //+" AND uri = "+quote(uri)
) ;
connection.execUpdate(sqlStmt) ;
} catch (SQLException ex)
{ throw new SDBExceptionSQL(format("Failed to remove prefix (%s,%s)", prefix, uri), ex) ; }
}
// Always put in a trailing ":" so the prefix is never the empty string
// which is null on Oracle but the prefix is a primary key and can't be null.
private String encode(String prefix)
{ return prefix+":" ; }
private String decode(String prefix)
{ return prefix.substring(0, prefix.length()-1) ; }
}