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.kernel.impl.observer; 008 009import org.fcrepo.kernel.api.identifiers.FedoraId; 010import org.fcrepo.kernel.api.observer.Event; 011import org.fcrepo.kernel.api.observer.EventType; 012import org.fcrepo.kernel.api.operations.ResourceOperation; 013import org.fcrepo.kernel.impl.util.UserUtil; 014 015import java.net.URI; 016import java.time.Instant; 017import java.util.HashSet; 018import java.util.Objects; 019import java.util.Set; 020 021/** 022 * Converts a ResourceOperation into an Event. 023 * 024 * @author pwinckles 025 */ 026public class ResourceOperationEventBuilder implements EventBuilder { 027 028 private FedoraId fedoraId; 029 private Set<EventType> types; 030 private Set<String> resourceTypes; 031 private String userID; 032 private String userAgent; 033 private String baseUrl; 034 private Instant date; 035 private String userAgentBaseUri; 036 037 /** 038 * Creates a new EventBuilder based on an ResourceOperation 039 * 040 * @param fedoraId the FedoraId the operation is on 041 * @param operation the ResourceOperation to create an event for 042 * @param userAgentBaseUri the base uri of the user agent, optional 043 * @return new builder 044 */ 045 public static ResourceOperationEventBuilder fromResourceOperation(final FedoraId fedoraId, 046 final ResourceOperation operation, 047 final String userAgentBaseUri) { 048 final var builder = new ResourceOperationEventBuilder(); 049 builder.fedoraId = fedoraId; 050 builder.date = Instant.now(); 051 builder.resourceTypes = new HashSet<>(); 052 builder.userID = operation.getUserPrincipal(); 053 builder.types = new HashSet<>(); 054 builder.types.add(mapOperationToEventType(operation)); 055 builder.userAgentBaseUri = userAgentBaseUri; 056 return builder; 057 } 058 059 private static EventType mapOperationToEventType(final ResourceOperation operation) { 060 switch (operation.getType()) { 061 case CREATE: 062 return EventType.RESOURCE_CREATION; 063 case UPDATE: 064 case UPDATE_HEADERS: 065 return EventType.RESOURCE_MODIFICATION; 066 case DELETE: 067 return EventType.RESOURCE_DELETION; 068 case PURGE: 069 return EventType.RESOURCE_PURGE; 070 case FOLLOW: 071 return EventType.INBOUND_REFERENCE; 072 default: 073 throw new IllegalStateException( 074 String.format("There is no EventType mapping for ResourceOperation type %s on operation %s", 075 operation.getType(), operation)); 076 } 077 } 078 079 private ResourceOperationEventBuilder() { 080 // Intentionally left blank 081 } 082 083 @Override 084 public EventBuilder merge(final EventBuilder other) { 085 if (other == null) { 086 return this; 087 } 088 089 if (!(other instanceof ResourceOperationEventBuilder)) { 090 throw new IllegalStateException( 091 String.format("Cannot merge EventBuilders because they are different types <%s> and <%s>", 092 this.getClass(), other.getClass())); 093 } 094 095 final var otherCast = (ResourceOperationEventBuilder) other; 096 097 if (!this.fedoraId.equals(otherCast.fedoraId)) { 098 throw new IllegalStateException( 099 String.format("Cannot merge events because they are for different resources: <%s> and <%s>", 100 this, otherCast)); 101 } 102 103 this.types.addAll(otherCast.types); 104 this.resourceTypes.addAll(otherCast.resourceTypes); 105 106 if (this.date.isBefore(otherCast.date)) { 107 this.date = otherCast.date; 108 } 109 110 return this; 111 } 112 113 @Override 114 public EventBuilder withResourceTypes(final Set<String> resourceTypes) { 115 this.resourceTypes = Objects.requireNonNullElse(resourceTypes, new HashSet<>()); 116 return this; 117 } 118 119 @Override 120 public EventBuilder withBaseUrl(final String baseUrl) { 121 this.baseUrl = baseUrl; 122 return this; 123 } 124 125 @Override 126 public EventBuilder withUserAgent(final String userAgent) { 127 this.userAgent = userAgent; 128 return this; 129 } 130 131 @Override 132 public Event build() { 133 URI userUri = null; 134 if (userID != null) { 135 userUri = UserUtil.getUserURI(userID, userAgentBaseUri); 136 } 137 return new EventImpl(fedoraId, types, resourceTypes, userID, userUri, userAgent, baseUrl, date); 138 } 139 140 @Override 141 public String toString() { 142 return "ResourceOperationEventBuilder{" + 143 "fedoraId=" + fedoraId + 144 ", types=" + types + 145 ", resourceTypes=" + resourceTypes + 146 ", userID='" + userID + '\'' + 147 ", userAgent='" + userAgent + '\'' + 148 ", baseUrl='" + baseUrl + '\'' + 149 ", date=" + date + 150 '}'; 151 } 152 153}