001    /*
002     * JBoss, Home of Professional Open Source.
003     * Copyright 2008, Red Hat Middleware LLC, and individual contributors
004     * as indicated by the @author tags. See the copyright.txt file in the
005     * distribution for a full listing of individual contributors. 
006     *
007     * This is free software; you can redistribute it and/or modify it
008     * under the terms of the GNU Lesser General Public License as
009     * published by the Free Software Foundation; either version 2.1 of
010     * the License, or (at your option) any later version.
011     *
012     * This software is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015     * Lesser General Public License for more details.
016     *
017     * You should have received a copy of the GNU Lesser General Public
018     * License along with this software; if not, write to the Free
019     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021     */
022    package org.jboss.dna.repository.observation;
023    
024    import java.util.Collections;
025    import java.util.Set;
026    import net.jcip.annotations.Immutable;
027    import org.jboss.dna.common.util.HashCode;
028    
029    /**
030     * A notification of changes to a node.
031     * @author Randall Hauch
032     */
033    @Immutable
034    public class NodeChange {
035    
036        private final String repositoryWorkspaceName;
037        private final String absolutePath;
038        private final int eventTypes;
039        private final Set<String> modifiedProperties;
040        private final Set<String> removedProperties;
041        private final int hc;
042    
043        public NodeChange( String repositoryWorkspaceName, String absolutePath, int eventTypes, Set<String> modifiedProperties, Set<String> removedProperties ) {
044            assert repositoryWorkspaceName != null;
045            assert absolutePath != null;
046            this.repositoryWorkspaceName = repositoryWorkspaceName;
047            this.absolutePath = absolutePath.trim();
048            this.hc = HashCode.compute(this.repositoryWorkspaceName, this.absolutePath);
049            this.eventTypes = eventTypes;
050            if (modifiedProperties == null) modifiedProperties = Collections.emptySet();
051            if (removedProperties == null) removedProperties = Collections.emptySet();
052            this.modifiedProperties = Collections.unmodifiableSet(modifiedProperties);
053            this.removedProperties = Collections.unmodifiableSet(removedProperties);
054        }
055    
056        /**
057         * @return absolutePath
058         */
059        public String getAbsolutePath() {
060            return this.absolutePath;
061        }
062    
063        /**
064         * @return repositoryWorkspaceName
065         */
066        public String getRepositoryWorkspaceName() {
067            return this.repositoryWorkspaceName;
068        }
069    
070        /**
071         * @return modifiedProperties
072         */
073        public Set<String> getModifiedProperties() {
074            return this.modifiedProperties;
075        }
076    
077        /**
078         * @return removedProperties
079         */
080        public Set<String> getRemovedProperties() {
081            return this.removedProperties;
082        }
083    
084        /**
085         * {@inheritDoc}
086         */
087        @Override
088        public int hashCode() {
089            return this.hc;
090        }
091    
092        public boolean includesAllEventTypes( int... jcrEventTypes ) {
093            for (int jcrEventType : jcrEventTypes) {
094                if ((this.eventTypes & jcrEventType) == 0) return false;
095            }
096            return true;
097        }
098    
099        public boolean includesEventTypes( int... jcrEventTypes ) {
100            for (int jcrEventType : jcrEventTypes) {
101                if ((this.eventTypes & jcrEventType) != 0) return true;
102            }
103            return false;
104        }
105    
106        public boolean isSameNode( NodeChange that ) {
107            if (that == this) return true;
108            if (this.hc != that.hc) return false;
109            if (!this.repositoryWorkspaceName.equals(that.repositoryWorkspaceName)) return false;
110            if (!this.absolutePath.equals(that.absolutePath)) return false;
111            return true;
112        }
113    
114        /**
115         * Return whether this node change occurs on a node on the supplied path.
116         * @param absolutePath the path
117         * @return true if the node is on the supplied absolute path, or false otherwise
118         * @see #isNotOnPath(String)
119         */
120        public boolean isOnPath( String absolutePath ) {
121            if (absolutePath == null) return false;
122            if (this.getAbsolutePath().startsWith(absolutePath)) return true;
123            return false;
124        }
125    
126        /**
127         * Return whether this node change occurs on a node on a different path than that supplied.
128         * @param absolutePath the path
129         * @return true if the node is on a different path, or false if it is on the same path
130         * @see #isOnPath(String)
131         */
132        public boolean isNotOnPath( String absolutePath ) {
133            return !isOnPath(absolutePath);
134        }
135    
136        /**
137         * Determine whether this node change includes the setting of new value(s) for the supplied property.
138         * @param property the name of the property
139         * @return true if the named property has a new value on this node, or false otherwise
140         */
141        public boolean isPropertyModified( String property ) {
142            return this.modifiedProperties.contains(property);
143        }
144    
145        /**
146         * Determine whether this node change includes the removal of the supplied property.
147         * @param property the name of the property
148         * @return true if the named property was removed from this node, or false otherwise
149         */
150        public boolean isPropertyRemoved( String property ) {
151            return this.removedProperties.contains(property);
152        }
153    
154        /**
155         * {@inheritDoc}
156         */
157        @Override
158        public boolean equals( Object obj ) {
159            if (obj == this) return true;
160            if (obj instanceof NodeChange) {
161                NodeChange that = (NodeChange)obj;
162                if (!this.isSameNode(that)) return false;
163                if (this.eventTypes != that.eventTypes) return false;
164                return true;
165            }
166            return false;
167        }
168    
169        /**
170         * {@inheritDoc}
171         */
172        @Override
173        public String toString() {
174            return this.repositoryWorkspaceName + "=>" + this.absolutePath;
175        }
176    }