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}