package edu.harvard.iq.dataverse.util; import edu.harvard.iq.dataverse.ControlledVocabularyValue; import edu.harvard.iq.dataverse.DatasetField; import edu.harvard.iq.dataverse.DatasetFieldCompoundValue; import edu.harvard.iq.dataverse.DatasetFieldType; import edu.harvard.iq.dataverse.DatasetFieldValue; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; /** * A means of iterating over {@link DatasetField}s, or a collection of them. * As these may have a complex structure (compound values, etc), this object * allows processing them via an event stream, similar to SAX parsing of XML. * Visiting of the fields is done in display order. * * @author michael */ public class DatasetFieldWalker { public interface Listener { void startField( DatasetField f ); void endField( DatasetField f ); void primitiveValue( DatasetFieldValue dsfv ); void controledVocabularyValue( ControlledVocabularyValue cvv ); void startCompoundValue( DatasetFieldCompoundValue dsfcv ); void endCompoundValue( DatasetFieldCompoundValue dsfcv ); } /** * Convenience method to walk over a field. * @param dsf the field to walk over. * @param l the listener to execute on {@code dsf}'s values and structure. */ public static void walk( DatasetField dsf, Listener l ) { DatasetFieldWalker joe = new DatasetFieldWalker(l); joe.walk(dsf); } /** * Convenience method to walk over a list of fields. Traversal * is done in display order. * @param fields the fields to go over. Does not have to be sorted. * @param l the listener to execute on each field values and structure. */ public static void walk( List<DatasetField> fields, Listener l ) { DatasetFieldWalker joe = new DatasetFieldWalker(l); for ( DatasetField dsf : sort( fields, DatasetField.DisplayOrder) ) { joe.walk(dsf); } } private Listener l; public DatasetFieldWalker(Listener l) { this.l = l; } public DatasetFieldWalker(){ this( null ); } public void walk( DatasetField fld ) { l.startField(fld); DatasetFieldType datasetFieldType = fld.getDatasetFieldType(); if ( datasetFieldType.isControlledVocabulary() ) { for ( ControlledVocabularyValue cvv : sort(fld.getControlledVocabularyValues(), ControlledVocabularyValue.DisplayOrder) ) { l.controledVocabularyValue(cvv); } } else if ( datasetFieldType.isPrimitive() ) { for ( DatasetFieldValue pv : sort(fld.getDatasetFieldValues(), DatasetFieldValue.DisplayOrder) ) { l.primitiveValue( pv ); } } else if ( datasetFieldType.isCompound() ) { for ( DatasetFieldCompoundValue dsfcv : sort( fld.getDatasetFieldCompoundValues(), DatasetFieldCompoundValue.DisplayOrder) ) { l.startCompoundValue(dsfcv); for ( DatasetField dsf : sort(dsfcv.getChildDatasetFields(), DatasetField.DisplayOrder ) ) { walk( dsf ); } l.endCompoundValue(dsfcv); } } l.endField(fld); } public void setL(Listener l) { this.l = l; } static private <T> Iterable<T> sort( List<T> list, Comparator<T> cmp ) { ArrayList<T> tbs = new ArrayList<>(list); Collections.sort(tbs, cmp); return tbs; } }