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;
023
024 import java.io.IOException;
025 import java.io.InputStream;
026 import java.net.URI;
027 import java.util.List;
028 import net.jcip.annotations.NotThreadSafe;
029 import org.jboss.dna.common.text.TextDecoder;
030 import org.jboss.dna.common.util.CheckArg;
031 import org.jboss.dna.graph.connectors.RepositorySource;
032 import org.jboss.dna.graph.connectors.RepositorySourceException;
033 import org.jboss.dna.graph.properties.Name;
034 import org.jboss.dna.graph.properties.NamespaceRegistry;
035 import org.jboss.dna.graph.properties.Path;
036 import org.jboss.dna.graph.properties.Property;
037 import org.jboss.dna.graph.xml.XmlHandler;
038 import org.jboss.dna.graph.xml.XmlHandler.Destination;
039 import org.xml.sax.InputSource;
040 import org.xml.sax.SAXException;
041 import org.xml.sax.XMLReader;
042 import org.xml.sax.helpers.XMLReaderFactory;
043
044 /**
045 * @author Randall Hauch
046 * @author John Verhaeg
047 */
048 public class GraphImporter {
049
050 private final Graph graph;
051
052 public GraphImporter( Graph graph ) {
053 CheckArg.isNotNull(graph, "graph");
054 this.graph = graph;
055 }
056
057 /**
058 * Get the context in which the importer will be executed.
059 *
060 * @return the execution context; never null
061 */
062 public ExecutionContext getContext() {
063 return this.graph.getContext();
064 }
065
066 /**
067 * The graph that this importer uses.
068 *
069 * @return the graph; never null
070 */
071 public Graph getGraph() {
072 return graph;
073 }
074
075 /**
076 * Read the content from the supplied URI and import into the repository at the supplied location.
077 *
078 * @param uri the URI where the importer can read the content that is to be imported
079 * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
080 * be null
081 * @return the batch of requests for creating the graph content that represents the imported content
082 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
083 * @throws IOException if there is a problem reading the content
084 * @throws SAXException if there is a problem with the SAX Parser
085 * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
086 * source}
087 */
088 public Graph.Batch importXml( URI uri,
089 Location location ) throws IOException, SAXException, RepositorySourceException {
090 return importXml(uri, location, false);
091 }
092
093 /**
094 * Read the content from the supplied URI and import into the repository at the supplied location.
095 *
096 * @param uri the URI where the importer can read the content that is to be imported
097 * @param location the location in the {@link RepositorySource repository source} where the content is to be written; may not
098 * be null
099 * @param skip true if the root element should be skipped, or false if a node should be created for the root XML element
100 * @return the batch of requests for creating the graph content that represents the imported content
101 * @throws IllegalArgumentException if the <code>uri</code> or destination path are null
102 * @throws IOException if there is a problem reading the content
103 * @throws SAXException if there is a problem with the SAX Parser
104 * @throws RepositorySourceException if there is a problem while writing the content to the {@link RepositorySource repository
105 * source}
106 */
107 public Graph.Batch importXml( URI uri,
108 Location location,
109 boolean skip ) throws IOException, SAXException, RepositorySourceException {
110 CheckArg.isNotNull(uri, "uri");
111 CheckArg.isNotNull(location, "location");
112 CheckArg.isNotNull(location.getPath(), "location.getPath()");
113
114 // Create the destination for the XmlHandler ...
115 Graph.Batch batch = graph.batch();
116 XmlHandler.Destination destination = new CreateOnGraphInBatch(batch);
117
118 // Determine where the content is to be placed ...
119 Path parentPath = location.getPath();
120 InputStream stream = null;
121 Name nameAttribute = JcrLexicon.NAME;
122 Name typeAttribute = JcrLexicon.PRIMARY_TYPE;
123 Name typeAttributeValue = null;
124 NamespaceRegistry reg = graph.getContext().getNamespaceRegistry();
125 if (reg.isRegisteredNamespaceUri(JcrNtLexicon.Namespace.URI)) {
126 typeAttributeValue = JcrNtLexicon.UNSTRUCTURED;
127 }
128
129 TextDecoder decoder = null;
130 XmlHandler.AttributeScoping scoping = XmlHandler.AttributeScoping.USE_DEFAULT_NAMESPACE;
131 XmlHandler handler = new XmlHandler(destination, skip, parentPath, decoder, nameAttribute, typeAttribute,
132 typeAttributeValue, scoping);
133 try {
134 stream = uri.toURL().openStream();
135 XMLReader reader = XMLReaderFactory.createXMLReader();
136 reader.setContentHandler(handler);
137 reader.setErrorHandler(handler);
138 reader.parse(new InputSource(stream));
139 } finally {
140 if (stream != null) stream.close();
141 }
142 return batch;
143 }
144
145 @NotThreadSafe
146 protected final static class CreateOnGraphInBatch implements Destination {
147 private final Graph.Batch batch;
148
149 protected CreateOnGraphInBatch( Graph.Batch batch ) {
150 assert batch != null;
151 this.batch = batch;
152 }
153
154 public ExecutionContext getExecutionContext() {
155 return batch.getGraph().getContext();
156 }
157
158 public void create( Path path,
159 List<Property> properties ) {
160 assert properties != null;
161 if (properties.isEmpty()) {
162 batch.create(path).and();
163 } else {
164 batch.create(path, properties).and();
165 }
166 }
167
168 public void create( Path path,
169 Property firstProperty,
170 Property... additionalProperties ) {
171 if (firstProperty == null) {
172 batch.create(path).and();
173 } else {
174 batch.create(path, firstProperty, additionalProperties);
175 }
176 }
177
178 public void submit() {
179 }
180 }
181
182 }