gnodet commented on code in PR #1378:
URL: https://github.com/apache/maven/pull/1378#discussion_r1453039589


##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();

Review Comment:
   Can we use a `ConcurrentHashMap` rather than a `HashMap` and synchronizing 
access to it ?



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {
+            this.name = Objects.requireNonNull(name);
+            this.valueType = Objects.requireNonNull(valueType);
+        }
+
+        /**
+         * If a key exists in the {@linkplain #intern() intern pool} for the 
given name, returns that key.
+         * Otherwise, if the {@code defaultType} is non-null, creates a key 
for values of the specified type.
+         * Otherwise, returns {@code null}.
+         *
+         * @param name name of the key to search or create
+         * @param defaultType value type of the key to create if none exist 
for the given name, or {@code null}
+         * @return key found or created, or {@code null} if no key was found 
and {@code defaultType} is null
+         *
+         * @see #intern()
+         */
+        public static Key<?> forName(String name, Class<?> defaultType) {
+            Key<?> key;
+            synchronized (INTERNS) {
+                key = INTERNS.get(name);
+            }
+            if (key == null && defaultType != null) {
+                key = new Key<>(name, defaultType);
+            }
+            return key;
+        }
+
+        /**
+         * {@return the name of the key}.
+         */
+        @Nonnull
+        public String name() {
+            return name;
+        }
+
+        /**
+         * {@return the type of value associated to the key}.
+         */
+        @Nonnull
+        public Class<V> valueType() {
+            return valueType;
+        }
+
+        /**
+         * {@return a canonical representation of this key}. A pool of keys, 
initially empty, is maintained privately.
+         * When the {@code intern()} method is invoked, if the pool already 
contains a key equal to this {@code Key}
+         * as determined by the {@link #equals(Object)} method, then the key 
from the pool is returned. Otherwise,
+         * if no key exist in the pool for this key {@linkplain #name() name}, 
then this {@code Key} object is added
+         * to the pool and {@code this} is returned. Otherwise an {@link 
IllegalStateException} is thrown.
+         *
+         * @throws IllegalStateException if a key exists in the pool for the 
same name but a different class of values.
+         *
+         * @see String#intern()
+         */
+        @SuppressWarnings("unchecked")
+        public Key<V> intern() {
+            Key<?> previous;
+            synchronized (INTERNS) {
+                previous = INTERNS.putIfAbsent(name, this);
+            }
+            if (previous == null) {
+                return this;
+            }
+            if (equals(previous)) {
+                return (Key<V>) previous;
+            }
+            throw new IllegalStateException("Key " + name + " already exists 
for a different class of values.");
+        }
+
+        /**
+         * {@return a string representation of this key}.
+         * By default, this is the name of this key.
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * {@return an hash code value for this key}.
+         */
+        @Override
+        public int hashCode() {
+            return 7 + name.hashCode() + 31 * valueType.hashCode();

Review Comment:
   `Objects.hash(name, valueType)`



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,
+ * the paths specified in a {@code --patch-module} Java option is effective 
only for a specified module.
+ * This type is created by calls to {@link #patchModule(String)} and a new 
instance must be created for
+ * every module to patch.</p>
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both on the Java class-path
+ * and on the Java module-path.</p>
+ *
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public final class JavaPathType extends PathType {
+    /**
+     * The path identified by the Java {@code --class-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this path type will not necessarily be placed on the 
class-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #MODULES} path type is also set, then the dependency 
can be placed either on the
+     *       class-path or on the module-path, but only one of those. The 
choice is up to the plugin,
+     *       possibly using heuristic rules (Maven 3 behavior).</li>
+     *   <li>If a {@link #patchModule(String)} is also set and the main JAR 
file was placed on the module-path,
+     *       then the test dependency will be placed on the Java {@code 
--patch-module} option instead of the
+     *       class-path.</li>
+     * </ul>
+     */
+    public static final JavaPathType CLASSES = new JavaPathType("CLASSES", 
"--class-path", null);
+
+    /**
+     * The path identified by the Java {@code --module-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this flag will not necessarily be placed on the 
module-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #CLASSES} path type is also set, then the dependency 
<em>should</em> be placed on the
+     *       module-path, but is nevertheless compatible with placement on the 
class-path. Compatibility can

Review Comment:
   `nevertheless` -> `also`



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {
+            this.name = Objects.requireNonNull(name);
+            this.valueType = Objects.requireNonNull(valueType);
+        }
+
+        /**
+         * If a key exists in the {@linkplain #intern() intern pool} for the 
given name, returns that key.
+         * Otherwise, if the {@code defaultType} is non-null, creates a key 
for values of the specified type.
+         * Otherwise, returns {@code null}.
+         *
+         * @param name name of the key to search or create
+         * @param defaultType value type of the key to create if none exist 
for the given name, or {@code null}
+         * @return key found or created, or {@code null} if no key was found 
and {@code defaultType} is null
+         *
+         * @see #intern()
+         */
+        public static Key<?> forName(String name, Class<?> defaultType) {
+            Key<?> key;
+            synchronized (INTERNS) {
+                key = INTERNS.get(name);
+            }
+            if (key == null && defaultType != null) {
+                key = new Key<>(name, defaultType);
+            }
+            return key;
+        }
+
+        /**
+         * {@return the name of the key}.
+         */
+        @Nonnull
+        public String name() {
+            return name;
+        }
+
+        /**
+         * {@return the type of value associated to the key}.
+         */
+        @Nonnull
+        public Class<V> valueType() {
+            return valueType;
+        }
+
+        /**
+         * {@return a canonical representation of this key}. A pool of keys, 
initially empty, is maintained privately.
+         * When the {@code intern()} method is invoked, if the pool already 
contains a key equal to this {@code Key}
+         * as determined by the {@link #equals(Object)} method, then the key 
from the pool is returned. Otherwise,
+         * if no key exist in the pool for this key {@linkplain #name() name}, 
then this {@code Key} object is added
+         * to the pool and {@code this} is returned. Otherwise an {@link 
IllegalStateException} is thrown.
+         *
+         * @throws IllegalStateException if a key exists in the pool for the 
same name but a different class of values.
+         *
+         * @see String#intern()
+         */
+        @SuppressWarnings("unchecked")
+        public Key<V> intern() {
+            Key<?> previous;
+            synchronized (INTERNS) {
+                previous = INTERNS.putIfAbsent(name, this);
+            }
+            if (previous == null) {
+                return this;
+            }
+            if (equals(previous)) {
+                return (Key<V>) previous;
+            }
+            throw new IllegalStateException("Key " + name + " already exists 
for a different class of values.");
+        }
+
+        /**
+         * {@return a string representation of this key}.
+         * By default, this is the name of this key.
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * {@return an hash code value for this key}.
+         */
+        @Override
+        public int hashCode() {
+            return 7 + name.hashCode() + 31 * valueType.hashCode();
+        }
+
+        /**
+         * Compares this key with the given object for equality.
+         * Two keys are considered equal if they have the same name
+         * and are associated to values of the same class.
+         *
+         * @param obj the object to compare with this key
+         * @return whether the given object is equal to this key
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj != null && getClass() == obj.getClass()) {
+                final Key<?> other = (Key<?>) obj;
+                return name.equals(other.name) && 
valueType.equals(other.valueType);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * The dependency type. The {@linkplain Key#name() name} of this property
+     * is equal to the {@code ArtifactProperties.TYPE} value.
+     */
+    Key<String> TYPE = new Key<>("type", String.class).intern();
+
+    /**
+     * The dependency language. The {@linkplain Key#name() name} of this 
property
+     * is equal to the {@code ArtifactProperties.LANGUAGE} value.
+     */
+    Key<String> LANGUAGE = new Key<>("language", String.class).intern();
+
+    /**
+     * Types of path (class-path, module-path, …) where the dependency can be 
placed.
+     * For most deterministic builds, the array length should be 1. In such 
case,
+     * the dependency will be unconditionally placed on the specified type of 
path
+     * and no heuristic rule will be involved.
+     *
+     * <p>It is nevertheless common to specify two or more types of path. For 
example,
+     * a Java library may be compatible with either the class-path or the 
module-path,
+     * and the user may have provided no instruction about which type to use. 
In such
+     * case, the plugin may apply rules for choosing a path. See for example
+     * {@link JavaPathType#CLASSES} and {@link JavaPathType#MODULES}.</p>
+     */
+    Key<PathType[]> PATH_TYPES = new Key<>("pathTypes", 
PathType[].class).intern();
+
+    /**
+     * Boolean flag telling that dependency contains all of its dependencies.
      * <p>
      * <em>Important: this flag must be kept in sync with resolver! (as is 
used during collection)</em>
      */
-    String FLAG_INCLUDES_DEPENDENCIES = "includesDependencies";
+    Key<Boolean> FLAG_INCLUDES_DEPENDENCIES = new 
Key<>("includesDependencies", Boolean.class).intern();
 
     /**
-     * Boolean flag telling that dependency is meant to be placed on class 
path. Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Boolean flag telling that dependency is meant to be placed on class 
path.
+     *
+     * @deprecated Use {@link #PATH_TYPES} and {@link JavaPathType#CLASSES} 
instead.
      */
-    String FLAG_CLASS_PATH_CONSTITUENT = "classPathConstituent";
+    @Deprecated
+    Key<Boolean> FLAG_CLASS_PATH_CONSTITUENT = new 
Key<>("classPathConstituent", Boolean.class).intern();
 
     /**
-     * Returns immutable "map view" of all the properties.
+     * {@return the keys of all properties in this map}.
      */
-    @Nonnull
-    Map<String, String> asMap();
+    Set<Key<?>> keys();
+
+    /**
+     * Returns the value associated to the given key.
+     *
+     * @param <V> type of value to get
+     * @param key key of the value to get
+     * @return value associated to the given key, or {@code null} if none
+     */
+    <V> V get(@Nonnull Key<V> key);
+
+    /**
+     * Returns the value associated to the given key, or the given default 
value if none.
+     *
+     * @param <V> type of value to get
+     * @param key key of the value to get
+     * @param defaultValue the value to return is none is associated to the 
given key, or {@code null}
+     * @return value associated to the given key, or {@code null} if none and 
the default is null
+     */
+    <V> V getOrDefault(@Nonnull Key<V> key, V defaultValue);

Review Comment:
   Missing `@Nullable` on the return value and the `V` parameter to be explicit 
.



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {

Review Comment:
   `final` in parameters is useless, please remove



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {
+            this.name = Objects.requireNonNull(name);
+            this.valueType = Objects.requireNonNull(valueType);
+        }
+
+        /**
+         * If a key exists in the {@linkplain #intern() intern pool} for the 
given name, returns that key.
+         * Otherwise, if the {@code defaultType} is non-null, creates a key 
for values of the specified type.
+         * Otherwise, returns {@code null}.
+         *
+         * @param name name of the key to search or create
+         * @param defaultType value type of the key to create if none exist 
for the given name, or {@code null}
+         * @return key found or created, or {@code null} if no key was found 
and {@code defaultType} is null
+         *
+         * @see #intern()
+         */
+        public static Key<?> forName(String name, Class<?> defaultType) {
+            Key<?> key;
+            synchronized (INTERNS) {
+                key = INTERNS.get(name);
+            }
+            if (key == null && defaultType != null) {
+                key = new Key<>(name, defaultType);
+            }
+            return key;
+        }
+
+        /**
+         * {@return the name of the key}.
+         */
+        @Nonnull
+        public String name() {
+            return name;
+        }
+
+        /**
+         * {@return the type of value associated to the key}.
+         */
+        @Nonnull
+        public Class<V> valueType() {
+            return valueType;
+        }
+
+        /**
+         * {@return a canonical representation of this key}. A pool of keys, 
initially empty, is maintained privately.
+         * When the {@code intern()} method is invoked, if the pool already 
contains a key equal to this {@code Key}
+         * as determined by the {@link #equals(Object)} method, then the key 
from the pool is returned. Otherwise,
+         * if no key exist in the pool for this key {@linkplain #name() name}, 
then this {@code Key} object is added
+         * to the pool and {@code this} is returned. Otherwise an {@link 
IllegalStateException} is thrown.
+         *
+         * @throws IllegalStateException if a key exists in the pool for the 
same name but a different class of values.
+         *
+         * @see String#intern()
+         */
+        @SuppressWarnings("unchecked")
+        public Key<V> intern() {

Review Comment:
   I don't think the whole `intern` thing is needed at all.
   I would suppose all references to `Key`s will be done using 
`DependencyProperties.XXX`, so I don't see a good use case for users to create 
duplicate instances.



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,
+ * the paths specified in a {@code --patch-module} Java option is effective 
only for a specified module.
+ * This type is created by calls to {@link #patchModule(String)} and a new 
instance must be created for
+ * every module to patch.</p>
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both on the Java class-path
+ * and on the Java module-path.</p>
+ *
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public final class JavaPathType extends PathType {
+    /**
+     * The path identified by the Java {@code --class-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this path type will not necessarily be placed on the 
class-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:

Review Comment:
   `There is` -> `There are`
   `be nevertheless` -> `nevertheless be`



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,
+ * the paths specified in a {@code --patch-module} Java option is effective 
only for a specified module.
+ * This type is created by calls to {@link #patchModule(String)} and a new 
instance must be created for
+ * every module to patch.</p>
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both on the Java class-path
+ * and on the Java module-path.</p>
+ *
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public final class JavaPathType extends PathType {
+    /**
+     * The path identified by the Java {@code --class-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this path type will not necessarily be placed on the 
class-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #MODULES} path type is also set, then the dependency 
can be placed either on the
+     *       class-path or on the module-path, but only one of those. The 
choice is up to the plugin,
+     *       possibly using heuristic rules (Maven 3 behavior).</li>
+     *   <li>If a {@link #patchModule(String)} is also set and the main JAR 
file was placed on the module-path,

Review Comment:
   `was placed` -> `is placed`



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,

Review Comment:
   `contrarily to` -> `unlike`



##########
api/maven-api-core/src/main/java/org/apache/maven/api/Type.java:
##########
@@ -80,11 +129,16 @@ public interface Type {
     String getClassifier();
 
     /**
-     * Specifies if the artifact contains java classes and should be
-     * added to the classpath.
+     * Specifies if the artifact contains java classes and can be added to the 
classpath.
+     * Whether the artifact <em>should</em> be added to the classpath depends 
on other
+     * {@linkplain #getDependencyProperties() dependency properties}.
+     *
+     * @return if the artifact <em>can</em> be added to the class path
      *
-     * @return if the artifact should be added to the class path
+     * @deprecated A value of {@code true} does not mean that the dependency 
<em>should</em>
+     * be placed on the classpath. See {@link JavaPathType} instead for better 
analysis.
      */
+    @Deprecated

Review Comment:
   If deprecation is necessary, it should be noted that it will be removed 
before 4.0.0 GA. 



##########
api/maven-api-core/src/main/java/org/apache/maven/api/PathType.java:
##########
@@ -0,0 +1,143 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the Java class-path, the Java module-path,
+ * or another kind of path for another programming language for example.
+ * This class is like an enumeration, except that it is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both
+ * on the Java class-path and on the Java module-path.</p>
+ *
+ * @see DependencyProperties#PATH_TYPES
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public abstract class PathType {

Review Comment:
   I'm not convinced we will ever have an implementation other than 
`JavaPathType`, in which case, both interfaces could be merged.  I'd also 
prefer an interface rather than an abstract class if that's possible.



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {
+            this.name = Objects.requireNonNull(name);
+            this.valueType = Objects.requireNonNull(valueType);
+        }
+
+        /**
+         * If a key exists in the {@linkplain #intern() intern pool} for the 
given name, returns that key.
+         * Otherwise, if the {@code defaultType} is non-null, creates a key 
for values of the specified type.
+         * Otherwise, returns {@code null}.
+         *
+         * @param name name of the key to search or create
+         * @param defaultType value type of the key to create if none exist 
for the given name, or {@code null}
+         * @return key found or created, or {@code null} if no key was found 
and {@code defaultType} is null
+         *
+         * @see #intern()
+         */
+        public static Key<?> forName(String name, Class<?> defaultType) {
+            Key<?> key;
+            synchronized (INTERNS) {
+                key = INTERNS.get(name);
+            }
+            if (key == null && defaultType != null) {
+                key = new Key<>(name, defaultType);
+            }
+            return key;
+        }
+
+        /**
+         * {@return the name of the key}.
+         */
+        @Nonnull
+        public String name() {
+            return name;
+        }
+
+        /**
+         * {@return the type of value associated to the key}.
+         */
+        @Nonnull
+        public Class<V> valueType() {
+            return valueType;
+        }
+
+        /**
+         * {@return a canonical representation of this key}. A pool of keys, 
initially empty, is maintained privately.
+         * When the {@code intern()} method is invoked, if the pool already 
contains a key equal to this {@code Key}
+         * as determined by the {@link #equals(Object)} method, then the key 
from the pool is returned. Otherwise,
+         * if no key exist in the pool for this key {@linkplain #name() name}, 
then this {@code Key} object is added
+         * to the pool and {@code this} is returned. Otherwise an {@link 
IllegalStateException} is thrown.
+         *
+         * @throws IllegalStateException if a key exists in the pool for the 
same name but a different class of values.
+         *
+         * @see String#intern()
+         */
+        @SuppressWarnings("unchecked")
+        public Key<V> intern() {
+            Key<?> previous;
+            synchronized (INTERNS) {
+                previous = INTERNS.putIfAbsent(name, this);
+            }
+            if (previous == null) {
+                return this;
+            }
+            if (equals(previous)) {
+                return (Key<V>) previous;
+            }
+            throw new IllegalStateException("Key " + name + " already exists 
for a different class of values.");
+        }
+
+        /**
+         * {@return a string representation of this key}.
+         * By default, this is the name of this key.
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * {@return an hash code value for this key}.
+         */
+        @Override
+        public int hashCode() {
+            return 7 + name.hashCode() + 31 * valueType.hashCode();
+        }
+
+        /**
+         * Compares this key with the given object for equality.
+         * Two keys are considered equal if they have the same name
+         * and are associated to values of the same class.
+         *
+         * @param obj the object to compare with this key
+         * @return whether the given object is equal to this key
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj != null && getClass() == obj.getClass()) {
+                final Key<?> other = (Key<?>) obj;
+                return name.equals(other.name) && 
valueType.equals(other.valueType);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * The dependency type. The {@linkplain Key#name() name} of this property
+     * is equal to the {@code ArtifactProperties.TYPE} value.
+     */
+    Key<String> TYPE = new Key<>("type", String.class).intern();
+
+    /**
+     * The dependency language. The {@linkplain Key#name() name} of this 
property
+     * is equal to the {@code ArtifactProperties.LANGUAGE} value.
+     */
+    Key<String> LANGUAGE = new Key<>("language", String.class).intern();
+
+    /**
+     * Types of path (class-path, module-path, …) where the dependency can be 
placed.
+     * For most deterministic builds, the array length should be 1. In such 
case,
+     * the dependency will be unconditionally placed on the specified type of 
path
+     * and no heuristic rule will be involved.
+     *
+     * <p>It is nevertheless common to specify two or more types of path. For 
example,
+     * a Java library may be compatible with either the class-path or the 
module-path,
+     * and the user may have provided no instruction about which type to use. 
In such
+     * case, the plugin may apply rules for choosing a path. See for example
+     * {@link JavaPathType#CLASSES} and {@link JavaPathType#MODULES}.</p>
+     */
+    Key<PathType[]> PATH_TYPES = new Key<>("pathTypes", 
PathType[].class).intern();

Review Comment:
   `Collection<PathType>` so that we can ensure immutability ?



##########
api/maven-api-core/src/main/java/org/apache/maven/api/DependencyProperties.java:
##########
@@ -33,27 +36,226 @@
 @Immutable
 public interface DependencyProperties {
     /**
-     * Boolean flag telling that dependency contains all of its dependencies. 
Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Keys in the dependency properties map.
+     * Each key can be associated to values of a specific class.
+     *
+     * @param  <V>  type of value associated to the key
+     */
+    class Key<V> {
+        /**
+         * The keys that are defined in this {@code DependencyProperties} map.
+         * Accesses to this map shall be synchronized on the map.
+         *
+         * @see #intern()
+         */
+        private static final Map<String, Key<?>> INTERNS = new HashMap<>();
+
+        /**
+         * Value returned by {@link #name()}.
+         */
+        @Nonnull
+        private final String name;
+
+        /**
+         * Value returned by {@link #valueType()}.
+         */
+        @Nonnull
+        private final Class<V> valueType;
+
+        /**
+         * Creates a new key.
+         *
+         * @param name name of the key
+         * @param valueType type of value associated to the key
+         */
+        public Key(@Nonnull final String name, @Nonnull final Class<V> 
valueType) {
+            this.name = Objects.requireNonNull(name);
+            this.valueType = Objects.requireNonNull(valueType);
+        }
+
+        /**
+         * If a key exists in the {@linkplain #intern() intern pool} for the 
given name, returns that key.
+         * Otherwise, if the {@code defaultType} is non-null, creates a key 
for values of the specified type.
+         * Otherwise, returns {@code null}.
+         *
+         * @param name name of the key to search or create
+         * @param defaultType value type of the key to create if none exist 
for the given name, or {@code null}
+         * @return key found or created, or {@code null} if no key was found 
and {@code defaultType} is null
+         *
+         * @see #intern()
+         */
+        public static Key<?> forName(String name, Class<?> defaultType) {
+            Key<?> key;
+            synchronized (INTERNS) {
+                key = INTERNS.get(name);
+            }
+            if (key == null && defaultType != null) {
+                key = new Key<>(name, defaultType);
+            }
+            return key;
+        }
+
+        /**
+         * {@return the name of the key}.
+         */
+        @Nonnull
+        public String name() {
+            return name;
+        }
+
+        /**
+         * {@return the type of value associated to the key}.
+         */
+        @Nonnull
+        public Class<V> valueType() {
+            return valueType;
+        }
+
+        /**
+         * {@return a canonical representation of this key}. A pool of keys, 
initially empty, is maintained privately.
+         * When the {@code intern()} method is invoked, if the pool already 
contains a key equal to this {@code Key}
+         * as determined by the {@link #equals(Object)} method, then the key 
from the pool is returned. Otherwise,
+         * if no key exist in the pool for this key {@linkplain #name() name}, 
then this {@code Key} object is added
+         * to the pool and {@code this} is returned. Otherwise an {@link 
IllegalStateException} is thrown.
+         *
+         * @throws IllegalStateException if a key exists in the pool for the 
same name but a different class of values.
+         *
+         * @see String#intern()
+         */
+        @SuppressWarnings("unchecked")
+        public Key<V> intern() {
+            Key<?> previous;
+            synchronized (INTERNS) {
+                previous = INTERNS.putIfAbsent(name, this);
+            }
+            if (previous == null) {
+                return this;
+            }
+            if (equals(previous)) {
+                return (Key<V>) previous;
+            }
+            throw new IllegalStateException("Key " + name + " already exists 
for a different class of values.");
+        }
+
+        /**
+         * {@return a string representation of this key}.
+         * By default, this is the name of this key.
+         */
+        @Override
+        public String toString() {
+            return name;
+        }
+
+        /**
+         * {@return an hash code value for this key}.
+         */
+        @Override
+        public int hashCode() {
+            return 7 + name.hashCode() + 31 * valueType.hashCode();
+        }
+
+        /**
+         * Compares this key with the given object for equality.
+         * Two keys are considered equal if they have the same name
+         * and are associated to values of the same class.
+         *
+         * @param obj the object to compare with this key
+         * @return whether the given object is equal to this key
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj != null && getClass() == obj.getClass()) {
+                final Key<?> other = (Key<?>) obj;
+                return name.equals(other.name) && 
valueType.equals(other.valueType);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * The dependency type. The {@linkplain Key#name() name} of this property
+     * is equal to the {@code ArtifactProperties.TYPE} value.
+     */
+    Key<String> TYPE = new Key<>("type", String.class).intern();
+
+    /**
+     * The dependency language. The {@linkplain Key#name() name} of this 
property
+     * is equal to the {@code ArtifactProperties.LANGUAGE} value.
+     */
+    Key<String> LANGUAGE = new Key<>("language", String.class).intern();
+
+    /**
+     * Types of path (class-path, module-path, …) where the dependency can be 
placed.
+     * For most deterministic builds, the array length should be 1. In such 
case,
+     * the dependency will be unconditionally placed on the specified type of 
path
+     * and no heuristic rule will be involved.
+     *
+     * <p>It is nevertheless common to specify two or more types of path. For 
example,
+     * a Java library may be compatible with either the class-path or the 
module-path,
+     * and the user may have provided no instruction about which type to use. 
In such
+     * case, the plugin may apply rules for choosing a path. See for example
+     * {@link JavaPathType#CLASSES} and {@link JavaPathType#MODULES}.</p>
+     */
+    Key<PathType[]> PATH_TYPES = new Key<>("pathTypes", 
PathType[].class).intern();
+
+    /**
+     * Boolean flag telling that dependency contains all of its dependencies.
      * <p>
      * <em>Important: this flag must be kept in sync with resolver! (as is 
used during collection)</em>
      */
-    String FLAG_INCLUDES_DEPENDENCIES = "includesDependencies";
+    Key<Boolean> FLAG_INCLUDES_DEPENDENCIES = new 
Key<>("includesDependencies", Boolean.class).intern();
 
     /**
-     * Boolean flag telling that dependency is meant to be placed on class 
path. Value of this key should be parsed with
-     * {@link Boolean#parseBoolean(String)} to obtain value.
+     * Boolean flag telling that dependency is meant to be placed on class 
path.
+     *
+     * @deprecated Use {@link #PATH_TYPES} and {@link JavaPathType#CLASSES} 
instead.
      */
-    String FLAG_CLASS_PATH_CONSTITUENT = "classPathConstituent";
+    @Deprecated
+    Key<Boolean> FLAG_CLASS_PATH_CONSTITUENT = new 
Key<>("classPathConstituent", Boolean.class).intern();
 
     /**
-     * Returns immutable "map view" of all the properties.
+     * {@return the keys of all properties in this map}.
      */
-    @Nonnull
-    Map<String, String> asMap();
+    Set<Key<?>> keys();
+
+    /**
+     * Returns the value associated to the given key.
+     *
+     * @param <V> type of value to get
+     * @param key key of the value to get
+     * @return value associated to the given key, or {@code null} if none
+     */
+    <V> V get(@Nonnull Key<V> key);

Review Comment:
   `Optional<V>` as a return value ?



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,
+ * the paths specified in a {@code --patch-module} Java option is effective 
only for a specified module.
+ * This type is created by calls to {@link #patchModule(String)} and a new 
instance must be created for
+ * every module to patch.</p>
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both on the Java class-path
+ * and on the Java module-path.</p>
+ *
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public final class JavaPathType extends PathType {
+    /**
+     * The path identified by the Java {@code --class-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this path type will not necessarily be placed on the 
class-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #MODULES} path type is also set, then the dependency 
can be placed either on the
+     *       class-path or on the module-path, but only one of those. The 
choice is up to the plugin,
+     *       possibly using heuristic rules (Maven 3 behavior).</li>
+     *   <li>If a {@link #patchModule(String)} is also set and the main JAR 
file was placed on the module-path,
+     *       then the test dependency will be placed on the Java {@code 
--patch-module} option instead of the
+     *       class-path.</li>
+     * </ul>
+     */
+    public static final JavaPathType CLASSES = new JavaPathType("CLASSES", 
"--class-path", null);
+
+    /**
+     * The path identified by the Java {@code --module-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this flag will not necessarily be placed on the 
module-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #CLASSES} path type is also set, then the dependency 
<em>should</em> be placed on the
+     *       module-path, but is nevertheless compatible with placement on the 
class-path. Compatibility can
+     *       be achieved, for example, by repeating in the {@code 
META-INF/services/} directory the services
+     *       that are declared in the {@code module-info.class} file. In that 
case, the path type can be chosen
+     *       by the plugin.</li>
+     *   <li>If a {@link #patchModule(String)} is also set and the main JAR 
file was placed on the module-path,
+     *       then the test dependency will be placed on the Java {@code 
--patch-module} option instead of the
+     *       module-path.</li>

Review Comment:
   `module-path` -> `{@code --module-path}` for consistency



##########
api/maven-api-core/src/main/java/org/apache/maven/api/JavaPathType.java:
##########
@@ -0,0 +1,282 @@
+/*
+ * 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 org.apache.maven.api;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Nonnull;
+
+/**
+ * The option of a Java command-line tool where to place the paths to some 
dependencies.
+ * A {@code PathType} can identify the class-path, the module-path, the 
patches for a specific module,
+ * or another kind of path. This class is like an enumeration, except that it 
is extensible:
+ * plugins can define their own kinds of path.
+ *
+ * <p>One path type is handled in a special way: contrarily to other options,
+ * the paths specified in a {@code --patch-module} Java option is effective 
only for a specified module.
+ * This type is created by calls to {@link #patchModule(String)} and a new 
instance must be created for
+ * every module to patch.</p>
+ *
+ * <p>Path types are often exclusive. For example, a dependency should not be 
both on the Java class-path
+ * and on the Java module-path.</p>
+ *
+ * @see 
org.apache.maven.api.services.DependencyResolverResult#getDispatchedPaths()
+ *
+ * @since 4.0.0
+ */
+@Experimental
+public final class JavaPathType extends PathType {
+    /**
+     * The path identified by the Java {@code --class-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this path type will not necessarily be placed on the 
class-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:
+     *
+     * <ul>
+     *   <li>If {@link #MODULES} path type is also set, then the dependency 
can be placed either on the
+     *       class-path or on the module-path, but only one of those. The 
choice is up to the plugin,
+     *       possibly using heuristic rules (Maven 3 behavior).</li>
+     *   <li>If a {@link #patchModule(String)} is also set and the main JAR 
file was placed on the module-path,
+     *       then the test dependency will be placed on the Java {@code 
--patch-module} option instead of the
+     *       class-path.</li>
+     * </ul>
+     */
+    public static final JavaPathType CLASSES = new JavaPathType("CLASSES", 
"--class-path", null);
+
+    /**
+     * The path identified by the Java {@code --module-path} option.
+     * Used for compilation, execution and Javadoc among others.
+     *
+     * <h4>Context-sensitive interpretation</h4>
+     * A dependency with this flag will not necessarily be placed on the 
module-path.
+     * There is two circumstances where the dependency may be nevertheless 
placed somewhere else:

Review Comment:
   `There is` -> `There are`
   `be nevertheless` -> `nevertheless be`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscr...@maven.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to