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.kernel.observer;
017
018import static com.google.common.base.MoreObjects.toStringHelper;
019import static com.google.common.base.Preconditions.checkArgument;
020import static com.google.common.base.Throwables.propagate;
021import static com.google.common.collect.Sets.union;
022import static java.util.Collections.singleton;
023import static javax.jcr.observation.Event.PROPERTY_ADDED;
024import static javax.jcr.observation.Event.PROPERTY_CHANGED;
025import static javax.jcr.observation.Event.PROPERTY_REMOVED;
026
027import java.util.HashMap;
028import java.util.HashSet;
029import java.util.Map;
030import java.util.Set;
031
032import javax.jcr.RepositoryException;
033import javax.jcr.observation.Event;
034
035import org.fcrepo.kernel.utils.EventType;
036
037import com.google.common.base.Function;
038import com.google.common.base.Joiner;
039import com.google.common.collect.Iterables;
040
041/**
042 * A very simple abstraction to prevent event-driven machinery downstream from the repository from relying directly
043 * on a JCR interface {@link Event}. Can represent either a single JCR event or several.
044 *
045 * @author ajs6f
046 * @since Feb 19, 2013
047 */
048public class FedoraEvent {
049
050    private Event e;
051
052    private Set<Integer> eventTypes = new HashSet<>();
053    private Set<String> eventProperties = new HashSet<>();
054
055    /**
056     * Wrap a JCR Event with our FedoraEvent decorators
057     *
058     * @param e
059     */
060    public FedoraEvent(final Event e) {
061        checkArgument(e != null, "null cannot support a FedoraEvent!");
062        this.e = e;
063    }
064
065    /**
066     * Create a FedoraEvent from an existing FedoraEvent object
067     * Note: Only the wrapped JCR event is passed on to the new object.
068     *
069     * @param e
070     */
071    public FedoraEvent(final FedoraEvent e) {
072        checkArgument(e != null, "null cannot support a FedoraEvent!");
073        this.e = e.e;
074    }
075
076    /**
077     * @return the event types of the underlying JCR {@link Event}s
078     */
079    public Set<Integer> getTypes() {
080        return eventTypes != null ? union(singleton(e.getType()), eventTypes) : singleton(e.getType());
081    }
082
083    /**
084     * @param type
085     * @return this object for continued use
086     */
087    public FedoraEvent addType(final Integer type) {
088        eventTypes.add(type);
089        return this;
090    }
091
092    /**
093     * @return the property names of the underlying JCR property {@link Event}s
094    **/
095    public Set<String> getProperties() {
096        return eventProperties;
097    }
098
099    /**
100     * Add a property name to this event
101     * @param property property name
102     * @return this object for continued use
103    **/
104    public FedoraEvent addProperty( final String property ) {
105        eventProperties.add(property);
106        return this;
107    }
108
109    /**
110     * @return the path of the underlying JCR {@link Event}s
111     */
112    public String getPath() throws RepositoryException {
113        if (e.getType() == PROPERTY_ADDED   ||
114            e.getType() == PROPERTY_CHANGED ||
115            e.getType() == PROPERTY_REMOVED) {
116            return e.getPath().substring(0, e.getPath().lastIndexOf("/"));
117        }
118        return e.getPath();
119    }
120
121    /**
122     * @return the user ID of the underlying JCR {@link Event}s
123     */
124    public String getUserID() {
125        return e.getUserID();
126    }
127
128    /**
129     * @return the node identifer of the underlying JCR {@link Event}s
130     */
131    public String getIdentifier() throws RepositoryException {
132        return e.getIdentifier();
133    }
134
135    /**
136     * @return the info map of the underlying JCR {@link Event}s
137     */
138    public Map<Object, Object> getInfo() throws RepositoryException {
139        return new HashMap<>(e.getInfo());
140    }
141
142    /**
143     * @return the user data of the underlying JCR {@link Event}s
144     */
145    public String getUserData() throws RepositoryException {
146        return e.getUserData();
147    }
148
149    /**
150     * @return the date of the underlying JCR {@link Event}s
151     */
152    public long getDate() throws RepositoryException {
153        return e.getDate();
154    }
155
156    @Override
157    public String toString() {
158        try {
159            return toStringHelper(this).add("Event types:",
160                    Joiner.on(',').join(Iterables.transform(getTypes(), new Function<Integer, String>() {
161
162                        @Override
163                        public String apply(final Integer type) {
164                            return EventType.valueOf(type).getName();
165                        }
166                    }))).add("Event properties:",
167                    Joiner.on(',').join(eventProperties)).add("Path:", getPath()).add("Date: ",
168                    getDate()).add("Info:", getInfo()).toString();
169        } catch (final RepositoryException e) {
170            throw propagate(e);
171        }
172    }
173}