package services.export;
import helpers.JsonLdConstants;
import models.Record;
import models.Resource;
import models.ResourceList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeSet;
public class CsvWithNestedIdsExporter implements AbstractCsvExporter {
private TreeSet<String> mKeys = new TreeSet<>();
private String[] mValues = new String[0];
private List<String> mDropFields = new ArrayList<>();
@Override
public String export(ResourceList aResourceList){
StringBuffer result = new StringBuffer();
List<Resource> resources = new ArrayList<>();
for (Resource record : aResourceList.getItems()) {
resources.add(record.getAsResource(Record.RESOURCE_KEY));
}
defineHeaderColumns(resources);
setDropFields(Arrays.asList(JsonLdConstants.TYPE));
result.append(headerKeysToCsvString().concat("\n"));
for (Resource resource : resources) {
result.append(buildRow(resource).concat("\n"));
}
return result.toString();
}
@Override
public String export(Resource aResource) {
StringBuffer result = new StringBuffer();
Resource resource = aResource.getAsResource(Record.RESOURCE_KEY);
defineHeaderColumns(Arrays.asList(resource));
setDropFields(Arrays.asList(JsonLdConstants.TYPE));
result.append(headerKeysToCsvString().concat("\n"));
result.append(buildRow(resource).concat("\n"));
return result.toString();
}
private String buildRow(Resource aResource) {
if (mKeys.isEmpty()) {
throw new IllegalStateException(
"Trying to export Resource as CSV before having headers been set up: \n" + aResource);
} //
else {
mValues = new String[mKeys.size()];
Iterator<Entry<String, Object>> it = aResource.entrySet().iterator();
while (it.hasNext()) {
flattenResourceElement(it.next());
}
return fieldValuesToCsvString(mValues);
}
}
private void flattenResourceElement(Entry<String, Object> aResourceEntry) {
Object value = aResourceEntry.getValue();
int index = getIndexInHeader(aResourceEntry.getKey());
if (index == -1) {
throw new IllegalStateException(
"Trying to export Resource entry but key not found in header: \n" + aResourceEntry);
} //
else {
if (value instanceof List<?>) {
ArrayList<?> values = (ArrayList<?>) value;
if (!values.isEmpty()) {
StringBuffer valueList = new StringBuffer(toExportString(values.get(0)));
for (int i = 1; i < values.size(); i++) {
valueList.append(", ").append(toExportString(values.get(i)));
}
mValues[index] = valueList.toString();
}
} //
else {
mValues[index] = toExportString(value);
}
}
}
private String toExportString(Object value) {
StringBuilder result = new StringBuilder();
if (value instanceof Resource) {
Resource resource = (Resource) value;
if (resource.get(JsonLdConstants.ID) != null) {
String id = resource.get(JsonLdConstants.ID).toString();
// only export IDs of nested Resources
result.append(id.toString());
} //
else {
// Resource without ID (e. g. "location"): export all sub fields flatly
// The order of exported subfields is not predicted as sub Resources do
// not necessarily contain the same fields.
result.append(((Resource) value).getValuesAsFlatString(",", mDropFields));
}
} //
else {
result.append(value.toString());
}
return result.toString();
}
@Override
public void defineHeaderColumns(List<Resource> aResourceList) {
mKeys.clear();
for (Resource resource : aResourceList) {
Iterator<Entry<String, Object>> it = resource.entrySet().iterator();
while (it.hasNext()) {
flattenKeys(it.next());
}
}
}
private void flattenKeys(Entry<String, Object> aResourceEntry) {
mKeys.add(aResourceEntry.getKey());
}
private int getIndexInHeader(String aFieldName) {
return mKeys.contains(aFieldName) ? mKeys.headSet(aFieldName).size() : -1;
}
@Override
public String headerKeysToCsvString() {
TreeSet<String> keys = new TreeSet<>();
keys.addAll(mKeys);
StringBuffer header = new StringBuffer("");
if (keys.size() > 0) {
header.append(keys.pollFirst());
}
while (!keys.isEmpty()) {
header.append(";").append(keys.pollFirst());
}
return header.toString();
}
@Override
public void setDropFields(List<String> aDropFields) {
mDropFields.clear();
mDropFields.addAll(aDropFields);
}
}