/*
* Copyright (c) 2017 OBiBa. All rights reserved.
*
* This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.obiba.magma.datasource.hibernate.converter;
import java.io.Serializable;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.obiba.core.service.impl.hibernate.AssociationCriteria;
import org.obiba.magma.MagmaRuntimeException;
import org.obiba.magma.Value;
import org.obiba.magma.ValueLoader;
import org.obiba.magma.ValueLoaderFactory;
import org.obiba.magma.datasource.hibernate.domain.ValueSetBinaryValue;
import org.obiba.magma.datasource.hibernate.domain.ValueSetValue;
import org.obiba.magma.type.BinaryType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.obiba.core.service.impl.hibernate.AssociationCriteria.Operation;
/**
*
*/
public class HibernateValueLoaderFactory implements ValueLoaderFactory {
private final SessionFactory sessionFactory;
private final Serializable variableId;
private final Serializable valueSetId;
public HibernateValueLoaderFactory(SessionFactory sessionFactory, Serializable variableId, Serializable valueSetId) {
this.sessionFactory = sessionFactory;
this.variableId = variableId;
this.valueSetId = valueSetId;
}
public HibernateValueLoaderFactory(SessionFactory sessionFactory, ValueSetValue valueSetValue) {
this(sessionFactory, valueSetValue.getVariable().getId(), valueSetValue.getValueSet().getId());
}
@Override
public ValueLoader create(Value valueRef, @Nullable Integer occurrence) {
return new HibernateBinaryValueLoader(sessionFactory, variableId, valueSetId, occurrence, valueRef);
}
private static final class HibernateBinaryValueLoader implements ValueLoader {
private static final long serialVersionUID = -1878370804810810064L;
private static final Logger log = LoggerFactory.getLogger(HibernateBinaryValueLoader.class);
private final SessionFactory sessionFactory;
private final Serializable variableId;
private final Serializable valueSetId;
private final int occurrence;
@Nullable
private final Value valueRef;
private byte[] value;
private HibernateBinaryValueLoader(SessionFactory sessionFactory, Serializable variableId, Serializable valueSetId,
@Nullable Integer occurrence, @Nullable Value valueRef) {
this.sessionFactory = sessionFactory;
this.variableId = variableId;
this.valueSetId = valueSetId;
this.occurrence = occurrence == null ? 0 : occurrence;
this.valueRef = valueRef;
}
@Override
public boolean isNull() {
return valueRef == null || valueRef.isNull();
}
@NotNull
@Override
@SuppressWarnings("ConstantConditions")
@edu.umd.cs.findbugs.annotations.SuppressWarnings("NP_NULL_ON_SOME_PATH")
public Object getValue() {
if(value == null) {
if(BinaryType.get().equals(valueRef.getValueType())) {
log.trace("Loading binary from value_set_value table (Base64)");
value = valueRef.isNull() ? null : (byte[]) valueRef.getValue();
} else {
log.trace("Loading binary from value_set_binary_value table");
Session session = sessionFactory.getCurrentSession();
ValueSetBinaryValue binaryValue = (ValueSetBinaryValue) AssociationCriteria
.create(ValueSetBinaryValue.class, session) //
.add("variable.id", Operation.eq, variableId) //
.add("valueSet.id", Operation.eq, valueSetId) //
.add("occurrence", Operation.eq, occurrence) //
.getCriteria().uniqueResult();
if(binaryValue == null) {
throw new MagmaRuntimeException(
"Cannot find binary value for variable[" + variableId + "], valueSet[" + valueSetId +
"] and occurrence[" + occurrence + "]");
}
value = binaryValue.getValue();
session.evict(binaryValue); // remove binaries from session to avoid filling up memory
}
}
return value;
}
@Override
public long getLength() {
if(valueRef == null) return 0;
if(BinaryType.get().equals(valueRef.getValueType())) {
log.trace("Loading binary from value_set_value table (Base64)");
return valueRef.isNull() ? 0 : ((byte[]) valueRef.getValue()).length;
}
Query query = sessionFactory.getCurrentSession()
.createSQLQuery("SELECT binaryValue.size FROM value_set_binary_value binaryValue " + //
"WHERE binaryValue.variable_id = :variable_id " + //
"AND binaryValue.value_set_id = :value_set_id " + //
"AND binaryValue.occurrence = :occurrence") //
.setParameter("variable_id", variableId) //
.setParameter("value_set_id", valueSetId) //
.setParameter("occurrence", occurrence);
Integer result = (Integer) query.uniqueResult();
return result == null ? 0 : result.longValue();
}
}
}