/*
* 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.js.views;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.obiba.magma.Initialisable;
import org.obiba.magma.MagmaRuntimeException;
import org.obiba.magma.NoSuchVariableException;
import org.obiba.magma.ValueTable;
import org.obiba.magma.ValueTableWriter.VariableWriter;
import org.obiba.magma.Variable;
import org.obiba.magma.VariableValueSource;
import org.obiba.magma.js.JavascriptVariableValueSourceFactory;
import org.obiba.magma.support.Initialisables;
import org.obiba.magma.views.ListClause;
/**
* This implementation of {@link ListClause} will contain {@link Variable}s with a "script" attribute and/or a "sameAs"
* attribute used to provide new custom variables derived from existing variables. Before use the initialise method must
* be called to compile the JavaScript necessary to return the values of the derived variables.
*/
public class VariablesClause implements ListClause, Initialisable {
private Set<Variable> variables = new LinkedHashSet<>();
@SuppressWarnings("TransientFieldInNonSerializableClass")
private transient ValueTable valueTable;
@SuppressWarnings("TransientFieldInNonSerializableClass")
private transient Set<VariableValueSource> variableValueSources;
@SuppressWarnings("TransientFieldInNonSerializableClass")
private transient boolean initialised = false;
public void setVariables(Collection<Variable> variables) {
this.variables.clear();
if(variables != null) {
this.variables.addAll(variables);
}
}
@NotNull
@Override
public VariableValueSource getVariableValueSource(String name) throws NoSuchVariableException {
if(!initialised) {
throw new IllegalStateException("The initialise() method must be called before getVariableValueSource().");
}
for(VariableValueSource variableValueSource : variableValueSources) {
if(variableValueSource.getVariable().getName().equals(name)) {
return variableValueSource;
}
}
throw new NoSuchVariableException(name);
}
@Override
public Iterable<VariableValueSource> getVariableValueSources() {
if(!initialised) {
throw new IllegalStateException("The initialise() method must be called before getVariableValueSources().");
}
return variableValueSources;
}
@Override
public void initialise() {
if(valueTable == null) {
throw new IllegalStateException("The setValueTable() method must be called before initialise().");
}
JavascriptVariableValueSourceFactory factory = new JavascriptVariableValueSourceFactory();
factory.setVariables(variables);
factory.setValueTable(valueTable);
variableValueSources = factory.createSources();
for(VariableValueSource vvs : variableValueSources) {
try {
Initialisables.initialise(vvs);
} catch(MagmaRuntimeException ignored) {
}
}
initialised = true;
}
@Override
public void setValueTable(@NotNull ValueTable valueTable) {
//noinspection ConstantConditions
if(valueTable == null) throw new IllegalArgumentException("valueTable cannot be null");
this.valueTable = valueTable;
}
@Override
public VariableWriter createWriter() {
return new JsVariableWriter();
}
private class JsVariableWriter implements VariableWriter {
@Override
public void writeVariable(@NotNull Variable variable) {
// update or add variable
Set<Variable> variableSet = new LinkedHashSet<>();
boolean updated = false;
for(Variable var : variables) {
if(var.getName().equals(variable.getName())) {
variableSet.add(variable);
updated = true;
} else {
variableSet.add(var);
}
}
if(!updated) {
variableSet.add(variable);
}
variables = variableSet;
}
@Override
public void removeVariable(@NotNull Variable variable) {
// update or add variable
Set<Variable> variableSet = new LinkedHashSet<>();
for(Variable var : variables) {
if(!var.getName().equals(variable.getName())) {
variableSet.add(var);
}
}
variables = variableSet;
}
@Override
public void close() {
}
}
}