/*
* Eoulsan development code
*
* This code may be freely distributed and modified under the
* terms of the GNU Lesser General Public License version 2.1 or
* later and CeCILL-C. This should be distributed with the code.
* If you do not have a copy, see:
*
* http://www.gnu.org/licenses/lgpl-2.1.txt
* http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt
*
* Copyright for this code is held jointly by the Genomic platform
* of the Institut de Biologie de l'École normale supérieure and
* the individual authors. These should be listed in @author doc
* comments.
*
* For more information on the Eoulsan project and its aims,
* or to join the Eoulsan Google group, visit the home page
* at:
*
* http://outils.genomique.biologie.ens.fr/eoulsan
*
*/
package fr.ens.biologie.genomique.eoulsan.core.workflow;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import fr.ens.biologie.genomique.eoulsan.data.DataMetadata;
import fr.ens.biologie.genomique.eoulsan.design.Design;
import fr.ens.biologie.genomique.eoulsan.design.Experiment;
import fr.ens.biologie.genomique.eoulsan.design.Sample;
/**
* This class define a simple class for metadata of data objects.
* @since 2.0
* @author Laurent Jourdren
*/
class SimpleDataMetadata extends AbstractDataMetadata implements Serializable {
private static final long serialVersionUID = -2905676240064559127L;
private final Design design;
private final Map<String, String> map = new HashMap<>();
private static final String STRING_TYPE = "value";
private static final String SAMPLE_NUMBER_TYPE = "design_sample_id";
private static final String SAMPLE_NAME_TYPE = "design_sample_name";
private static final String DESIGN_METADATA_TYPE = "design_metadata";
private static final String SAMPLE_METADATA_TYPE = "design_sample_metadata";
private static final String EXPERIMENT_METADATA_TYPE =
"design_experiment_sample_metadata";
private static final char SEPARATOR = ':';
/**
* Get the raw value of a metadata entry.
* @param key the key
* @return the raw entry if exists or null
*/
String getRaw(final String key) {
checkKey(key);
return this.map.get(key);
}
@Override
public String get(final String key) {
final String value = getRaw(key);
if (value == null) {
return null;
}
final String type = value.substring(0, value.indexOf(SEPARATOR));
switch (type) {
case STRING_TYPE:
return value.substring(type.length() + 1);
case SAMPLE_NAME_TYPE:
final String sampleId1 = value.substring(type.length() + 1);
try {
return this.design.getSample(sampleId1).getName();
} catch (IllegalArgumentException e) {
return null;
}
case SAMPLE_METADATA_TYPE:
final int endSampleId = value.indexOf(SEPARATOR, type.length() + 1);
final String sampleId2 = value.substring(type.length() + 1, endSampleId);
final String sampleMDKey = value.substring(endSampleId + 1);
try {
return this.design.getSample(sampleId2).getMetadata().get(sampleMDKey);
} catch (IllegalArgumentException e) {
return null;
}
case DESIGN_METADATA_TYPE:
final String designMDKey = value.substring(type.length() + 1);
try {
return this.design.getMetadata().get(designMDKey);
} catch (IllegalArgumentException e) {
return null;
}
default:
throw new IllegalStateException("Unknown metadata type: " + type);
}
}
/**
* Set the raw entry of a metadata.
* @param key the key
* @param value the raw value
*/
void setRaw(final String key, final String value) {
checkKey(key);
checkNotNull(value, "value argument cannot be null");
this.map.put(key, value);
}
@Override
public void set(final String key, final String value) {
checkNotNull(value, "value argument cannot be null");
setRaw(key, STRING_TYPE + SEPARATOR + value);
}
void setSampleName(final Sample sample) {
checkNotNull(sample, "sample argument cannot be null");
final String value = SAMPLE_NAME_TYPE + SEPARATOR + sample.getId();
setRaw(SAMPLE_NAME_KEY, value);
}
void setSampleNumber(final Sample sample) {
checkNotNull(sample, "sample argument cannot be null");
final String value = SAMPLE_NUMBER_TYPE + SEPARATOR + sample.getId();
setRaw(SAMPLE_NUMBER_KEY, value);
}
void setSampleMetadata(final Sample sample, final String key) {
checkNotNull(sample, "sample argument cannot be null");
checkNotNull(key, "key argument cannot be null");
checkArgument(sample.getMetadata().contains(key));
final String value =
SAMPLE_METADATA_TYPE + SEPARATOR + sample.getId() + SEPARATOR + key;
setRaw(key, value);
}
void setDesignMetadata(final Design design, final String key) {
checkNotNull(design, "sample argument cannot be null");
checkNotNull(key, "key argument cannot be null");
checkArgument(design.getMetadata().contains(key));
final String value = DESIGN_METADATA_TYPE + SEPARATOR + key;
setRaw(key, value);
}
void setExperimentMetadata(final Experiment experiment, final String key) {
checkNotNull(experiment, "sample argument cannot be null");
checkNotNull(key, "key argument cannot be null");
checkArgument(experiment.getMetadata().contains(key));
final String value = EXPERIMENT_METADATA_TYPE + SEPARATOR + key;
setRaw(key, value);
}
@Override
public boolean containsKey(final String key) {
checkKey(key);
return this.map.containsKey(key);
}
@Override
public boolean removeKey(final String key) {
checkKey(key);
this.map.remove(key);
return true;
}
@Override
public void set(final DataMetadata metadata) {
checkNotNull(metadata, "metadata argument cannot be null");
final SimpleDataMetadata md = WorkflowDataUtils.getSimpleMetadata(metadata);
if (md != null) {
// If metadata object is a SimpleDataMetaData do raw copy
for (Map.Entry<String, String> e : md.map.entrySet()) {
setRaw(e.getKey(), e.getValue());
}
} else {
// If not, do a standard copy
for (String key : metadata.keySet()) {
set(key, metadata.get(key));
}
}
}
@Override
public void clear() {
this.map.clear();
}
@Override
public Set<String> keySet() {
return this.map.keySet();
}
@Override
public String toString() {
return this.map.toString();
}
private void checkKey(final String key) {
checkNotNull(key, "key argument cannot be null");
for (int i = 0; i < key.length(); i++) {
if (key.charAt(i) < ' ') {
throw new IllegalArgumentException(
"Invalid metadata key character found: " + key.charAt(i));
}
}
}
//
// Constructor
//
/**
* Constructor.
*/
SimpleDataMetadata(final Design design) {
this.design = design;
}
}