001/**
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 *
006 */
007package org.fcrepo.migration.handlers;
008
009import java.util.ArrayList;
010import java.util.HashMap;
011import java.util.List;
012import java.util.Map;
013import java.util.Collections;
014
015import org.fcrepo.migration.DatastreamVersion;
016import org.fcrepo.migration.ObjectInfo;
017import org.fcrepo.migration.ObjectProperties;
018import org.fcrepo.migration.ObjectReference;
019import org.fcrepo.migration.ObjectVersionReference;
020import org.fcrepo.migration.FedoraObjectVersionHandler;
021import org.fcrepo.migration.StreamingFedoraObjectHandler;
022
023/**
024 * A StreamingFedoraObjectHandler implementation that caches all the references to
025 * the Fedora 3 object and provides them to a FedoraObjectHandler implementation
026 * which in turn can process the object as a whole in a random-access fashion rather
027 * than as a stream.
028 * @author mdurbin
029 */
030public class ObjectAbstractionStreamingFedoraObjectHandler implements StreamingFedoraObjectHandler {
031
032    private FedoraObjectVersionHandler versionHandler;
033
034    private ObjectInfo objectInfo;
035
036    private ObjectProperties objectProperties;
037
038    private List<String> dsIds;
039
040    private Map<String, List<DatastreamVersion>> dsIdToVersionListMap;
041
042    /**
043     * the object abstraction streaming fedora object handler.
044     * @param versionHandler the fedora object version handler
045     */
046    public ObjectAbstractionStreamingFedoraObjectHandler(final FedoraObjectVersionHandler versionHandler) {
047        this.versionHandler = versionHandler;
048        this.dsIds = new ArrayList<String>();
049        this.dsIdToVersionListMap = new HashMap<String, List<DatastreamVersion>>();
050    }
051
052    @Override
053    public void beginObject(final ObjectInfo object) {
054        this.objectInfo = object;
055    }
056
057    @Override
058    public void processObjectProperties(final ObjectProperties properties) {
059        this.objectProperties = properties;
060    }
061
062    @Override
063    public void processDatastreamVersion(final DatastreamVersion dsVersion) {
064        List<DatastreamVersion> versions = dsIdToVersionListMap.get(dsVersion.getDatastreamInfo().getDatastreamId());
065        if (versions == null) {
066            dsIds.add(dsVersion.getDatastreamInfo().getDatastreamId());
067            versions = new ArrayList<DatastreamVersion>();
068            dsIdToVersionListMap.put(dsVersion.getDatastreamInfo().getDatastreamId(), versions);
069        }
070        versions.add(dsVersion);
071    }
072
073    @Override
074    public void completeObject(final ObjectInfo object) {
075        final var objectReference = getObjectReference();
076        try {
077            final Map<String, List<DatastreamVersion>> versionMap = buildVersionMap();
078            final List<String> versionDates = new ArrayList<String>(versionMap.keySet());
079            Collections.sort(versionDates);
080            final List<ObjectVersionReference> versions = new ArrayList<ObjectVersionReference>();
081            for (final String versionDate : versionDates) {
082                versions.add(getObjectVersionReference(versionDate, versionDates, objectReference, versionMap));
083            }
084            versionHandler.processObjectVersions(versions, object);
085        } finally {
086            cleanForReuse();
087        }
088    }
089
090    @Override
091    public void abortObject(final ObjectInfo object) {
092        cleanForReuse();
093    }
094
095    /**
096     * Removes any state that's specific to a Fedora 3 object that was processed
097     * so that this Handler may be reused for a different object.
098     */
099    private void cleanForReuse() {
100        this.dsIds.clear();
101        this.dsIdToVersionListMap.clear();
102    }
103
104    private Map<String, List<DatastreamVersion>> buildVersionMap() {
105        final Map<String, List<DatastreamVersion>> versionMap = new HashMap<String, List<DatastreamVersion>>();
106        for (final String dsId : dsIds) {
107            for (final DatastreamVersion v : dsIdToVersionListMap.get(dsId)) {
108                final String date = v.getCreated();
109                List<DatastreamVersion> versionsForDate = versionMap.get(date);
110                if (versionsForDate == null) {
111                    versionsForDate = new ArrayList<DatastreamVersion>();
112                    versionMap.put(date, versionsForDate);
113                }
114                versionsForDate.add(v);
115            }
116        }
117        return versionMap;
118    }
119
120    private ObjectReference getObjectReference() {
121        return new ObjectReference() {
122            @Override
123            public ObjectInfo getObjectInfo() {
124                return objectInfo;
125            }
126
127            @Override
128            public ObjectProperties getObjectProperties() {
129                return objectProperties;
130            }
131
132            @Override
133            public List<String> listDatastreamIds() {
134                return dsIds;
135            }
136
137            @Override
138            public List<DatastreamVersion> getDatastreamVersions(final String datastreamId) {
139                return dsIdToVersionListMap.get(datastreamId);
140            }
141        };
142    }
143
144    private ObjectVersionReference getObjectVersionReference(final String versionDate, final List<String> versionDates,
145                                                             final ObjectReference objectReference,
146                                                             final Map<String, List<DatastreamVersion>> versionMap) {
147        return new ObjectVersionReference() {
148            @Override
149            public ObjectReference getObject() {
150                return objectReference;
151            }
152
153            @Override
154            public ObjectProperties getObjectProperties() {
155                return objectProperties;
156            }
157
158            @Override
159            public String getVersionDate() {
160                return versionDate;
161            }
162
163            @Override
164            public List<DatastreamVersion> listChangedDatastreams() {
165                return versionMap.get(versionDate);
166            }
167
168            @Override
169            public boolean isLastVersion() {
170                return versionDates.get(versionDates.size() - 1).equals(versionDate);
171            }
172
173            @Override
174            public boolean isFirstVersion() {
175                return versionDates.get(0).equals(versionDate);
176            }
177
178            @Override
179            public int getVersionIndex() {
180                return versionDates.indexOf(versionDate);
181            }
182
183            @Override
184            public boolean wasDatastreamChanged(final String dsId) {
185                for (final DatastreamVersion v : listChangedDatastreams()) {
186                    if (v.getDatastreamInfo().getDatastreamId().equals(dsId)) {
187                        return true;
188                    }
189                }
190                return false;
191            }
192        };
193    }
194}