/*
* 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.spss.support;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import org.obiba.magma.Attribute;
import org.obiba.magma.Category;
import org.obiba.magma.Value;
import org.obiba.magma.ValueType;
import org.obiba.magma.Variable;
import org.obiba.magma.VariableValueSource;
import org.obiba.magma.VariableValueSourceFactory;
import org.obiba.magma.datasource.spss.SpssVariableValueSource;
import org.obiba.magma.type.TextType;
import org.opendatafoundation.data.spss.SPSSFile;
import org.opendatafoundation.data.spss.SPSSFileException;
import org.opendatafoundation.data.spss.SPSSNumericVariable;
import org.opendatafoundation.data.spss.SPSSVariable;
import org.opendatafoundation.data.spss.SPSSVariableCategory;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import static org.obiba.magma.datasource.spss.support.CharacterSetValidator.validate;
public class SpssVariableValueSourceFactory implements VariableValueSourceFactory {
//
// Data members
//
@NotNull
private final SPSSFile spssFile;
@NotNull
private final String entityType;
@NotNull
private final String locale;
private final int idVariableIndex;
private final String occurrenceGroup;
private final Map<String, List<Integer>> identifierToVariableIndex;
/**
*
* @param spssFile
* @param identifierToVariableIndex
* @throws IOException
* @throws SPSSFileException
*/
public SpssVariableValueSourceFactory(@NotNull SPSSFile spssFile, @NotNull String entityType, @NotNull String locale, int idVariableIndex,
Map<String, List<Integer>> identifierToVariableIndex, String occurrenceGroup) {
this.spssFile = spssFile;
this.entityType = entityType;
this.locale = locale;
this.idVariableIndex = idVariableIndex;
this.identifierToVariableIndex = identifierToVariableIndex;
this.occurrenceGroup = occurrenceGroup;
}
@Override
public Set<VariableValueSource> createSources() {
Set<VariableValueSource> sources = Sets.newLinkedHashSet();
for(int i = 0; i < spssFile.getVariableCount(); i++) {
if (i != idVariableIndex) {
SPSSVariable spssVariable = spssFile.getVariable(i);
try {
sources.add(new SpssVariableValueSource(createVariableBuilder(i, spssVariable), spssVariable,
identifierToVariableIndex));
} catch(SpssInvalidCharacterException e) {
String variableName = spssVariable.getName();
// In the dictionary the first row is reserved for entity variable
int variableIndex = i + 1;
throw new SpssDatasourceParsingException("Failed to create variable.", "InvalidCharsetCharacter",
variableIndex, e.getSource()).metadataInfo(variableName, variableIndex).extraInfo(e);
}
}
}
return sources;
}
//
// Private methods
//
private void initializeCategories(SPSSVariable variable, Variable.Builder builder) throws SpssInvalidCharacterException {
if(variable.categoryMap != null) {
for(String category : variable.categoryMap.keySet()) {
SPSSVariableCategory spssCategory = variable.categoryMap.get(category);
validate(category);
validate(spssCategory.label);
builder.addCategory(Category.Builder.newCategory(category)
.addAttribute(addLabelAttribute(spssCategory.label))
.missing(isCategoryValueMissingCode(variable, spssCategory)).build());
}
}
}
private boolean isCategoryValueMissingCode(SPSSVariable spssVariable, SPSSVariableCategory spssCategory) {
if(spssVariable instanceof SPSSNumericVariable) {
return spssVariable.isMissingValueCode(spssCategory.value);
}
return spssVariable.isMissingValueCode(spssCategory.strValue);
}
@SuppressWarnings("ChainOfInstanceofChecks")
private Variable createVariableBuilder(int variableIndex, @NotNull SPSSVariable spssVariable)
throws SpssInvalidCharacterException {
String variableName = spssVariable.getName();
validate(variableName);
Variable.Builder builder = Variable.Builder.newVariable(variableName, TextType.get(), entityType);
builder.index(variableIndex);
addAttributes(builder, spssVariable);
addLabel(builder, spssVariable);
ValueType valueType = SpssVariableTypeMapper.map(spssVariable);
builder.type(valueType);
initializeCategories(spssVariable, builder);
if (!Strings.isNullOrEmpty(occurrenceGroup)) {
builder.repeatable();
builder.occurrenceGroup(occurrenceGroup);
}
return builder.build();
}
private void addLabel(@NotNull Variable.Builder builder, @NotNull SPSSVariable spssVariable)
throws SpssInvalidCharacterException {
String label = spssVariable.getLabel();
if(!Strings.isNullOrEmpty(label)) {
builder.addAttribute(addLabelAttribute(label));
}
}
private Attribute addLabelAttribute(String value) {
Attribute.Builder attributeBuilder = Attribute.Builder.newAttribute("label").withValue(value);
if(!Strings.isNullOrEmpty(locale)) {
attributeBuilder.withLocale(new Locale(locale));
}
return attributeBuilder.build();
}
private void addAttributes(Variable.Builder builder, @NotNull SPSSVariable spssVariable)
throws SpssInvalidCharacterException {
builder.addAttribute(createAttribute("measure", spssVariable.getMeasureLabel()))
.addAttribute(createAttribute("width", spssVariable.getLength()))
.addAttribute(createAttribute("decimals", spssVariable.getDecimals()))
.addAttribute(createAttribute("shortName", spssVariable.getShortName()))
.addAttribute(createAttribute("format", spssVariable.getSPSSFormat()));
}
private Attribute createAttribute(String attributeName, @Nullable String value) throws SpssInvalidCharacterException {
validate(value);
return Attribute.Builder.newAttribute(attributeName).withNamespace("spss").withValue(value).build();
}
private Attribute createAttribute(String attributeName, int value) throws SpssInvalidCharacterException {
return createAttribute(attributeName, String.valueOf(value));
}
}