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