package services.export; import helpers.JsonLdConstants; 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 CsvDetailedExporter implements AbstractCsvExporter { private static String mPathSeparator = ">"; 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(); defineHeaderColumns(aResourceList.getItems()); setDropFields(Arrays.asList(JsonLdConstants.TYPE)); result.append(headerKeysToCsvString().concat("\n")); for (Resource resource : aResourceList.getItems()) { result.append(export(resource).concat("\n")); } return result.toString(); } @Override public String export(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, String aKeyPath) { if (aResourceEntry.getValue() instanceof String) { int index = getIndexInHeader(aKeyPath + aResourceEntry.getKey()); if (index == -1) { throw new IllegalStateException( "Trying to export Resource entry but key not found in header: \n" + aResourceEntry); } else { mValues[index] = (String) aResourceEntry.getValue(); } } // else if (aResourceEntry.getValue() instanceof Resource) { Iterator<Entry<String, Object>> it = ((Resource) aResourceEntry.getValue()).entrySet() .iterator(); while (it.hasNext()) { flattenResourceElement(it.next(), aKeyPath + aResourceEntry.getKey() + mPathSeparator); } } // else if (aResourceEntry.getValue() instanceof List<?>) { ArrayList<?> values = (ArrayList<?>) aResourceEntry.getValue(); for (int i = 0; i < values.size(); i++) { Object value = values.get(i); if (value instanceof Resource) { Iterator<Entry<String, Object>> it = ((Resource) value).entrySet().iterator(); while (it.hasNext()) { flattenResourceElement(it.next(), aKeyPath + aResourceEntry.getKey() + mPathSeparator + i + mPathSeparator); } } // else if (value instanceof String) { int index = getIndexInHeader(aKeyPath + aResourceEntry.getKey() + mPathSeparator + i); if (index == -1) { throw new IllegalStateException( "Trying to export List in Resource entry but key not found in header: \n" + values); } else { mValues[index] = (String) value; } } } } } 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, String aKeyPath) { if (aResourceEntry.getValue() instanceof String) { mKeys.add(aKeyPath + aResourceEntry.getKey()); } // else if (aResourceEntry.getValue() instanceof Resource) { Iterator<Entry<String, Object>> it = ((Resource) aResourceEntry.getValue()).entrySet() .iterator(); while (it.hasNext()) { flattenKeys(it.next(), aKeyPath + aResourceEntry.getKey() + mPathSeparator); } } // else if (aResourceEntry.getValue() instanceof List<?>) { ArrayList<?> values = (ArrayList<?>) aResourceEntry.getValue(); for (int i = 0; i < values.size(); i++) { Object value = values.get(i); if (value instanceof Resource) { Iterator<Entry<String, Object>> it = ((Resource) value).entrySet().iterator(); while (it.hasNext()) { flattenKeys(it.next(), aKeyPath + aResourceEntry.getKey() + mPathSeparator + i + mPathSeparator); } } else if (value instanceof String) { mKeys.add(aKeyPath + aResourceEntry.getKey() + mPathSeparator + i); } } } } private int getIndexInHeader(String aFieldName) { return mKeys.contains(aFieldName) ? mKeys.headSet(aFieldName).size() : -1; } public String headerKeysToCsvString() { StringBuffer header = new StringBuffer(""); for (String key : mKeys) { header.append(key); if (mKeys.tailSet(key).size() > 0) { header.append(";"); } } return header.toString(); } @Override public void setDropFields(List<String> aDropFields) { mDropFields.clear(); mDropFields.addAll(aDropFields); } }