/*
* Copyright 2012 Research Studios Austria Forschungsges.m.b.H.
*
* 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 won.protocol.model;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URI;
/**
* Encapsulates a jena model for storing it in a relational db.
*/
@Entity
@Table(name = "rdf_models")
public class ModelHolder
{
private static final int DEFAULT_BYTE_ARRAY_SIZE = 500;
@Transient
private final Logger logger = LoggerFactory.getLogger(getClass());
//the URI of the model
@Id
@Column( name = "modelURI", unique = true)
@Convert( converter = URIConverter.class)
private URI uri;
//the model as a byte array
@Lob @Column( name = "model", nullable = false, length = 100000)
private byte[] modelBytes;
//for multiple accesses to model, cache it.
@Transient
private Model cachedModel;
ModelHolder(){}
public ModelHolder(final URI uri, final Model model) {
this.uri = uri;
setModel(model);
this.cachedModel = model;
}
public URI getUri() {
return uri;
}
public void setUri(final URI uri) {
this.uri = uri;
}
byte[] getModelBytes() {
return modelBytes;
}
void setModelBytes(final byte[] modelBytes) {
this.modelBytes = modelBytes;
this.cachedModel = null;
}
/**
* Careful, expensive operation: writes model to string.
* @param model
*/
public void setModel(Model model) {
assert this.uri != null : "uri must not be null";
assert this.modelBytes != null : "model must not be null";
ByteArrayOutputStream out = new ByteArrayOutputStream(DEFAULT_BYTE_ARRAY_SIZE);
synchronized(this){
RDFDataMgr.write(out, model, Lang.TTL);
this.modelBytes = out.toByteArray();
if (logger.isDebugEnabled()){
logger.debug("wrote model {} to byte array of length {}", this.uri, this.modelBytes.length);
}
}
}
/**
* Careful, expensive operation: reads model from string.
* @return
*/
public Model getModel(){
assert this.uri != null : "uri must not be null";
assert this.modelBytes != null : "model must not be null";
if (this.cachedModel != null) return cachedModel;
synchronized (this) {
if (this.cachedModel != null) return cachedModel;
Model model = ModelFactory.createDefaultModel();
InputStream is = new ByteArrayInputStream(this.modelBytes);
try {
RDFDataMgr.read(model, is, this.uri.toString(), Lang.TTL);
} catch (Exception e) {
logger.warn("could not read model {} from byte array. Byte array is null: {}, has length {}",
new Object[]{this.uri,
this.modelBytes == null,
this.modelBytes == null ? -1 : this.modelBytes.length}
);
logger.warn("caught exception while reading model", e);
}
this.cachedModel = model;
return model;
}
}
}