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.connector.federation.executor;
023    
024    import java.util.Set;
025    import net.jcip.annotations.NotThreadSafe;
026    import org.jboss.dna.connector.federation.Projection;
027    import org.jboss.dna.graph.ExecutionContext;
028    import org.jboss.dna.graph.commands.CopyBranchCommand;
029    import org.jboss.dna.graph.commands.CopyNodeCommand;
030    import org.jboss.dna.graph.commands.CreateNodeCommand;
031    import org.jboss.dna.graph.commands.DeleteBranchCommand;
032    import org.jboss.dna.graph.commands.GetChildrenCommand;
033    import org.jboss.dna.graph.commands.GetNodeCommand;
034    import org.jboss.dna.graph.commands.GetPropertiesCommand;
035    import org.jboss.dna.graph.commands.MoveBranchCommand;
036    import org.jboss.dna.graph.commands.RecordBranchCommand;
037    import org.jboss.dna.graph.commands.SetPropertiesCommand;
038    import org.jboss.dna.graph.commands.executor.AbstractCommandExecutor;
039    import org.jboss.dna.graph.connectors.RepositoryConnection;
040    import org.jboss.dna.graph.connectors.RepositoryConnectionFactory;
041    import org.jboss.dna.graph.connectors.RepositorySource;
042    import org.jboss.dna.graph.connectors.RepositorySourceException;
043    import org.jboss.dna.graph.properties.DateTime;
044    import org.jboss.dna.graph.properties.Path;
045    import org.jboss.dna.graph.properties.PathFactory;
046    
047    /**
048     * @author Randall Hauch
049     */
050    @NotThreadSafe
051    public class SingleProjectionCommandExecutor extends AbstractCommandExecutor {
052    
053        private final Projection projection;
054        private final PathFactory pathFactory;
055        private final RepositoryConnectionFactory connectionFactory;
056        private RepositoryConnection connection;
057    
058        /**
059         * @param context the execution context in which the executor will be run; may not be null
060         * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
061         * @param projection the projection used for the cached information; may not be null and must have exactly one
062         *        {@link Projection#getRules() rule}
063         * @param connectionFactory the factory for {@link RepositoryConnection} instances
064         */
065        public SingleProjectionCommandExecutor( ExecutionContext context,
066                                                String sourceName,
067                                                Projection projection,
068                                                RepositoryConnectionFactory connectionFactory ) {
069            this(context, sourceName, null, projection, connectionFactory);
070        }
071    
072        /**
073         * @param context the execution context in which the executor will be run; may not be null
074         * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
075         * @param now the current time; may be null if the system time is to be used
076         * @param projection the projection used for the cached information; may not be null and must have exactly one
077         *        {@link Projection#getRules() rule}
078         * @param connectionFactory the factory for {@link RepositoryConnection} instances
079         */
080        public SingleProjectionCommandExecutor( ExecutionContext context,
081                                                String sourceName,
082                                                DateTime now,
083                                                Projection projection,
084                                                RepositoryConnectionFactory connectionFactory ) {
085            super(context, sourceName, now);
086            assert connectionFactory != null;
087            assert projection != null;
088            assert projection.getRules().size() == 1;
089            this.projection = projection;
090            this.connectionFactory = connectionFactory;
091            this.pathFactory = context.getValueFactories().getPathFactory();
092            assert this.pathFactory != null;
093        }
094    
095        protected RepositoryConnection getConnection() throws RepositorySourceException {
096            if (connection == null) {
097                // Create a connection ...
098                connection = this.connectionFactory.createConnection(this.projection.getSourceName());
099            }
100            return connection;
101        }
102    
103        /**
104         * {@inheritDoc}
105         * 
106         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#close()
107         */
108        @Override
109        public void close() {
110            if (this.connection != null) {
111                try {
112                    this.connection.close();
113                } finally {
114                    this.connection = null;
115                }
116            }
117            super.close();
118        }
119    
120        /**
121         * {@inheritDoc}
122         * 
123         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.GetChildrenCommand)
124         */
125        @Override
126        public void execute( GetChildrenCommand command ) throws RepositorySourceException {
127            Path pathInSource = getPathInSource(command.getPath());
128            getConnection().execute(this.getExecutionContext(), new ProjectedGetChildrenCommand(command, pathInSource));
129        }
130    
131        /**
132         * {@inheritDoc}
133         * 
134         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.GetPropertiesCommand)
135         */
136        @Override
137        public void execute( GetPropertiesCommand command ) throws RepositorySourceException {
138            Path pathInSource = getPathInSource(command.getPath());
139            getConnection().execute(this.getExecutionContext(), new ProjectedGetPropertiesCommand(command, pathInSource));
140        }
141    
142        /**
143         * {@inheritDoc}
144         * 
145         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.GetNodeCommand)
146         */
147        @Override
148        public void execute( GetNodeCommand command ) throws RepositorySourceException {
149            Path pathInSource = getPathInSource(command.getPath());
150            getConnection().execute(this.getExecutionContext(), new ProjectedGetNodeCommand(command, pathInSource));
151        }
152    
153        /**
154         * {@inheritDoc}
155         * 
156         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.CreateNodeCommand)
157         */
158        @Override
159        public void execute( CreateNodeCommand command ) throws RepositorySourceException {
160            Path pathInSource = getPathInSource(command.getPath());
161            getConnection().execute(this.getExecutionContext(), new ProjectedCreateNodeCommand(command, pathInSource));
162        }
163    
164        /**
165         * {@inheritDoc}
166         * 
167         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.SetPropertiesCommand)
168         */
169        @Override
170        public void execute( SetPropertiesCommand command ) throws RepositorySourceException {
171            Path pathInSource = getPathInSource(command.getPath());
172            getConnection().execute(this.getExecutionContext(), new ProjectedSetPropertiesCommand(command, pathInSource));
173        }
174    
175        /**
176         * {@inheritDoc}
177         * 
178         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.DeleteBranchCommand)
179         */
180        @Override
181        public void execute( DeleteBranchCommand command ) throws RepositorySourceException {
182            Path pathInSource = getPathInSource(command.getPath());
183            getConnection().execute(this.getExecutionContext(), new ProjectedDeleteBranchCommand(command, pathInSource));
184        }
185    
186        /**
187         * {@inheritDoc}
188         * 
189         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.MoveBranchCommand)
190         */
191        @Override
192        public void execute( MoveBranchCommand command ) throws RepositorySourceException {
193            Path pathInSource = getPathInSource(command.getPath());
194            Path newPathInSource = getPathInSource(command.getNewPath());
195            getConnection().execute(this.getExecutionContext(),
196                                    new ProjectedMoveBranchCommand(command, pathInSource, newPathInSource));
197        }
198    
199        /**
200         * {@inheritDoc}
201         * 
202         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.RecordBranchCommand)
203         */
204        @Override
205        public void execute( RecordBranchCommand command ) throws RepositorySourceException {
206            Path pathInSource = getPathInSource(command.getPath());
207            getConnection().execute(this.getExecutionContext(), new ProjectedRecordBranchCommand(command, pathInSource));
208        }
209    
210        /**
211         * {@inheritDoc}
212         * 
213         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.CopyBranchCommand)
214         */
215        @Override
216        public void execute( CopyBranchCommand command ) throws RepositorySourceException {
217            Path pathInSource = getPathInSource(command.getPath());
218            Path newPathInSource = getPathInSource(command.getNewPath());
219            getConnection().execute(this.getExecutionContext(),
220                                    new ProjectedCopyBranchCommand(command, pathInSource, newPathInSource));
221        }
222    
223        /**
224         * {@inheritDoc}
225         * 
226         * @see org.jboss.dna.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.graph.commands.CopyNodeCommand)
227         */
228        @Override
229        public void execute( CopyNodeCommand command ) throws RepositorySourceException {
230            Path pathInSource = getPathInSource(command.getPath());
231            Path newPathInSource = getPathInSource(command.getNewPath());
232            getConnection().execute(this.getExecutionContext(), new ProjectedCopyNodeCommand(command, pathInSource, newPathInSource));
233        }
234    
235        protected Path getPathInSource( Path pathInRepository ) {
236            Set<Path> paths = this.projection.getPathsInSource(pathInRepository, pathFactory);
237            if (!paths.isEmpty()) {
238                return paths.iterator().next();
239            }
240            return this.projection.getPathsInSource(pathInRepository, pathFactory).iterator().next();
241        }
242    
243        protected Path getPathInRepository( Path pathInSource ) {
244            return this.projection.getPathsInRepository(pathInSource, pathFactory).iterator().next();
245        }
246    
247    }