/*
* 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.fs;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Map;
import java.util.Set;
import javax.validation.constraints.NotNull;
import org.obiba.magma.Disposable;
import org.obiba.magma.Initialisable;
import org.obiba.magma.MagmaRuntimeException;
import org.obiba.magma.VariableEntity;
import org.obiba.magma.datasource.fs.FsDatasource.InputCallback;
import org.obiba.magma.datasource.fs.FsDatasource.OutputCallback;
import org.obiba.magma.support.VariableEntityBean;
import org.obiba.magma.support.VariableEntityProvider;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
class FsVariableEntityProvider implements VariableEntityProvider, Initialisable, Disposable {
private static final String ENTITIES_NAME = "entities.xml";
private final FsValueTable valueTable;
private String entityType;
private final XStream xstream;
private final BiMap<VariableEntity, String> entityToFile = HashBiMap.create();
private boolean entityToFileMapModified = false;
/**
* Pads filenames with zeroes
*/
private final NumberFormat entryFilenameFormat = new DecimalFormat("0000000");
FsVariableEntityProvider(FsValueTable valueTable) {
this(valueTable, null);
}
FsVariableEntityProvider(FsValueTable valueTable, String entityType) {
this.valueTable = valueTable;
this.entityType = entityType;
xstream = valueTable.getDatasource().getXStreamInstance();
}
@Override
public void initialise() {
valueTable.readEntry(ENTITIES_NAME, new InputCallback<Void>() {
@Override
@SuppressWarnings("unchecked")
public Void readEntry(Reader reader) throws IOException {
try {
ObjectInputStream ois = xstream.createObjectInputStream(reader);
entityType = (String) ois.readObject();
Map<String, String> entries = (Map<String, String>) ois.readObject();
for(Map.Entry<String, String> entry : entries.entrySet()) {
entityToFile.put(new VariableEntityBean(entityType, entry.getKey()), entry.getValue());
}
} catch(ClassNotFoundException e) {
throw new MagmaRuntimeException(e);
}
return null;
}
});
}
@Override
public void dispose() {
if(entityToFileMapModified || !valueTable.getEntry(ENTITIES_NAME).exists()) {
valueTable.writeEntry(ENTITIES_NAME, new OutputCallback<Void>() {
@Override
public Void writeEntry(Writer writer) throws IOException {
try(ObjectOutputStream oos = xstream.createObjectOutputStream(writer, "entities")) {
oos.writeObject(entityType);
Map<String, String> entries = Maps.newHashMap();
for(Map.Entry<VariableEntity, String> entry : entityToFile.entrySet()) {
entries.put(entry.getKey().getIdentifier(), entry.getValue());
}
oos.writeObject(entries);
return null;
}
}
});
}
}
@NotNull
@Override
public String getEntityType() {
return entityType;
}
@NotNull
@Override
public Set<VariableEntity> getVariableEntities() {
return entityToFile.keySet();
}
@Override
public boolean isForEntityType(@SuppressWarnings("ParameterHidesMemberVariable") String entityType) {
return getEntityType().equals(entityType);
}
String addEntity(VariableEntity entity) {
if(!entityToFile.containsKey(entity)) {
entityToFile.put(entity, entryFilenameFormat.format(entityToFile.size() + 1) + ".xml");
entityToFileMapModified = true;
}
return getEntityFile(entity);
}
String getEntityFile(VariableEntity variableEntity) {
return entityToFile.get(variableEntity);
}
VariableEntity getEntityForFile(String filename) {
return entityToFile.inverse().get(filename);
}
}