View Javadoc
1   /*
2    * Copyright 2020-2022  the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.xml;
18  
19  import java.io.File;
20  import java.net.URL;
21  import java.util.Arrays;
22  import java.util.Collection;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Optional;
26  import javax.xml.transform.Source;
27  import javax.xml.validation.Schema;
28  import javax.xml.validation.SchemaFactory;
29  import org.springframework.core.io.ResourceLoader;
30  import org.w3c.dom.ls.LSResourceResolver;
31  import org.xml.sax.ErrorHandler;
32  
33  /**
34   * The schema builder wraps the standard {@link SchemaFactory} of Java into a builder. It also
35   * offers the ability to load schema using Spring's {@link ResourceLoader}.
36   *
37   * @author Christian Bremer
38   */
39  public interface SchemaBuilder {
40  
41    /**
42     * Creates a new schema builder.
43     *
44     * @return the schema builder
45     */
46    static SchemaBuilder newInstance() {
47      return new SchemaBuilderImpl();
48    }
49  
50    /**
51     * Copy schema builder.
52     *
53     * @return the schema builder
54     */
55    SchemaBuilder copy();
56  
57    /**
58     * Specifies the schema language.
59     *
60     * <p>Default is {@code javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI}
61     * ("http://www.w3.org/2001/XMLSchema").
62     *
63     * @param schemaLanguage specifies the schema language which the used schema factory will
64     *     understand
65     * @return the schema builder
66     * @see SchemaFactory#newInstance(String)
67     */
68    SchemaBuilder withSchemaLanguage(String schemaLanguage);
69  
70    /**
71     * Specifies the factory to use.
72     *
73     * @param factoryClassName the factory class name
74     * @return the schema builder
75     * @see SchemaFactory#newInstance(String, String, ClassLoader)
76     */
77    SchemaBuilder withFactory(String factoryClassName);
78  
79    /**
80     * Specifies the class loader to use.
81     *
82     * @param classLoader the class loader
83     * @return the schema builder
84     * @see SchemaFactory#newInstance(String, String, ClassLoader)
85     */
86    SchemaBuilder withClassLoader(ClassLoader classLoader);
87  
88    /**
89     * Specifies the resource loader to use. The resource loader is used to retrieve the xsd files
90     * that are specified in the schema location (see {@link #fetchSchemaSources(String...)}).
91     *
92     * <p>Default is {@link org.springframework.core.io.DefaultResourceLoader}.
93     *
94     * @param resourceLoader the resource loader
95     * @return the schema builder
96     */
97    SchemaBuilder withResourceLoader(ResourceLoader resourceLoader);
98  
99    /**
100    * Specifies the resource resolver to use.
101    *
102    * @param resourceResolver the resource resolver
103    * @return the schema builder
104    * @see SchemaFactory#setResourceResolver(LSResourceResolver)
105    */
106   SchemaBuilder withResourceResolver(LSResourceResolver resourceResolver);
107 
108   /**
109    * Specifies the error handler to use.
110    *
111    * @param errorHandler the error handler
112    * @return the schema builder
113    * @see SchemaFactory#setErrorHandler(ErrorHandler)
114    */
115   SchemaBuilder withErrorHandler(ErrorHandler errorHandler);
116 
117   /**
118    * Adds a feature to the schema factory.
119    *
120    * @param name the name
121    * @param value the value
122    * @return the schema builder
123    * @see SchemaFactory#setFeature(String, boolean)
124    */
125   SchemaBuilder withFeature(String name, Boolean value);
126 
127   /**
128    * Adds a property to the schema factory.
129    *
130    * @param name the name
131    * @param value the value
132    * @return the schema builder
133    * @see SchemaFactory#setProperty(String, Object)
134    */
135   SchemaBuilder withProperty(String name, Object value);
136 
137   /**
138    * Retrieves the schema files of the specified locations.
139    *
140    * <p>The location can have any format that is supported by the {@link ResourceLoader}.
141    *
142    * @param locations the locations
143    * @return the list
144    * @see #withResourceLoader(ResourceLoader)
145    */
146   default List<Source> fetchSchemaSources(String... locations) {
147     return Optional.ofNullable(locations)
148         .map(a -> fetchSchemaSources(Arrays.asList(a)))
149         .orElseGet(Collections::emptyList);
150   }
151 
152   /**
153    * Retrieves the schema files of the specified locations.
154    *
155    * <p>The location can have any format that is supported by the {@link ResourceLoader}.
156    *
157    * @param locations the locations
158    * @return the schema files as source list
159    * @see #withResourceLoader(ResourceLoader)
160    */
161   List<Source> fetchSchemaSources(Collection<String> locations);
162 
163   /**
164    * Retrieves the schema files of the specified locations and builds the schema.
165    *
166    * <p>The location can have any format that is supported by the {@link ResourceLoader}.
167    *
168    * @param locations the locations
169    * @return the schema
170    */
171   default Schema buildSchema(String... locations) {
172     return Optional.ofNullable(locations)
173         .map(c -> buildSchema(fetchSchemaSources(c)))
174         .orElseGet(() -> buildSchema((Source[]) null));
175   }
176 
177   /**
178    * Builds schema.
179    *
180    * @param url the url
181    * @return the schema
182    * @see SchemaFactory#newSchema(URL)
183    */
184   Schema buildSchema(URL url);
185 
186   /**
187    * Builds schema.
188    *
189    * @param file the file
190    * @return the schema
191    * @see SchemaFactory#newSchema(File)
192    */
193   Schema buildSchema(File file);
194 
195   /**
196    * Builds schema.
197    *
198    * @param source the source
199    * @return the schema
200    * @see SchemaFactory#newSchema(Source)
201    */
202   default Schema buildSchema(Source source) {
203     return Optional.ofNullable(source)
204         .map(s -> buildSchema(new Source[]{s}))
205         .orElseGet(() -> buildSchema((Source[]) null));
206   }
207 
208   /**
209    * Builds schema.
210    *
211    * @param sources the sources
212    * @return the schema
213    * @see SchemaFactory#newSchema(Source[])
214    */
215   Schema buildSchema(Source[] sources);
216 
217   /**
218    * Builds schema.
219    *
220    * @param sources the sources
221    * @return the schema
222    * @see SchemaFactory#newSchema(Source[])
223    */
224   default Schema buildSchema(Collection<? extends Source> sources) {
225     return Optional.ofNullable(sources)
226         .map(c -> buildSchema(c.toArray(new Source[0])))
227         .orElseGet(() -> buildSchema((Source[]) null));
228   }
229 
230 }