diff --git a/ccm-core/src/main/java/org/libreccm/portation/AbstractMarshaller.java b/ccm-core/src/main/java/org/libreccm/portation/AbstractMarshaller.java index e0262551d..8f999c43d 100644 --- a/ccm-core/src/main/java/org/libreccm/portation/AbstractMarshaller.java +++ b/ccm-core/src/main/java/org/libreccm/portation/AbstractMarshaller.java @@ -18,13 +18,10 @@ */ package org.libreccm.portation; -import com.fasterxml.jackson.dataformat.csv.CsvMapper; -import com.fasterxml.jackson.dataformat.csv.CsvSchema; import org.apache.log4j.Logger; import org.libreccm.core.Identifiable; import java.io.File; -import java.io.IOException; import java.util.List; /** @@ -37,33 +34,30 @@ import java.util.List; * @author { } /** - * Main import method. Imports a list of string representing object of - * the same type ({@code T}) from a CSV-file and parses them into the - * corresponding objects. - * - * TODO: throw exception for ui - * TODO: error message not with uuid * * @return List of {@code T}-typed objects being imported */ - public List importEntities() { + public List importEntities() { switch (format) { case CSV: - /*List importObjects = new ArrayList<>(); - try { - mapper.readerFor(getClassT()).with(schema).readValues(file) - .forEachRemaining(t -> importObjects.add((T) t)); - } catch (IOException e) { - log.error(String.format("Error reading object with UUID %d from " + - "CSV-file with the name %s.", 1234, file.getName())); - } - return importObjects;*/ break; case JSON: @@ -162,29 +124,4 @@ public abstract class AbstractMarshaller { return null; } - /** - * Abstract method to get the class of the extending subclass fulfilling - * the generic type {@code T}. - * - * @return Class of the extending subclass. - */ - protected abstract Class getClassT(); - - /** - * Abstract method to get the CSV schema needed for both ex- and - * importation specific to every extending subclass. - * - * @return The CSV schema specific to the implementing subclass - */ - protected abstract CsvSchema getCsvSchema(); - - - /* JSON Export/Import */ - - - - /* XML Export/Import */ - - - } diff --git a/ccm-core/src/main/java/org/libreccm/portation/Marshaller.java b/ccm-core/src/main/java/org/libreccm/portation/Marshaller.java index 514925acc..29ec9a98c 100644 --- a/ccm-core/src/main/java/org/libreccm/portation/Marshaller.java +++ b/ccm-core/src/main/java/org/libreccm/portation/Marshaller.java @@ -27,12 +27,15 @@ import javax.faces.bean.RequestScoped; import javax.inject.Inject; import java.util.ArrayList; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; -import java.util.stream.Collectors; +import java.util.Map; /** + * Central class for exporting and importing objects of this system stored in + * the database. Retrieves all available implementations of + * {@link AbstractMarshaller} using CDI. The implementations have to be CDI + * beans of course. Also they must be annotated with the {@link Marshals} + * annotation. * * @author Tobias Osmers * @version created the 03.02.2016 @@ -45,72 +48,95 @@ public class Marshaller { private Instance> marshallerInstances; + // Assigns lists with objects of the same type as values to their typ as + // key. + private Map, List> classListMap; + /** + * Main export method. Organizes the objects into list of the same type + * and calls a second export method for each list. * - * @param objects - * @param format - * @param filename + * @param objects All objects to be exported + * @param format The export style/format e.g. CSV or JSON + * @param filename The name of the file to be exported to */ - @SuppressWarnings("unchecked") - public void exportObjects(List objects, Format format, String filename) { + public void exportObjects(List objects, Format format, + String filename) { + putObjects(objects); - List> objectsByClass = new ArrayList<>(); - Queue> queue = new LinkedList<>(); - - // Splits list of all entities into lists of the same entity class - while (!objects.isEmpty()) { - Class clazz = objects.get(0).getClass(); - objectsByClass.add(objects.stream() - .filter(t -> t.getClass() == clazz) - .collect(Collectors.toList())); - queue.add(clazz); - } - - // Exports list of the same class - for (List objectList : objectsByClass) { - final Instance> - marshallerInstance = marshallerInstances.select(new - MarshalsLiteral(queue.peek())); - - if (marshallerInstance.isUnsatisfied()) { - // If there are no marshals we have a problem... - throw new IllegalArgumentException(String.format("No " + - "marshaller for \"%s\" found.", queue.peek() - .getName())); - } else if (marshallerInstance.isAmbiguous()) { - // If there is more than one marshaller something is wrong... - throw new IllegalArgumentException(String.format("More than " + - "one marshaller for \"%s\" found.", queue.peek() - .getName())); - } else { - // Gets the marshaller and calls the export method - final Iterator> it = - marshallerInstance.iterator(); - - AbstractMarshaller marshaller = it - .next(); - marshaller.init(format, filename); - marshaller.exportEntities(objectList); - } - queue.remove(); + for (Map.Entry, List> + classListEntry : classListMap.entrySet()) { + exportList( classListEntry.getValue(), classListEntry.getKey(), + format, filename); } } - private List getListForClass(List objList, Class objClass) { - - return null; - //objList.stream().filter(obj -> obj.getClass() == objClass) - // .collect(Collectors.toList()); - } - - - - /** + * Organizes a list of different {@link Identifiable} objects into a map + * assigning lists of the same type to their type as values to a key. The + * type which all objects of that list have in common is their key. + * That opens the possibility of being certain of the objects types in + * the list. Guarantied through this implementation. * + * @param objects list of all objects being organized + */ + private void putObjects(List objects) { + for (Identifiable object : objects) { + Class type = object.getClass(); + + if (classListMap.containsKey(type)) { + classListMap.get(type).add(object); + } else { + List values = new ArrayList<>(); + values.add(object); + classListMap.put(type, values); + } + } + } + + /** + * Selects the right marshaller for the given type, initializes that + * marshaller for the given export wishes and calls the export method of + * that marshaller upon the given list of same typed objects. + * + * @param list List of objects to be exported of the same type + * @param type The class of the type + * @param format The export style + * @param filename The filename + * @param The type + */ + private void exportList(List list, Class type, Format format, String filename) { + + final Instance> + marshallerInstance = marshallerInstances.select(new + MarshalsLiteral(type)); + + if (marshallerInstance.isUnsatisfied()) { + //If there are no marshallers we have a problem... + throw new IllegalArgumentException(String.format( + "No marshallers for \"%s\" found.", type.getName())); + } else if (marshallerInstance.isAmbiguous()) { + //If there is more than one marshaller something is wrong... + throw new IllegalArgumentException(String.format( + "More than one marshaller for \"%s\" found.", type + .getName())); + } else { + // Get the marshaller for this list and call the export method. + final Iterator> + iterator = marshallerInstance.iterator(); + @SuppressWarnings("unchecked") + final AbstractMarshaller marshaller = (AbstractMarshaller) + iterator.next(); + + marshaller.init(format, filename); + marshaller.exportEntities(list); + } + } + + /** + * {@link AnnotationLiteral} used for filtering the available marshallers. */ private class MarshalsLiteral extends AnnotationLiteral implements Marshals { diff --git a/ccm-core/src/main/java/org/libreccm/portation/Marshals.java b/ccm-core/src/main/java/org/libreccm/portation/Marshals.java index 115df83a1..636c78a0c 100644 --- a/ccm-core/src/main/java/org/libreccm/portation/Marshals.java +++ b/ccm-core/src/main/java/org/libreccm/portation/Marshals.java @@ -27,7 +27,9 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * + * Qualifier annotation for implementations of {@link AbstractMarshaller}. The + * value is the implementation of {@link Identifiable} for which the annotated + * {@link AbstractMarshaller} implementation exports and imports its instances. * * @author