This is an automated email from the ASF dual-hosted git repository.

mawiesne pushed a commit to branch 
OPENNLP-1729-Provide-easier-loading-of-Models-for-given-model-lang-and-type
in repository https://gitbox.apache.org/repos/asf/opennlp.git

commit cdfe0aca78e6d4f8644994d4bcde7cc104bbdbf3
Author: Martin Wiesner <[email protected]>
AuthorDate: Mon Apr 28 22:29:16 2025 +0200

    OPENNLP-1729: Provide easier loading of Models for given model lang and type
    - extracts ModelType from DownloadUtil
    - adds new methods to ClassPathModelLoader to obtain actual model instances 
easily
    - adds ClassPathModelProvider interface
    - adds DefaultClassPathModelProvider which combines existing classes to 
achieve easier access to model objects via classpath loading
    - adds JUnit tests for the new classes
    - adds and improves JavaDoc
---
 opennlp-tools-models/pom.xml                       |  12 ++
 .../tools/models/ClassPathLoaderException.java     |  38 ++++++
 .../opennlp/tools/models/ClassPathModelLoader.java |  84 +++++++++++-
 .../tools/models/ClassPathModelProvider.java       |  77 +++++++++++
 .../models/DefaultClassPathModelProvider.java      |  90 +++++++++++++
 .../models/classgraph/ClassgraphModelFinder.java   |   1 +
 .../tools/models/AbstractClassPathFinderTest.java  |   3 +-
 .../tools/models/ClassPathModelLoaderTest.java     |  77 +++++++++++
 .../models/DefaultClassPathModelProviderTest.java  |  96 +++++++++++++
 .../main/java/opennlp/tools/chunker/ChunkerME.java |   3 +-
 .../main/java/opennlp/tools/models/ModelType.java  |  42 ++++++
 .../java/opennlp/tools/postag/POSTaggerME.java     |   3 +-
 .../tools/postag/ThreadSafePOSTaggerME.java        |   3 +-
 .../tools/sentdetect/SentenceDetectorME.java       |   3 +-
 .../sentdetect/ThreadSafeSentenceDetectorME.java   |   3 +-
 .../tools/tokenize/ThreadSafeTokenizerME.java      |   3 +-
 .../java/opennlp/tools/tokenize/TokenizerME.java   |   3 +-
 .../main/java/opennlp/tools/util/DownloadUtil.java |  28 +---
 .../lemmatizer/LemmatizerModelLoaderIT.java        |   3 +-
 .../tools/cmdline/postag/POSModelLoaderIT.java     |   3 +-
 .../cmdline/sentdetect/SentenceModelLoaderIT.java  |   3 +-
 .../cmdline/tokenizer/TokenizerModelLoaderIT.java  |   3 +-
 .../TwentyNewsgroupSampleStreamFactoryTest.java    |   3 +-
 .../brat/BratNameSampleStreamFactoryTest.java      |   3 +-
 .../muc/Muc6NameSampleStreamFactoryTest.java       |   3 +-
 .../opennlp/tools/util/DownloadParserTest.java     | 150 +++++++++++----------
 .../tools/util/DownloadUtilDownloadTwiceTest.java  |   3 +-
 .../java/opennlp/tools/util/DownloadUtilTest.java  |  11 +-
 .../src/test/java/opennlp/uima/AbstractIT.java     |   7 +-
 .../uima/util/AnnotationComparatorTest.java        |   3 +-
 .../java/opennlp/uima/util/AnnotatorUtilTest.java  |   3 +-
 .../java/opennlp/uima/util/OpennlpUtilTest.java    |   3 +-
 .../test/java/opennlp/uima/util/UimaUtilTest.java  |   3 +-
 33 files changed, 644 insertions(+), 129 deletions(-)

diff --git a/opennlp-tools-models/pom.xml b/opennlp-tools-models/pom.xml
index dd403d83..3d1f9188 100644
--- a/opennlp-tools-models/pom.xml
+++ b/opennlp-tools-models/pom.xml
@@ -76,6 +76,18 @@
             <version>${opennlp.models.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.opennlp</groupId>
+            <artifactId>opennlp-models-tokenizer-en</artifactId>
+            <version>${opennlp.models.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.opennlp</groupId>
+            <artifactId>opennlp-models-pos-en</artifactId>
+            <version>${opennlp.models.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.opennlp</groupId>
             <artifactId>opennlp-models-langdetect</artifactId>
diff --git 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathLoaderException.java
 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathLoaderException.java
new file mode 100644
index 00000000..eec5cd09
--- /dev/null
+++ 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathLoaderException.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+import java.io.Serial;
+
+public class ClassPathLoaderException extends RuntimeException {
+
+  @Serial
+  private static final long serialVersionUID = 8858291914366114032L;
+
+  public ClassPathLoaderException(String message) {
+    super(message);
+  }
+
+  public ClassPathLoaderException(Throwable cause) {
+    super(cause);
+  }
+
+  public ClassPathLoaderException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelLoader.java
 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelLoader.java
index 2e51b664..e00c280a 100644
--- 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelLoader.java
+++ 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelLoader.java
@@ -16,14 +16,21 @@
  */
 package opennlp.tools.models;
 
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
 import java.util.Objects;
 import java.util.Properties;
+import java.util.Set;
+
+import opennlp.tools.util.model.BaseModel;
 
 /**
  * Responsible for loading OpenNLP models from the classpath via {@link 
ClassPathModelEntry entries}.
- * If models could be loaded successfully, those are provided as {@link 
ClassPathModel model references}.
+ * If models could be loaded successfully, those are provided as {@link 
ClassPathModel model references}
+ * or as instances of the specified {@link ModelType}.
  *
  * @see ClassPathModel
  * @see ClassPathModelEntry
@@ -37,7 +44,7 @@ public class ClassPathModelLoader {
    *              Moreover, it is validated that the {@link 
ClassPathModelEntry#model() binary data}
    *              and {@link ClassPathModelEntry#properties() meta-data} are 
not {@code null}.
    * @return A {@link ClassPathModel} containing the model resources.
-   * @throws IOException thrown if something went wrong during reading 
resources from the classpath.
+   * @throws IOException Thrown if something went wrong during reading 
resources from the classpath.
    */
   public ClassPathModel load(ClassPathModelEntry entry) throws IOException {
     Objects.requireNonNull(entry, "entry must not be null");
@@ -47,7 +54,7 @@ public class ClassPathModelLoader {
     final Properties properties = new Properties();
 
     if (entry.properties().isPresent()) {
-      try (InputStream inputStream = 
entry.properties().get().toURL().openStream()) {
+      try (InputStream inputStream = new 
BufferedInputStream(entry.properties().get().toURL().openStream())) {
         properties.load(inputStream);
       }
     }
@@ -59,4 +66,75 @@ public class ClassPathModelLoader {
 
     return new ClassPathModel(properties, model);
   }
+
+  /**
+   * Restores a {@link T model} among a set {@link ClassPathModelEntry 
classpath entries}
+   * according to the specified parameters {@code lang} and {@code type}.
+   *
+   * @param classPathEntries A non-empty set of {@link ClassPathModelEntry 
candidates} to find a matching
+   *                         model in. Must not be {@code null}. If it is 
empty, the result will
+   *                         be {@code null}.
+   * @param lang      The language code of the requested model. If {@code 
null}, the result will
+   *                  be {@code null} as well.
+   * @param type      The {@link ModelType} to select the model variant.
+   * @param modelType The class of model type parameter {@link T} to create an 
instance of.
+   *
+   * @return An model instance of type {@link T}, or {@code null} if no match 
was found
+   *         for the specified parameters.
+   *         
+   * @throws IllegalArgumentException Thrown if parameters were invalid.
+   * @throws ClassPathLoaderException Thrown if {@link T} could not be 
instantiated correctly.
+   * @throws IOException Thrown if something went wrong during reading 
resources from the classpath.
+   */
+  <T extends BaseModel> T load(Set<ClassPathModelEntry> classPathEntries, 
String lang,
+                               ModelType type, Class<T> modelType) throws 
IOException {
+    return load(classPathEntries, lang, type.getName(), modelType);
+  }
+
+  /**
+   * Restores a {@link T model} among a set {@link ClassPathModelEntry 
classpath entries}
+   * according to the specified parameters {@code lang} and {@code type}.
+   *
+   * @param classPathEntries A non-empty set of {@link ClassPathModelEntry 
candidates} to find a matching
+   *                         model in. Must not be {@code null}. If it is 
empty, the result will
+   *                         be {@code null}.
+   * @param lang      The language code of the requested model. If {@code 
null}, the result will
+   *                  be {@code null} as well.
+   * @param type      The type string to narrow down the model variant. Note: 
Custom naming patterns
+   *                  can be applied here, as the {@code type} fragment will 
be used for a 'contains'
+   *                  check internally.
+   * @param modelType The class of model type parameter {@link T} to create an 
instance of.
+   *
+   * @return An model instance of type {@link T}, or {@code null} if no match 
was found
+   *         for the specified parameters.
+   *         
+   * @throws IllegalArgumentException Thrown if parameters were invalid.
+   * @throws ClassPathLoaderException Thrown if {@link T} could not be 
instantiated correctly.
+   * @throws IOException Thrown if something went wrong during reading 
resources from the classpath.
+   */
+  <T extends BaseModel> T load(Set<ClassPathModelEntry> classPathEntries, 
String lang,
+                               String type, Class<T> modelType) throws 
IOException {
+    if (classPathEntries == null) {
+      throw new IllegalArgumentException("The provided ClassPath entries must 
not be null!");
+    }
+    T result = null;
+    if (classPathEntries.isEmpty()) {
+      return result;
+    }
+    try {
+      for (ClassPathModelEntry entry : classPathEntries) {
+        final ClassPathModel cpm = load(entry);
+        if (cpm != null && cpm.getModelLanguage().equals(lang) && 
cpm.getModelName().contains(type)) {
+          try (InputStream is = new BufferedInputStream(new 
ByteArrayInputStream(cpm.model()))) {
+            result = 
modelType.getConstructor(InputStream.class).newInstance(is);
+            break; // found a match
+          }
+        }
+      }
+    } catch (InstantiationException | IllegalAccessException |
+             InvocationTargetException | NoSuchMethodException e) {
+      throw new ClassPathLoaderException(e);
+    }
+    return result;
+  }
 }
diff --git 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelProvider.java
 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelProvider.java
new file mode 100644
index 00000000..9640299a
--- /dev/null
+++ 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/ClassPathModelProvider.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+import java.io.IOException;
+
+import opennlp.tools.util.model.BaseModel;
+
+/**
+ * A provider for obtaining pre-trained OpenNLP {@link BaseModel models} from
+ * an application's classpath.
+ * <p>
+ * Providing models available in the classpath requires a {@link 
ClassPathModelFinder finder}
+ * and a {@link ClassPathModelLoader} at runtime. Depending on the environment,
+ * a custom {@code finder} can be used.
+ *
+ * @see BaseModel
+ * @see ClassPathModelFinder
+ * @see ClassPathModelLoader
+ */
+public interface ClassPathModelProvider {
+
+  /**
+   * Restores a {@link T model} among all classpath models at runtime
+   * according to the specified parameters {@code lang} and {@code type}.
+   *
+   * @param lang      The ISO language code of the requested model. If {@code 
null}, the result will
+   *                  be {@code null} as well.
+   * @param type      The type string to narrow down the model variant. Note: 
Custom naming patterns
+   *                  can be applied here, as the {@code type} fragment will 
be used for a 'contains'
+   *                  check internally.
+   * @param modelType The class of model type parameter {@link T} to create an 
instance of.
+   *
+   * @return An model instance of type {@link T}, or {@code null} if no match 
was found
+   *         for the specified parameters.
+   * @throws IllegalArgumentException Thrown if parameters were invalid.
+   * @throws IOException Thrown if something went wrong during reading 
resources from the classpath.
+   */
+  <T extends BaseModel> T load(String lang, ModelType type, Class<T> modelType)
+          throws IOException;
+
+  /**
+   * Restores a {@link T model} among all classpath models at runtime
+   * according to the specified parameters {@code lang} and {@code type}.
+   *
+   * @param lang      The ISO language code of the requested model. If {@code 
null}, the result will
+   *                  be {@code null} as well.
+   * @param type      The type string to narrow down the model variant. Note: 
Custom naming patterns
+   *                  can be applied here, as the {@code type} fragment will 
be used for a 'contains'
+   *                  check internally.
+   * @param modelType The class of model type parameter {@link T} to create an 
instance of.
+   * @param reloadCache {@code true}, if the internal cache of the {@link 
ClassPathModelFinder}
+   *                    should explicitly be reloaded, {@code false} otherwise.
+   *
+   * @return An model instance of type {@link T}, or {@code null} if no match 
was found
+   *         for the specified parameters.
+   * @throws IllegalArgumentException Thrown if parameters were invalid.
+   * @throws IOException Thrown if something went wrong during reading 
resources from the classpath.
+   */
+  <T extends BaseModel> T load(String lang, ModelType type, Class<T> modelType,
+                               boolean reloadCache) throws IOException;
+}
diff --git 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/DefaultClassPathModelProvider.java
 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/DefaultClassPathModelProvider.java
new file mode 100644
index 00000000..ee923e6c
--- /dev/null
+++ 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/DefaultClassPathModelProvider.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+import java.io.IOException;
+
+import opennlp.tools.models.simple.SimpleClassPathModelFinder;
+import opennlp.tools.util.model.BaseModel;
+
+/**
+ * A default implementation of {@link ClassPathModelProvider} which by default 
relies on
+ * {@link SimpleClassPathModelFinder} to scan for models in the current 
classpath.
+ *
+ * @see ClassPathModelFinder
+ * @see ClassPathModelLoader
+ */
+public class DefaultClassPathModelProvider implements ClassPathModelProvider {
+
+  private final ClassPathModelFinder finder;
+  private final ClassPathModelLoader loader;
+
+  /**
+   * Instantiates a {@link DefaultClassPathModelProvider} with a {@link 
SimpleClassPathModelFinder}
+   * and uses a default {@link ClassPathModelLoader}.
+   * By default, it scans for the {@link 
ClassPathModelFinder#OPENNLP_MODEL_JAR_PREFIX} pattern for
+   * available model jars.
+   *
+   * @implNote If you require a different model jar prefix pattern for your 
environment and or
+   *           model file naming strategy, please use
+   *           {@link #DefaultClassPathModelProvider(ClassPathModelFinder, 
ClassPathModelLoader)
+   *           constructor} with two arguments.
+   */
+  public DefaultClassPathModelProvider() {
+    this(new SimpleClassPathModelFinder(), new ClassPathModelLoader());
+  }
+
+  /**
+   * Instantiates a {@link DefaultClassPathModelProvider} with the specified 
{@code modelJarPattern},
+   * a {@link ClassPathModelFinder model finder} and a {@link 
ClassPathModelLoader model loader} instance.
+   *
+   * @param finder          The {@link ClassPathModelFinder} instance to use 
for this provider.
+   *                        It must not be {@code null}.
+   * @param loader          The {@link ClassPathModelLoader} instance to use 
for this provider.
+   *                        It must not be {@code null}.
+   * @throws IllegalArgumentException Thrown if one of the specified 
parameters were invalid.
+   */
+  public DefaultClassPathModelProvider(ClassPathModelFinder finder, 
ClassPathModelLoader loader) {
+    if (finder == null) {
+      throw new IllegalArgumentException("ClassPathModelFinder cannot be 
null.");
+    }
+    if (loader == null) {
+      throw new IllegalArgumentException("ClassPathModelLoader cannot be 
null.");
+    }
+    this.finder = finder;
+    this.loader = loader;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public <T extends BaseModel> T load(String lang, ModelType type, Class<T> 
modelType)
+          throws IOException {
+    return load(lang, type, modelType, false);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public <T extends BaseModel> T load(String lang, ModelType type, Class<T> 
modelType,
+                                      boolean reloadCache) throws IOException {
+    return loader.load(finder.findModels(reloadCache), lang, type, modelType);
+  }
+}
diff --git 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/classgraph/ClassgraphModelFinder.java
 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/classgraph/ClassgraphModelFinder.java
index c440945c..b413f6ee 100644
--- 
a/opennlp-tools-models/src/main/java/opennlp/tools/models/classgraph/ClassgraphModelFinder.java
+++ 
b/opennlp-tools-models/src/main/java/opennlp/tools/models/classgraph/ClassgraphModelFinder.java
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package opennlp.tools.models.classgraph;
 
 import java.net.URI;
diff --git 
a/opennlp-tools-models/src/test/java/opennlp/tools/models/AbstractClassPathFinderTest.java
 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/AbstractClassPathFinderTest.java
index e03f08ce..a9da5e8e 100644
--- 
a/opennlp-tools-models/src/test/java/opennlp/tools/models/AbstractClassPathFinderTest.java
+++ 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/AbstractClassPathFinderTest.java
@@ -26,14 +26,13 @@ import static 
org.junit.jupiter.api.Assertions.assertNotNull;
 
 public abstract class AbstractClassPathFinderTest extends 
AbstractClassPathModelTest {
 
-
   @Test
   public void testFindOpenNLPModels() {
     final ClassPathModelFinder finder = getModelFinder();
 
     final Set<ClassPathModelEntry> models = finder.findModels(false);
     assertNotNull(models);
-    assertEquals(2, models.size());
+    assertEquals(4, models.size());
 
     for (ClassPathModelEntry entry : models) {
       assertNotNull(entry.model());
diff --git 
a/opennlp-tools-models/src/test/java/opennlp/tools/models/ClassPathModelLoaderTest.java
 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/ClassPathModelLoaderTest.java
new file mode 100644
index 00000000..cc979efd
--- /dev/null
+++ 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/ClassPathModelLoaderTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import opennlp.tools.models.simple.SimpleClassPathModelFinder;
+import opennlp.tools.postag.POSModel;
+import opennlp.tools.tokenize.TokenizerModel;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class ClassPathModelLoaderTest {
+
+  // SUT
+  private ClassPathModelLoader loader;
+
+  @BeforeEach
+  void setUp() {
+    loader = new ClassPathModelLoader();
+  }
+
+  @Test
+  void testLoadModelWithEmptyClassPathEntriesShouldReturnNull() throws 
IOException {
+    assertNull(loader.load(Collections.emptySet(), "en", "pos", 
POSModel.class));
+  }
+
+  @Test
+  void testLoadModelWithUnsupportedLanguageCodeShouldReturnNull() throws 
IOException {
+    assertNull(loader.load(Collections.emptySet(), "xy", "pos", 
POSModel.class));
+  }
+
+  @Test
+  void testLoadModelWithIllegalModelTypeShouldReturnNull() throws IOException {
+    assertNull(loader.load(Collections.emptySet(), "en", "xyz", 
POSModel.class));
+  }
+
+  @Test
+  void testLoadModelWithInconsistentClassTypeShouldTrow() {
+    SimpleClassPathModelFinder finder = new SimpleClassPathModelFinder();
+    // Check if a mismatch is correctly detected and thrown
+    assertThrows(ClassPathLoaderException.class, () ->
+            loader.load(finder.findModels(true), "en", "pos", 
TokenizerModel.class));
+  }
+
+  @Test
+  void testLoadModelWithIllegalArguments1() {
+    assertThrows(IllegalArgumentException.class, ()
+            -> loader.load(null, "en", "pos", POSModel.class));
+  }
+
+  @Test
+  void testLoadModelWithIllegalArguments2() {
+    assertThrows(IllegalArgumentException.class, ()
+            -> loader.load(null, "en", ModelType.POS_GENERIC, POSModel.class));
+  }
+}
diff --git 
a/opennlp-tools-models/src/test/java/opennlp/tools/models/DefaultClassPathModelProviderTest.java
 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/DefaultClassPathModelProviderTest.java
new file mode 100644
index 00000000..f8a027ca
--- /dev/null
+++ 
b/opennlp-tools-models/src/test/java/opennlp/tools/models/DefaultClassPathModelProviderTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+import java.io.IOException;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import opennlp.tools.models.simple.SimpleClassPathModelFinder;
+import opennlp.tools.postag.POSModel;
+import opennlp.tools.sentdetect.SentenceModel;
+import opennlp.tools.tokenize.TokenizerModel;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class DefaultClassPathModelProviderTest {
+
+  private static SimpleClassPathModelFinder finder;
+  private static ClassPathModelLoader loader;
+
+  // SUT
+  private DefaultClassPathModelProvider provider;
+
+  @BeforeAll
+  public static void initEnv() {
+    finder = new SimpleClassPathModelFinder();
+    loader = new ClassPathModelLoader();
+  }
+
+  @BeforeEach
+  void setup() {
+    provider = new DefaultClassPathModelProvider(finder, loader);
+  }
+
+  @Test
+  void testLoadSentenceModel() throws IOException {
+    SentenceModel m = provider.load("en", ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+    assertNotNull(m);
+    assertTrue(m.isLoadedFromSerialized());
+  }
+
+  @Test
+  void testLoadTokenizerModel() throws IOException {
+    TokenizerModel m = provider.load("en", ModelType.TOKENIZER, 
TokenizerModel.class);
+    assertNotNull(m);
+    assertTrue(m.isLoadedFromSerialized());
+  }
+
+  @Test
+  void testLoadPOSModel() throws IOException {
+    POSModel m = provider.load("en", ModelType.POS_GENERIC, POSModel.class);
+    assertNotNull(m);
+    assertTrue(m.isLoadedFromSerialized());
+  }
+
+  @Test
+  void testCreateInstance() {
+    try {
+      new DefaultClassPathModelProvider();
+    } catch (RuntimeException e) {
+      fail(e.getLocalizedMessage(), e);
+    }
+  }
+
+  @Test
+  void testCreateInstanceWithIllegalParameters1() {
+    assertThrows(IllegalArgumentException.class, () ->
+            new DefaultClassPathModelProvider(finder, null));
+  }
+
+  @Test
+  void testCreateInstanceWithIllegalParameters2() {
+    assertThrows(IllegalArgumentException.class, () ->
+            new DefaultClassPathModelProvider(null, loader));
+  }
+}
diff --git a/opennlp-tools/src/main/java/opennlp/tools/chunker/ChunkerME.java 
b/opennlp-tools/src/main/java/opennlp/tools/chunker/ChunkerME.java
index e036742e..d0daf86b 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/chunker/ChunkerME.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/chunker/ChunkerME.java
@@ -30,6 +30,7 @@ import opennlp.tools.ml.TrainerFactory.TrainerType;
 import opennlp.tools.ml.model.Event;
 import opennlp.tools.ml.model.MaxentModel;
 import opennlp.tools.ml.model.SequenceClassificationModel;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.ObjectStream;
 import opennlp.tools.util.Sequence;
@@ -63,7 +64,7 @@ public class ChunkerME implements Chunker {
    * @throws IOException Thrown if the model cannot be downloaded or saved.
    */
   public ChunkerME(String language) throws IOException {
-    this(DownloadUtil.downloadModel(language, DownloadUtil.ModelType.CHUNKER, 
ChunkerModel.class));
+    this(DownloadUtil.downloadModel(language, ModelType.CHUNKER, 
ChunkerModel.class));
   }
 
   /**
diff --git a/opennlp-tools/src/main/java/opennlp/tools/models/ModelType.java 
b/opennlp-tools/src/main/java/opennlp/tools/models/ModelType.java
new file mode 100644
index 00000000..6e863157
--- /dev/null
+++ b/opennlp-tools/src/main/java/opennlp/tools/models/ModelType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package opennlp.tools.models;
+
+/**
+ * A model type to  pattern enumeration.
+ */
+public enum ModelType {
+  LEMMATIZER("lemma"),
+  TOKENIZER("token"),
+  SENTENCE_DETECTOR("sent"),
+  POS("pos-perceptron"),
+  POS_GENERIC("pos"),
+  NAME_FINDER("ner"),
+  CHUNKER("chunker"),
+  PARSER("parser-chunking");
+
+  private final String name;
+
+  ModelType(String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+}
diff --git a/opennlp-tools/src/main/java/opennlp/tools/postag/POSTaggerME.java 
b/opennlp-tools/src/main/java/opennlp/tools/postag/POSTaggerME.java
index a85ceb55..c3c03a12 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/postag/POSTaggerME.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/postag/POSTaggerME.java
@@ -39,6 +39,7 @@ import opennlp.tools.ml.TrainerFactory.TrainerType;
 import opennlp.tools.ml.model.Event;
 import opennlp.tools.ml.model.MaxentModel;
 import opennlp.tools.ml.model.SequenceClassificationModel;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.ngram.NGramModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.ObjectStream;
@@ -115,7 +116,7 @@ public class POSTaggerME implements POSTagger {
    * @throws IOException Thrown if the model could not be downloaded or saved.
    */
   public POSTaggerME(String language, POSTagFormat format) throws IOException {
-    this(DownloadUtil.downloadModel(language, DownloadUtil.ModelType.POS, 
POSModel.class), format);
+    this(DownloadUtil.downloadModel(language, ModelType.POS, POSModel.class), 
format);
   }
 
   /**
diff --git 
a/opennlp-tools/src/main/java/opennlp/tools/postag/ThreadSafePOSTaggerME.java 
b/opennlp-tools/src/main/java/opennlp/tools/postag/ThreadSafePOSTaggerME.java
index a1e29283..39ad425e 100644
--- 
a/opennlp-tools/src/main/java/opennlp/tools/postag/ThreadSafePOSTaggerME.java
+++ 
b/opennlp-tools/src/main/java/opennlp/tools/postag/ThreadSafePOSTaggerME.java
@@ -20,6 +20,7 @@ package opennlp.tools.postag;
 import java.io.IOException;
 
 import opennlp.tools.commons.ThreadSafe;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.Sequence;
 
@@ -68,7 +69,7 @@ public class ThreadSafePOSTaggerME implements POSTagger, 
AutoCloseable {
    * @throws IOException Thrown if the model could not be downloaded or saved.
    */
   public ThreadSafePOSTaggerME(String language, POSTagFormat format) throws 
IOException {
-    this(DownloadUtil.downloadModel(language, DownloadUtil.ModelType.POS, 
POSModel.class), format);
+    this(DownloadUtil.downloadModel(language, ModelType.POS, POSModel.class), 
format);
   }
 
   /**
diff --git 
a/opennlp-tools/src/main/java/opennlp/tools/sentdetect/SentenceDetectorME.java 
b/opennlp-tools/src/main/java/opennlp/tools/sentdetect/SentenceDetectorME.java
index 1908b02f..5fbf9de6 100644
--- 
a/opennlp-tools/src/main/java/opennlp/tools/sentdetect/SentenceDetectorME.java
+++ 
b/opennlp-tools/src/main/java/opennlp/tools/sentdetect/SentenceDetectorME.java
@@ -31,6 +31,7 @@ import opennlp.tools.ml.EventTrainer;
 import opennlp.tools.ml.TrainerFactory;
 import opennlp.tools.ml.model.Event;
 import opennlp.tools.ml.model.MaxentModel;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.lang.Factory;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.ObjectStream;
@@ -91,7 +92,7 @@ public class SentenceDetectorME implements SentenceDetector {
    */
   public SentenceDetectorME(String language) throws IOException {
     this(DownloadUtil.downloadModel(language,
-            DownloadUtil.ModelType.SENTENCE_DETECTOR, SentenceModel.class));
+            ModelType.SENTENCE_DETECTOR, SentenceModel.class));
   }
 
   /**
diff --git 
a/opennlp-tools/src/main/java/opennlp/tools/sentdetect/ThreadSafeSentenceDetectorME.java
 
b/opennlp-tools/src/main/java/opennlp/tools/sentdetect/ThreadSafeSentenceDetectorME.java
index 6cff0a0a..dae891c4 100644
--- 
a/opennlp-tools/src/main/java/opennlp/tools/sentdetect/ThreadSafeSentenceDetectorME.java
+++ 
b/opennlp-tools/src/main/java/opennlp/tools/sentdetect/ThreadSafeSentenceDetectorME.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import opennlp.tools.commons.ThreadSafe;
 import opennlp.tools.dictionary.Dictionary;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.Span;
 
@@ -56,7 +57,7 @@ public class ThreadSafeSentenceDetectorME implements 
SentenceDetector, AutoClose
    * @throws IOException Thrown if the model could not be downloaded or saved.
    */
   public ThreadSafeSentenceDetectorME(String language) throws IOException {
-    this(DownloadUtil.downloadModel(language, 
DownloadUtil.ModelType.SENTENCE_DETECTOR, SentenceModel.class));
+    this(DownloadUtil.downloadModel(language, ModelType.SENTENCE_DETECTOR, 
SentenceModel.class));
   }
 
   /**
diff --git 
a/opennlp-tools/src/main/java/opennlp/tools/tokenize/ThreadSafeTokenizerME.java 
b/opennlp-tools/src/main/java/opennlp/tools/tokenize/ThreadSafeTokenizerME.java
index 2f105fb1..6915f5fb 100644
--- 
a/opennlp-tools/src/main/java/opennlp/tools/tokenize/ThreadSafeTokenizerME.java
+++ 
b/opennlp-tools/src/main/java/opennlp/tools/tokenize/ThreadSafeTokenizerME.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 
 import opennlp.tools.commons.ThreadSafe;
 import opennlp.tools.dictionary.Dictionary;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.Span;
 
@@ -56,7 +57,7 @@ public class ThreadSafeTokenizerME implements Tokenizer, 
AutoCloseable {
    * @throws IOException Thrown if the model could not be downloaded or saved.
    */
   public ThreadSafeTokenizerME(String language) throws IOException {
-    this(DownloadUtil.downloadModel(language, 
DownloadUtil.ModelType.TOKENIZER, TokenizerModel.class));
+    this(DownloadUtil.downloadModel(language, ModelType.TOKENIZER, 
TokenizerModel.class));
   }
 
   /**
diff --git 
a/opennlp-tools/src/main/java/opennlp/tools/tokenize/TokenizerME.java 
b/opennlp-tools/src/main/java/opennlp/tools/tokenize/TokenizerME.java
index a617108f..3fcb6a0d 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/tokenize/TokenizerME.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/tokenize/TokenizerME.java
@@ -30,6 +30,7 @@ import opennlp.tools.ml.EventTrainer;
 import opennlp.tools.ml.TrainerFactory;
 import opennlp.tools.ml.model.Event;
 import opennlp.tools.ml.model.MaxentModel;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.ObjectStream;
 import opennlp.tools.util.Span;
@@ -120,7 +121,7 @@ public class TokenizerME extends AbstractTokenizer {
    * @throws IOException Thrown if the model cannot be downloaded or saved.
    */
   public TokenizerME(String language) throws IOException {
-    this(DownloadUtil.downloadModel(language, DownloadUtil.ModelType.TOKENIZER,
+    this(DownloadUtil.downloadModel(language, ModelType.TOKENIZER,
             TokenizerModel.class));
   }
 
diff --git a/opennlp-tools/src/main/java/opennlp/tools/util/DownloadUtil.java 
b/opennlp-tools/src/main/java/opennlp/tools/util/DownloadUtil.java
index cd80792f..7a6244fb 100644
--- a/opennlp-tools/src/main/java/opennlp/tools/util/DownloadUtil.java
+++ b/opennlp-tools/src/main/java/opennlp/tools/util/DownloadUtil.java
@@ -45,6 +45,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import opennlp.tools.commons.Internal;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.model.BaseModel;
 
 /**
@@ -54,25 +55,6 @@ public class DownloadUtil {
 
   private static final Logger logger = 
LoggerFactory.getLogger(DownloadUtil.class);
 
-  /**
-   * The type of model.
-   */
-  public enum ModelType {
-    LEMMATIZER("lemma"),
-    TOKENIZER("token"),
-    SENTENCE_DETECTOR("sent"),
-    POS("pos-perceptron"),
-    NAME_FINDER("ner"),
-    CHUNKER("chunker"),
-    PARSER("parser-chunking");
-
-    private final String name;
-
-    ModelType(String name) {
-      this.name = name;
-    }
-  }
-
   private static final String BASE_URL =
       System.getProperty("OPENNLP_DOWNLOAD_BASE_URL", 
"https://dlcdn.apache.org/opennlp/";);
   private static final String MODEL_URI_PATH =
@@ -86,7 +68,7 @@ public class DownloadUtil {
    * for a particular {@code language}.
    *
    * @param language  The ISO language code of the requested model.
-   * @param modelType The {@link DownloadUtil.ModelType type} of model.
+   * @param modelType The {@link ModelType type} of model.
    * @return {@code true} if a model exists locally, {@code false} otherwise.
    * @throws IOException Thrown if IO errors occurred or the computed hash sum
    * of an associated, local model file was incorrect.
@@ -117,10 +99,10 @@ public class DownloadUtil {
   }
 
   /**
-   * Triggers a download for the specified {@link DownloadUtil.ModelType}.
+   * Triggers a download for the specified {@link ModelType}.
    *
    * @param language  The ISO language code of the requested model.
-   * @param modelType The {@link DownloadUtil.ModelType type} of model.
+   * @param modelType The {@link ModelType type} of model.
    * @param type      The class of the resulting model.
    * @param <T>       The generic type which is a subclass of {@link 
BaseModel}.
    * @return A model instance of type {@link T}.
@@ -136,7 +118,7 @@ public class DownloadUtil {
       }
     }
 
-    throw new IOException("There is no model available: " + language + " " + 
modelType.name);
+    throw new IOException("There is no model available: " + language + " " + 
modelType.getName());
   }
 
   /**
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/lemmatizer/LemmatizerModelLoaderIT.java
 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/lemmatizer/LemmatizerModelLoaderIT.java
index c34d186a..da19b5e9 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/lemmatizer/LemmatizerModelLoaderIT.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/lemmatizer/LemmatizerModelLoaderIT.java
@@ -29,6 +29,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 import opennlp.tools.AbstractModelLoaderTest;
 import opennlp.tools.EnabledWhenCDNAvailable;
 import opennlp.tools.lemmatizer.LemmatizerModel;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.util.DownloadUtil;
 
 @EnabledWhenCDNAvailable(hostname = "dlcdn.apache.org")
@@ -41,7 +42,7 @@ public class LemmatizerModelLoaderIT extends 
AbstractModelLoaderTest {
   public static void initResources() {
     SUPPORTED_LANG_CODES.forEach(lang -> {
       try {
-        DownloadUtil.downloadModel(lang, DownloadUtil.ModelType.LEMMATIZER, 
LemmatizerModel.class);
+        DownloadUtil.downloadModel(lang, ModelType.LEMMATIZER, 
LemmatizerModel.class);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/postag/POSModelLoaderIT.java
 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/postag/POSModelLoaderIT.java
index 06ae24d7..65793232 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/postag/POSModelLoaderIT.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/postag/POSModelLoaderIT.java
@@ -28,6 +28,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.AbstractModelLoaderTest;
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.postag.POSModel;
 import opennlp.tools.util.DownloadUtil;
 
@@ -41,7 +42,7 @@ public class POSModelLoaderIT extends AbstractModelLoaderTest 
{
   public static void initResources() {
     SUPPORTED_LANG_CODES.forEach(lang -> {
       try {
-        DownloadUtil.downloadModel(lang, DownloadUtil.ModelType.POS, 
POSModel.class);
+        DownloadUtil.downloadModel(lang, ModelType.POS, POSModel.class);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/sentdetect/SentenceModelLoaderIT.java
 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/sentdetect/SentenceModelLoaderIT.java
index 7440b6fe..a061bda6 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/sentdetect/SentenceModelLoaderIT.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/sentdetect/SentenceModelLoaderIT.java
@@ -28,6 +28,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.AbstractModelLoaderTest;
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.util.DownloadUtil;
 
@@ -41,7 +42,7 @@ public class SentenceModelLoaderIT extends 
AbstractModelLoaderTest {
   public static void initResources() {
     SUPPORTED_LANG_CODES.forEach(lang -> {
       try {
-        DownloadUtil.downloadModel(lang, 
DownloadUtil.ModelType.SENTENCE_DETECTOR, SentenceModel.class);
+        DownloadUtil.downloadModel(lang, ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/tokenizer/TokenizerModelLoaderIT.java
 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/tokenizer/TokenizerModelLoaderIT.java
index e482dd65..7c3067bf 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/cmdline/tokenizer/TokenizerModelLoaderIT.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/cmdline/tokenizer/TokenizerModelLoaderIT.java
@@ -28,6 +28,7 @@ import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.AbstractModelLoaderTest;
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.tokenize.TokenizerModel;
 import opennlp.tools.util.DownloadUtil;
 
@@ -41,7 +42,7 @@ public class TokenizerModelLoaderIT extends 
AbstractModelLoaderTest {
   public static void initResources() {
     SUPPORTED_LANG_CODES.forEach(lang -> {
       try {
-        DownloadUtil.downloadModel(lang, DownloadUtil.ModelType.TOKENIZER, 
TokenizerModel.class);
+        DownloadUtil.downloadModel(lang, ModelType.TOKENIZER, 
TokenizerModel.class);
       } catch (IOException e) {
         throw new RuntimeException(e);
       }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/formats/TwentyNewsgroupSampleStreamFactoryTest.java
 
b/opennlp-tools/src/test/java/opennlp/tools/formats/TwentyNewsgroupSampleStreamFactoryTest.java
index d07f1ece..7b12a705 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/formats/TwentyNewsgroupSampleStreamFactoryTest.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/formats/TwentyNewsgroupSampleStreamFactoryTest.java
@@ -33,6 +33,7 @@ import opennlp.tools.cmdline.ObjectStreamFactory;
 import opennlp.tools.cmdline.StreamFactoryRegistry;
 import opennlp.tools.cmdline.TerminateToolException;
 import opennlp.tools.doccat.DocumentSample;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.tokenize.TokenizerModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.ObjectStream;
@@ -72,7 +73,7 @@ public class TwentyNewsgroupSampleStreamFactoryTest extends
     TwentyNewsgroupSampleStreamFactory.registerFactory();
     try {
       // ensure, the model is available locally for later test purposes
-      DownloadUtil.downloadModel("en", DownloadUtil.ModelType.TOKENIZER, 
TokenizerModel.class);
+      DownloadUtil.downloadModel("en", ModelType.TOKENIZER, 
TokenizerModel.class);
     } catch (IOException e) {
       fail(e.getLocalizedMessage());
     }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/formats/brat/BratNameSampleStreamFactoryTest.java
 
b/opennlp-tools/src/test/java/opennlp/tools/formats/brat/BratNameSampleStreamFactoryTest.java
index edfbd844..8f9eb50a 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/formats/brat/BratNameSampleStreamFactoryTest.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/formats/brat/BratNameSampleStreamFactoryTest.java
@@ -34,6 +34,7 @@ import opennlp.tools.cmdline.StreamFactoryRegistry;
 import opennlp.tools.cmdline.TerminateToolException;
 import opennlp.tools.formats.AbstractSampleStreamFactory;
 import opennlp.tools.formats.AbstractSampleStreamFactoryTest;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.namefind.NameSample;
 import opennlp.tools.tokenize.TokenizerModel;
 import opennlp.tools.util.DownloadUtil;
@@ -76,7 +77,7 @@ public class BratNameSampleStreamFactoryTest extends
     BratNameSampleStreamFactory.registerFactory();
     try {
       // ensure, the model is available locally for later test purposes
-      DownloadUtil.downloadModel("en", DownloadUtil.ModelType.TOKENIZER, 
TokenizerModel.class);
+      DownloadUtil.downloadModel("en", ModelType.TOKENIZER, 
TokenizerModel.class);
     } catch (IOException e) {
       fail(e.getLocalizedMessage());
     }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/formats/muc/Muc6NameSampleStreamFactoryTest.java
 
b/opennlp-tools/src/test/java/opennlp/tools/formats/muc/Muc6NameSampleStreamFactoryTest.java
index ffe1c0a6..f2857302 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/formats/muc/Muc6NameSampleStreamFactoryTest.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/formats/muc/Muc6NameSampleStreamFactoryTest.java
@@ -31,6 +31,7 @@ import opennlp.tools.cmdline.StreamFactoryRegistry;
 import opennlp.tools.cmdline.TerminateToolException;
 import opennlp.tools.formats.AbstractSampleStreamFactory;
 import opennlp.tools.formats.AbstractSampleStreamFactoryTest;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.namefind.NameSample;
 import opennlp.tools.tokenize.TokenizerModel;
 import opennlp.tools.util.DownloadUtil;
@@ -70,7 +71,7 @@ public class Muc6NameSampleStreamFactoryTest extends
     Muc6NameSampleStreamFactory.registerFactory();
     try {
       // ensure, the model is available locally for later test purposes
-      DownloadUtil.downloadModel("en", DownloadUtil.ModelType.TOKENIZER, 
TokenizerModel.class);
+      DownloadUtil.downloadModel("en", ModelType.TOKENIZER, 
TokenizerModel.class);
     } catch (IOException e) {
       fail(e.getLocalizedMessage());
     }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadParserTest.java 
b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadParserTest.java
index 6276d272..dfff59c5 100644
--- a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadParserTest.java
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadParserTest.java
@@ -27,6 +27,8 @@ import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
+import opennlp.tools.models.ModelType;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -35,22 +37,22 @@ public class DownloadParserTest {
 
   @ParameterizedTest(name = "Verify \"{0}\" available models")
   @MethodSource(value = "expectedModels")
-  void testAvailableModels(String language, Map<DownloadUtil.ModelType, 
String> expectedModels) {
+  void testAvailableModels(String language, Map<ModelType, String> 
expectedModels) {
 
     final URL baseUrl = fromClasspath("opennlp/tools/util/index.html");
     assertNotNull(baseUrl);
 
     final DownloadUtil.DownloadParser downloadParser = new 
DownloadUtil.DownloadParser(baseUrl);
 
-    Map<String, Map<DownloadUtil.ModelType, String>> result = 
downloadParser.getAvailableModels();
+    Map<String, Map<ModelType, String>> result = 
downloadParser.getAvailableModels();
 
     assertNotNull(result);
     assertEquals(32, result.size());
 
-    final Map<DownloadUtil.ModelType, String> availableModels = 
result.get(language);
+    final Map<ModelType, String> availableModels = result.get(language);
     assertNotNull(availableModels);
 
-    for (Map.Entry<DownloadUtil.ModelType, String> e : 
expectedModels.entrySet()) {
+    for (Map.Entry<ModelType, String> e : expectedModels.entrySet()) {
       final String url = availableModels.get(e.getKey());
       final String expectedUrl = baseUrl + "/" + e.getValue();
 
@@ -69,7 +71,7 @@ public class DownloadParserTest {
   void testInvalidUrl() throws MalformedURLException {
     final DownloadUtil.DownloadParser downloadParser =
         new DownloadUtil.DownloadParser(new URL("file:/this/does/not/exist"));
-    Map<String, Map<DownloadUtil.ModelType, String>> result = 
downloadParser.getAvailableModels();
+    Map<String, Map<ModelType, String>> result = 
downloadParser.getAvailableModels();
     assertNotNull(result);
     assertEquals(0, result.size());
   }
@@ -90,97 +92,97 @@ public class DownloadParserTest {
     // Data as defined in "test/resources/opennlp/tools/util/index.html"
     return Stream.of(
       Arguments.of("en",Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "en-ud-ewt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "en-ud-ewt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "en-ud-ewt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "en-ud-ewt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "en-ud-ewt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "en-ud-ewt-" + MODEL_POS + VER + BIN)),
       Arguments.of("fr", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "fr-ud-gsd-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "fr-ud-gsd-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "fr-ud-gsd-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "fr-ud-gsd-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "fr-ud-gsd-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "fr-ud-gsd-" + MODEL_POS + VER + BIN)),
       Arguments.of("de", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "de-ud-gsd-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "de-ud-gsd-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "de-ud-gsd-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "de-ud-gsd-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "de-ud-gsd-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "de-ud-gsd-" + MODEL_POS + VER + BIN)),
       Arguments.of("it", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "it-ud-vit-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "it-ud-vit-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "it-ud-vit-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "it-ud-vit-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "it-ud-vit-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "it-ud-vit-" + MODEL_POS + VER + BIN)),
       Arguments.of("nl", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "nl-ud-alpino-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "nl-ud-alpino-" + 
MODEL_TOK + VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "nl-ud-alpino-" + MODEL_POS + 
VER + BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "nl-ud-alpino-" + MODEL_SENT + 
VER + BIN,
+        ModelType.TOKENIZER, OPENNLP + "nl-ud-alpino-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "nl-ud-alpino-" + MODEL_POS + VER + BIN)),
       Arguments.of("bg", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "bg-ud-btb-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "bg-ud-btb-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "bg-ud-btb-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "bg-ud-btb-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "bg-ud-btb-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "bg-ud-btb-" + MODEL_POS + VER + BIN)),
       Arguments.of("cs", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "cs-ud-pdt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "cs-ud-pdt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "cs-ud-pdt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "cs-ud-pdt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "cs-ud-pdt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "cs-ud-pdt-" + MODEL_POS + VER + BIN)),
       Arguments.of("da", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "da-ud-ddt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "da-ud-ddt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "da-ud-ddt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "da-ud-ddt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "da-ud-ddt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "da-ud-ddt-" + MODEL_POS + VER + BIN)),
       Arguments.of("es", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "es-ud-gsd-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "es-ud-gsd-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "es-ud-gsd-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "es-ud-gsd-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "es-ud-gsd-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "es-ud-gsd-" + MODEL_POS + VER + BIN)),
       Arguments.of("et", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "et-ud-edt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "et-ud-edt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "et-ud-edt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "et-ud-edt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "et-ud-edt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "et-ud-edt-" + MODEL_POS + VER + BIN)),
       Arguments.of("fi", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "fi-ud-tdt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "fi-ud-tdt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "fi-ud-tdt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "fi-ud-tdt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "fi-ud-tdt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "fi-ud-tdt-" + MODEL_POS + VER + BIN)),
       Arguments.of("hr", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "hr-ud-set-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "hr-ud-set-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "hr-ud-set-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "hr-ud-set-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "hr-ud-set-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "hr-ud-set-" + MODEL_POS + VER + BIN)),
       Arguments.of("lv", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "lv-ud-lvtb-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "lv-ud-lvtb-" + MODEL_TOK 
+ VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "lv-ud-lvtb-" + MODEL_POS + VER 
+ BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "lv-ud-lvtb-" + MODEL_SENT + 
VER + BIN,
+        ModelType.TOKENIZER, OPENNLP + "lv-ud-lvtb-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "lv-ud-lvtb-" + MODEL_POS + VER + BIN)),
       Arguments.of("no", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "no-ud-bokmaal-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "no-ud-bokmaal-" + 
MODEL_TOK + VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "no-ud-bokmaal-" + MODEL_POS + 
VER + BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "no-ud-bokmaal-" + MODEL_SENT + 
VER + BIN,
+        ModelType.TOKENIZER, OPENNLP + "no-ud-bokmaal-" + MODEL_TOK + VER + 
BIN,
+        ModelType.POS, OPENNLP + "no-ud-bokmaal-" + MODEL_POS + VER + BIN)),
       Arguments.of("pl", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "pl-ud-pdb-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "pl-ud-pdb-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "pl-ud-pdb-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "pl-ud-pdb-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "pl-ud-pdb-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "pl-ud-pdb-" + MODEL_POS + VER + BIN)),
       Arguments.of("pt", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "pt-ud-gsd-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "pt-ud-gsd-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "pt-ud-gsd-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "pt-ud-gsd-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "pt-ud-gsd-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "pt-ud-gsd-" + MODEL_POS + VER + BIN)),
       Arguments.of("ro", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "ro-ud-rrt-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "ro-ud-rrt-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "ro-ud-rrt-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "ro-ud-rrt-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "ro-ud-rrt-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "ro-ud-rrt-" + MODEL_POS + VER + BIN)),
       Arguments.of("ru", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "ru-ud-gsd-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "ru-ud-gsd-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "ru-ud-gsd-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "ru-ud-gsd-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "ru-ud-gsd-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "ru-ud-gsd-" + MODEL_POS + VER + BIN)),
       Arguments.of("sr", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "sr-ud-set-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "sr-ud-set-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "sr-ud-set-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "sr-ud-set-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "sr-ud-set-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "sr-ud-set-" + MODEL_POS + VER + BIN)),
       Arguments.of("sk", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "sk-ud-snk-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "sk-ud-snk-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "sk-ud-snk-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "sk-ud-snk-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "sk-ud-snk-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "sk-ud-snk-" + MODEL_POS + VER + BIN)),
       Arguments.of("sl", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "sl-ud-ssj-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "sl-ud-ssj-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "sl-ud-ssj-" + MODEL_POS + VER + 
BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "sl-ud-ssj-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "sl-ud-ssj-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "sl-ud-ssj-" + MODEL_POS + VER + BIN)),
       Arguments.of("sv", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "sv-ud-talbanken-" 
+ MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "sv-ud-talbanken-" + 
MODEL_TOK + VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "sv-ud-talbanken-" + MODEL_POS + 
VER + BIN)),
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "sv-ud-talbanken-" + MODEL_SENT 
+ VER + BIN,
+        ModelType.TOKENIZER, OPENNLP + "sv-ud-talbanken-" + MODEL_TOK + VER + 
BIN,
+        ModelType.POS, OPENNLP + "sv-ud-talbanken-" + MODEL_POS + VER + BIN)),
       Arguments.of("uk", Map.of(
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, OPENNLP + "uk-ud-iu-" + 
MODEL_SENT + VER + BIN,
-        DownloadUtil.ModelType.TOKENIZER, OPENNLP + "uk-ud-iu-" + MODEL_TOK + 
VER + BIN,
-        DownloadUtil.ModelType.POS, OPENNLP + "uk-ud-iu-" + MODEL_POS + VER + 
BIN))
+        ModelType.SENTENCE_DETECTOR, OPENNLP + "uk-ud-iu-" + MODEL_SENT + VER 
+ BIN,
+        ModelType.TOKENIZER, OPENNLP + "uk-ud-iu-" + MODEL_TOK + VER + BIN,
+        ModelType.POS, OPENNLP + "uk-ud-iu-" + MODEL_POS + VER + BIN))
     );
   }
 }
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilDownloadTwiceTest.java
 
b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilDownloadTwiceTest.java
index 24bad516..a9982ecc 100644
--- 
a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilDownloadTwiceTest.java
+++ 
b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilDownloadTwiceTest.java
@@ -30,6 +30,7 @@ import org.junit.jupiter.api.Test;
 import org.slf4j.LoggerFactory;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -61,7 +62,7 @@ public class DownloadUtilDownloadTwiceTest {
   @Test
   public void testDownloadModelTwice() throws IOException {
     String lang = "de";
-    DownloadUtil.ModelType type = DownloadUtil.ModelType.SENTENCE_DETECTOR;
+    ModelType type = ModelType.SENTENCE_DETECTOR;
     
     try (LogCaptor logCaptor = LogCaptor.forClass(DownloadUtil.class)) {
       boolean alreadyDownloaded = DownloadUtil.existsModel(lang, type);
diff --git 
a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilTest.java 
b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilTest.java
index c5355601..f92ada9c 100644
--- a/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilTest.java
+++ b/opennlp-tools/src/test/java/opennlp/tools/util/DownloadUtilTest.java
@@ -29,6 +29,7 @@ import org.junit.jupiter.params.provider.NullAndEmptySource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.tokenize.TokenizerModel;
 
@@ -48,7 +49,7 @@ public class DownloadUtilTest {
   @EnabledWhenCDNAvailable(hostname = "dlcdn.apache.org")
   public void testDownloadModelByLanguage(String lang) throws IOException {
     SentenceModel model = DownloadUtil.downloadModel(lang,
-        DownloadUtil.ModelType.SENTENCE_DETECTOR, SentenceModel.class);
+        ModelType.SENTENCE_DETECTOR, SentenceModel.class);
     assertNotNull(model);
     assertEquals(lang, model.getLanguage());
     assertTrue(model.isLoadedFromSerialized());
@@ -68,7 +69,7 @@ public class DownloadUtilTest {
   @EnabledWhenCDNAvailable(hostname = "dlcdn.apache.org")
   public void testExistsModel() throws IOException {
     final String lang = "en";
-    final DownloadUtil.ModelType type = 
DownloadUtil.ModelType.SENTENCE_DETECTOR;
+    final ModelType type = ModelType.SENTENCE_DETECTOR;
     // Prepare
     SentenceModel model = DownloadUtil.downloadModel(lang, type, 
SentenceModel.class);
     assertNotNull(model);
@@ -82,7 +83,7 @@ public class DownloadUtilTest {
   @ValueSource(strings = {"xy", "\t", "\n"})
   @EnabledWhenCDNAvailable(hostname = "dlcdn.apache.org")
   public void testExistsModelInvalid(String input) throws IOException {
-    assertFalse(DownloadUtil.existsModel(input, 
DownloadUtil.ModelType.SENTENCE_DETECTOR));
+    assertFalse(DownloadUtil.existsModel(input, ModelType.SENTENCE_DETECTOR));
   }
 
   @ParameterizedTest(name = "Detect invalid input: \"{0}\"")
@@ -90,10 +91,10 @@ public class DownloadUtilTest {
   @ValueSource(strings = {" ", "\t", "\n"})
   public void testDownloadModelInvalid(String input) {
     assertThrows(IOException.class, () -> DownloadUtil.downloadModel(input,
-            DownloadUtil.ModelType.SENTENCE_DETECTOR, SentenceModel.class), 
"Invalid model");
+            ModelType.SENTENCE_DETECTOR, SentenceModel.class), "Invalid 
model");
   }
 
-  private static final DownloadUtil.ModelType MT_TOKENIZER = 
DownloadUtil.ModelType.TOKENIZER;
+  private static final ModelType MT_TOKENIZER = ModelType.TOKENIZER;
 
   // Note: This needs to be public as JUnit 5 requires it like this.
   public static Stream<Arguments> provideURLs() {
diff --git a/opennlp-uima/src/test/java/opennlp/uima/AbstractIT.java 
b/opennlp-uima/src/test/java/opennlp/uima/AbstractIT.java
index 1295dead..39c27387 100644
--- a/opennlp-uima/src/test/java/opennlp/uima/AbstractIT.java
+++ b/opennlp-uima/src/test/java/opennlp/uima/AbstractIT.java
@@ -41,6 +41,7 @@ import org.junit.jupiter.api.BeforeAll;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import opennlp.tools.models.ModelType;
 import opennlp.tools.postag.POSModel;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.tokenize.TokenizerModel;
@@ -57,9 +58,9 @@ abstract class AbstractIT extends AbstractUimaTest {
   @BeforeAll
   public static void initEnv() throws IOException {
     // ensure referenced UD models are present in download home
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.TOKENIZER, 
TokenizerModel.class);
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.POS, 
POSModel.class);
+    DownloadUtil.downloadModel("en", ModelType.TOKENIZER, 
TokenizerModel.class);
+    DownloadUtil.downloadModel("en", ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+    DownloadUtil.downloadModel("en", ModelType.POS, POSModel.class);
 
     // ensure referenced classic model files are present in download home
     for (String modelName: List.of("en-ner-organization", "en-ner-location", 
"en-ner-person",
diff --git 
a/opennlp-uima/src/test/java/opennlp/uima/util/AnnotationComparatorTest.java 
b/opennlp-uima/src/test/java/opennlp/uima/util/AnnotationComparatorTest.java
index bcab5d01..2366355a 100644
--- a/opennlp-uima/src/test/java/opennlp/uima/util/AnnotationComparatorTest.java
+++ b/opennlp-uima/src/test/java/opennlp/uima/util/AnnotationComparatorTest.java
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.uima.AbstractUimaTest;
@@ -56,7 +57,7 @@ class AnnotationComparatorTest extends AbstractUimaTest {
   @BeforeAll
   public static void initEnv() throws IOException {
     // ensure referenced UD models are present in download home
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+    DownloadUtil.downloadModel("en", ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
   }
 
   @BeforeEach
diff --git 
a/opennlp-uima/src/test/java/opennlp/uima/util/AnnotatorUtilTest.java 
b/opennlp-uima/src/test/java/opennlp/uima/util/AnnotatorUtilTest.java
index 0aeba0b6..66a0b48f 100644
--- a/opennlp-uima/src/test/java/opennlp/uima/util/AnnotatorUtilTest.java
+++ b/opennlp-uima/src/test/java/opennlp/uima/util/AnnotatorUtilTest.java
@@ -38,6 +38,7 @@ import org.junit.jupiter.params.provider.NullAndEmptySource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.uima.AbstractUimaTest;
@@ -62,7 +63,7 @@ class AnnotatorUtilTest extends AbstractUimaTest {
   @BeforeAll
   public static void initEnv() throws IOException {
     // ensure referenced UD models are present in download home
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+    DownloadUtil.downloadModel("en", ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
   }
 
   @BeforeEach
diff --git a/opennlp-uima/src/test/java/opennlp/uima/util/OpennlpUtilTest.java 
b/opennlp-uima/src/test/java/opennlp/uima/util/OpennlpUtilTest.java
index 332784a1..b5a93c05 100644
--- a/opennlp-uima/src/test/java/opennlp/uima/util/OpennlpUtilTest.java
+++ b/opennlp-uima/src/test/java/opennlp/uima/util/OpennlpUtilTest.java
@@ -30,6 +30,7 @@ import org.junit.jupiter.params.provider.EmptySource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.tools.util.TrainingParameters;
@@ -53,7 +54,7 @@ public class OpennlpUtilTest extends AbstractTest {
   @BeforeAll
   public static void initEnv() throws IOException {
     sentModel = DownloadUtil.downloadModel(
-            "en", DownloadUtil.ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+            "en", ModelType.SENTENCE_DETECTOR, SentenceModel.class);
   }
 
   @Test
diff --git a/opennlp-uima/src/test/java/opennlp/uima/util/UimaUtilTest.java 
b/opennlp-uima/src/test/java/opennlp/uima/util/UimaUtilTest.java
index d101a76b..084083f8 100644
--- a/opennlp-uima/src/test/java/opennlp/uima/util/UimaUtilTest.java
+++ b/opennlp-uima/src/test/java/opennlp/uima/util/UimaUtilTest.java
@@ -33,6 +33,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import opennlp.tools.EnabledWhenCDNAvailable;
+import opennlp.tools.models.ModelType;
 import opennlp.tools.sentdetect.SentenceModel;
 import opennlp.tools.util.DownloadUtil;
 import opennlp.uima.AbstractUimaTest;
@@ -59,7 +60,7 @@ class UimaUtilTest extends AbstractUimaTest {
   @BeforeAll
   public static void initEnv() throws IOException {
     // ensure referenced UD models are present in download home
-    DownloadUtil.downloadModel("en", DownloadUtil.ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
+    DownloadUtil.downloadModel("en", ModelType.SENTENCE_DETECTOR, 
SentenceModel.class);
   }
 
   @BeforeEach

Reply via email to