001    /*
002     * JBoss DNA (http://www.jboss.org/dna)
003     * See the COPYRIGHT.txt file distributed with this work for information
004     * regarding copyright ownership.  Some portions may be licensed
005     * to Red Hat, Inc. under one or more contributor license agreements.
006     * See the AUTHORS.txt file in the distribution for a full listing of 
007     * individual contributors. 
008     *
009     * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
010     * is licensed to you under the terms of the GNU Lesser General Public License as
011     * published by the Free Software Foundation; either version 2.1 of
012     * the License, or (at your option) any later version.
013     *
014     * JBoss DNA is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     * Lesser General Public License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this software; if not, write to the Free
021     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
022     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
023     */
024    package org.jboss.dna.graph.request;
025    
026    import java.io.Serializable;
027    import java.util.concurrent.atomic.AtomicBoolean;
028    import org.jboss.dna.graph.connector.RepositoryConnection;
029    
030    /**
031     * The abstract base class for all classes representing requests to be executed against a {@link RepositoryConnection}.
032     * 
033     * @author Randall Hauch
034     */
035    public abstract class Request implements Serializable {
036    
037        private static final long serialVersionUID = 1L;
038    
039        private Throwable error;
040        private AtomicBoolean cancelled;
041    
042        protected Request() {
043            this.cancelled = new AtomicBoolean(false);
044        }
045    
046        /**
047         * Set the error for this request.
048         * 
049         * @param error the error to be associated with this request, or null if this request is to have no error
050         */
051        public void setError( Throwable error ) {
052            this.error = error;
053        }
054    
055        /**
056         * Return whether there is an error associated with this request
057         * 
058         * @return true if there is an error, or false otherwise
059         */
060        public boolean hasError() {
061            return this.error != null;
062        }
063    
064        /**
065         * Get the error associated with this request, if there is such an error.
066         * 
067         * @return the error, or null if there is none
068         */
069        public Throwable getError() {
070            return error;
071        }
072    
073        /**
074         * Check whether this request has been cancelled. Although it is a recommendation that the result of this method be followed
075         * wherever possible, it is not required to immediately stop processing the request if this method returns <code>true</code>.
076         * For example, if processing is almost complete, it may be appropriate to simply finish processing the request.
077         * <p>
078         * This method is safe to be called by different threads.
079         * </p>
080         * 
081         * @return true if this request has been cancelled, or false otherwise.
082         */
083        public boolean isCancelled() {
084            return cancelled.get();
085        }
086    
087        /**
088         * Set the cancelled state of this request. All requests are initially marked as not cancelled. Note that this is designed so
089         * that the same {@link AtomicBoolean} instance can be passed to multiple requests, allowing a single flag to dictate the
090         * cancelled state of all of those requests.
091         * <p>
092         * So, by default, each request should already be set up to not be cancelled, so for most cases this method does not need to
093         * be called at all. This method should be called when this flag is to be shared among multiple requests, usually when the
094         * requests are being initialized or assembled.
095         * </p>
096         * 
097         * @param cancelled the new (potentially shared) cancelled state for the request; may not be null
098         */
099        /*package*/void setCancelledFlag( AtomicBoolean cancelled ) {
100            assert cancelled != null;
101            this.cancelled = cancelled;
102        }
103    
104        /**
105         * Get this request's cancelled flag.
106         * 
107         * @return the cancelled flag
108         */
109        /*package*/AtomicBoolean getCancelledFlag() {
110            return cancelled;
111        }
112    
113        /**
114         * Cancel this request. After this method is called, the {@link #isCancelled() cancellation flag} is set, and any current or
115         * future processing of the request may be affected by the cancellation. (Note however, that processors may choose to not
116         * respect this request.)
117         * <p>
118         * This method is safe to be called by different threads.
119         * </p>
120         */
121        public void cancel() {
122            this.cancelled.set(true);
123        }
124    
125        /**
126         * Return whether this request only reads information.
127         * 
128         * @return true if this request reads information, or false if it requests that the repository content be changed in some way
129         */
130        public abstract boolean isReadOnly();
131    }