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     * Unless otherwise indicated, all code in JBoss DNA is licensed
010     * 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.io;
025    
026    import java.util.List;
027    import net.jcip.annotations.NotThreadSafe;
028    import org.jboss.dna.graph.ExecutionContext;
029    import org.jboss.dna.graph.Graph;
030    import org.jboss.dna.graph.NodeConflictBehavior;
031    import org.jboss.dna.graph.Graph.Batch;
032    import org.jboss.dna.graph.Graph.Create;
033    import org.jboss.dna.graph.property.Path;
034    import org.jboss.dna.graph.property.Property;
035    
036    /**
037     * A {@link Destination} that makes the changes to a graph via a {@link Batch}.
038     */
039    @NotThreadSafe
040    public class GraphBatchDestination implements Destination {
041        protected final Graph.Batch batch;
042        protected final boolean ignoreSubmit;
043    
044        /**
045         * Create a new instance that will use the specified batch. When {@link #submit()} is called, the batch will be
046         * {@link Batch#execute() executed}.
047         * 
048         * @param batch the batch
049         * @throws IllegalArgumentException if the batch is null
050         */
051        public GraphBatchDestination( Graph.Batch batch ) {
052            this(batch, false);
053        }
054    
055        /**
056         * Create a new instance that will use the specified batch. If {@code ignoreSubmit} is true, then {@link #submit()} does
057         * nothing (and the batch must be executed}; otherwise, {@link #submit()} immediately calls the {@link Batch#execute()
058         * executed}.
059         * 
060         * @param batch the batch
061         * @param ignoreSubmit true if the {@link #submit()} method should be ignored, or false otherwise
062         * @throws IllegalArgumentException if the batch is null
063         */
064        public GraphBatchDestination( Graph.Batch batch,
065                                      boolean ignoreSubmit ) {
066            assert batch != null;
067            this.batch = batch;
068            this.ignoreSubmit = ignoreSubmit;
069        }
070    
071        /**
072         * Return whether this instance is ignoring calls to {@link #submit()}.
073         * 
074         * @return ignoreSubmit
075         */
076        public boolean isSubmitIgnored() {
077            return ignoreSubmit;
078        }
079    
080        /**
081         * {@inheritDoc}
082         * 
083         * @see org.jboss.dna.graph.io.Destination#getExecutionContext()
084         */
085        public ExecutionContext getExecutionContext() {
086            return batch.getGraph().getContext();
087        }
088    
089        /**
090         * {@inheritDoc}
091         * 
092         * @see org.jboss.dna.graph.io.Destination#create(org.jboss.dna.graph.property.Path, java.util.List)
093         */
094        public void create( Path path,
095                            List<Property> properties ) {
096            assert properties != null;
097            Create<Batch> create = null;
098            if (properties.isEmpty()) {
099                create = batch.create(path);
100            } else {
101                create = batch.create(path, properties);
102            }
103            assert create != null;
104            NodeConflictBehavior behavior = createBehaviorFor(path);
105            if (behavior != null) {
106                switch (behavior) {
107                    case APPEND:
108                        create.byAppending();
109                        break;
110                    case REPLACE:
111                        create.orReplace();
112                        break;
113                    case UPDATE:
114                        create.byAppending();
115                        break;
116                    case DO_NOT_REPLACE:
117                        create.byAppending();
118                        break;
119                }
120            }
121            create.and();
122        }
123    
124        /**
125         * {@inheritDoc}
126         * 
127         * @see org.jboss.dna.graph.io.Destination#create(org.jboss.dna.graph.property.Path, org.jboss.dna.graph.property.Property,
128         *      org.jboss.dna.graph.property.Property[])
129         */
130        public void create( Path path,
131                            Property firstProperty,
132                            Property... additionalProperties ) {
133            Create<Batch> create = null;
134            if (firstProperty == null) {
135                create = batch.create(path);
136            } else {
137                create = batch.create(path, firstProperty, additionalProperties);
138            }
139            assert create != null;
140            NodeConflictBehavior behavior = createBehaviorFor(path);
141            if (behavior != null) {
142                switch (behavior) {
143                    case APPEND:
144                        create.byAppending();
145                        break;
146                    case REPLACE:
147                        create.orReplace();
148                        break;
149                    case UPDATE:
150                        create.byAppending();
151                        break;
152                    case DO_NOT_REPLACE:
153                        create.byAppending();
154                        break;
155                }
156            }
157            create.and();
158        }
159    
160        /**
161         * {@inheritDoc}
162         * 
163         * @see org.jboss.dna.graph.io.Destination#setProperties(org.jboss.dna.graph.property.Path,
164         *      org.jboss.dna.graph.property.Property[])
165         */
166        public void setProperties( Path path,
167                                   Property... properties ) {
168            if (properties == null) return;
169    
170            batch.set(properties).on(path);
171        }
172    
173        /**
174         * {@inheritDoc}
175         * 
176         * @see org.jboss.dna.graph.io.Destination#submit()
177         */
178        public void submit() {
179            // Execute only if we're not ignoring submits ...
180            if (!this.ignoreSubmit && !batch.hasExecuted()) batch.execute();
181        }
182    
183        /**
184         * Override this method in a subclass to control the {@link NodeConflictBehavior} that should be used when creating the node
185         * at the supplied path. By default, this method returns null.
186         * 
187         * @param path the path of the new node
188         * @return the conflict behavior, or null if {@link NodeConflictBehavior#UPDATE} should be used
189         */
190        protected NodeConflictBehavior createBehaviorFor( Path path ) {
191            return null;
192        }
193    }