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.graph.commands.executor;
023
024 import org.jboss.dna.graph.ExecutionContext;
025 import org.jboss.dna.graph.commands.CompositeCommand;
026 import org.jboss.dna.graph.commands.CopyBranchCommand;
027 import org.jboss.dna.graph.commands.CopyNodeCommand;
028 import org.jboss.dna.graph.commands.CreateNodeCommand;
029 import org.jboss.dna.graph.commands.DeleteBranchCommand;
030 import org.jboss.dna.graph.commands.GetChildrenCommand;
031 import org.jboss.dna.graph.commands.GetNodeCommand;
032 import org.jboss.dna.graph.commands.GetPropertiesCommand;
033 import org.jboss.dna.graph.commands.GraphCommand;
034 import org.jboss.dna.graph.commands.MoveBranchCommand;
035 import org.jboss.dna.graph.commands.RecordBranchCommand;
036 import org.jboss.dna.graph.commands.SetPropertiesCommand;
037 import org.jboss.dna.graph.connectors.RepositoryConnection;
038 import org.jboss.dna.graph.connectors.RepositorySourceException;
039 import org.jboss.dna.graph.properties.DateTime;
040
041 /**
042 * Abstract implementation of the {@link CommandExecutor} interface that provides implementations for all methods, making this a
043 * useful base class for all {@link CommandExecutor} implementations. Because all methods are implemented, subclasses only need to
044 * override methods that are appropriate or applicable, and all other commands will be processed correctly (even if new command
045 * interfaces are added in later versions). In some cases, as with {@link CompositeCommand} and {@link GetNodeCommand}, these
046 * implementations attempt to process the command. In other cases (e.g., {@link GetPropertiesCommand}, and
047 * {@link DeleteBranchCommand}), the methods do nothing and should be overridden if the command is to be processed.
048 * <p>
049 * The implementation is also designed to be instantated as needed. This may be once per call to
050 * {@link RepositoryConnection#execute(ExecutionContext, GraphCommand...)}, or may be once per transaction. Either way, this class
051 * is designed to allow subclasses to store additional state that may otherwise be expensive or undesirable to obtain repeatedly.
052 * However, this state should be independent of the commands that are processed, meaning that implementations should generally not
053 * change state as a result of processing specific commands.
054 * </p>
055 *
056 * @author Randall Hauch
057 */
058 public abstract class AbstractCommandExecutor implements CommandExecutor {
059
060 private final ExecutionContext context;
061 private final String sourceName;
062 private final DateTime nowInUtc;
063
064 protected AbstractCommandExecutor( ExecutionContext context,
065 String sourceName ) {
066 this(context, sourceName, null);
067 }
068
069 protected AbstractCommandExecutor( ExecutionContext context,
070 String sourceName,
071 DateTime now ) {
072 assert context != null;
073 assert sourceName != null && sourceName.trim().length() != 0;
074 this.context = context;
075 this.sourceName = sourceName;
076 this.nowInUtc = now != null ? now.toUtcTimeZone() : context.getValueFactories().getDateFactory().createUtc();
077 }
078
079 /**
080 * Get the environment in which these commands are being executed.
081 *
082 * @return the execution context; never null
083 */
084 public ExecutionContext getExecutionContext() {
085 return context;
086 }
087
088 /**
089 * Get the name of the repository source.
090 *
091 * @return the source name; never null or empty
092 */
093 public String getSourceName() {
094 return sourceName;
095 }
096
097 /**
098 * Get the current time associated with this executor. All calls to this method will result in the same time.
099 *
100 * @return the current time expressed in UTC
101 */
102 public DateTime getCurrentTimeInUtc() {
103 return nowInUtc;
104 }
105
106 /**
107 * {@inheritDoc}
108 * <p>
109 * This implementation examines the instance to see which {@link GraphCommand command interfaces} are implemented by the
110 * command, and delegates to the appropriate methods.
111 *
112 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.GraphCommand)
113 */
114 public void execute( GraphCommand command ) throws RepositorySourceException {
115 if (command == null) return;
116 if (command instanceof CompositeCommand) {
117 execute((CompositeCommand)command);
118 // A composite command should only contain other commands and should not do anything on its own
119 return;
120 }
121 // The command could implement multiple "get" behaviors
122 if (command instanceof GetNodeCommand) {
123 execute((GetNodeCommand)command);
124 } else if (command instanceof GetPropertiesCommand) {
125 execute((GetPropertiesCommand)command);
126 } else if (command instanceof GetChildrenCommand) {
127 execute((GetChildrenCommand)command);
128 }
129 // The command could record the branch even if deleting or moving ...
130 if (command instanceof RecordBranchCommand) {
131 execute((RecordBranchCommand)command);
132 }
133 // If the command createa a node, it will have properties to set
134 if (command instanceof CreateNodeCommand) {
135 execute((CreateNodeCommand)command);
136 } else if (command instanceof SetPropertiesCommand) {
137 execute((SetPropertiesCommand)command);
138 }
139 // A copy command will either copy a branch or a node, but not both
140 if (command instanceof CopyBranchCommand) {
141 execute((CopyBranchCommand)command);
142 } else if (command instanceof CopyNodeCommand) {
143 execute((CopyNodeCommand)command);
144 }
145 // The command can either delete or move a branch, but a command can't do both (the move does delete)
146 if (command instanceof DeleteBranchCommand) {
147 execute((DeleteBranchCommand)command);
148 } else if (command instanceof MoveBranchCommand) {
149 execute((MoveBranchCommand)command);
150 }
151 }
152
153 /**
154 * {@inheritDoc}
155 *
156 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.CompositeCommand)
157 */
158 public void execute( CompositeCommand command ) throws RepositorySourceException {
159 assert command != null;
160 for (GraphCommand nestedCommand : command) {
161 execute(nestedCommand);
162 }
163 }
164
165 /**
166 * {@inheritDoc}
167 * <p>
168 * This method implementation simply delegates to both the {@link #execute(GetPropertiesCommand)} and
169 * {@link #execute(GetChildrenCommand)} methods, and should be overridden by subclasses that can process
170 * {@link GetNodeCommand} more efficiently as a single command.
171 * </p>
172 *
173 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.GetNodeCommand)
174 */
175 public void execute( GetNodeCommand command ) throws RepositorySourceException {
176 execute((GetPropertiesCommand)command);
177 execute((GetChildrenCommand)command);
178 }
179
180 /**
181 * {@inheritDoc}
182 *
183 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.GetPropertiesCommand)
184 */
185 public void execute( GetPropertiesCommand command ) throws RepositorySourceException {
186 }
187
188 /**
189 * {@inheritDoc}
190 *
191 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.GetChildrenCommand)
192 */
193 public void execute( GetChildrenCommand command ) throws RepositorySourceException {
194 }
195
196 /**
197 * {@inheritDoc}
198 *
199 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.CreateNodeCommand)
200 */
201 public void execute( CreateNodeCommand command ) throws RepositorySourceException {
202 }
203
204 /**
205 * {@inheritDoc}
206 *
207 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.SetPropertiesCommand)
208 */
209 public void execute( SetPropertiesCommand command ) throws RepositorySourceException {
210 }
211
212 /**
213 * {@inheritDoc}
214 *
215 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.CopyNodeCommand)
216 */
217 public void execute( CopyNodeCommand command ) throws RepositorySourceException {
218 }
219
220 /**
221 * {@inheritDoc}
222 *
223 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.CopyBranchCommand)
224 */
225 public void execute( CopyBranchCommand command ) throws RepositorySourceException {
226 }
227
228 /**
229 * {@inheritDoc}
230 *
231 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.DeleteBranchCommand)
232 */
233 public void execute( DeleteBranchCommand command ) throws RepositorySourceException {
234 }
235
236 /**
237 * {@inheritDoc}
238 *
239 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.MoveBranchCommand)
240 */
241 public void execute( MoveBranchCommand command ) throws RepositorySourceException {
242 }
243
244 /**
245 * {@inheritDoc}
246 *
247 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.graph.commands.RecordBranchCommand)
248 */
249 public void execute( RecordBranchCommand command ) throws RepositorySourceException {
250 }
251
252 /**
253 * {@inheritDoc}
254 *
255 * @see org.jboss.dna.graph.commands.executor.CommandExecutor#close()
256 */
257 public void close() {
258 }
259
260 }