View Javadoc
1   package org.codehaus.plexus.languages.java.jpms;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Collections;
23  import java.util.LinkedHashSet;
24  import java.util.List;
25  import java.util.Objects;
26  import java.util.Set;
27  
28  /**
29   * Simple representation of a ModuleDescriptor containing info required by this plugin.
30   * It will provide only methods matching Java 9 ModuleDescriptor, so once Java 9  is required, we can easily switch
31   *
32   * @author Robert Scholte
33   * @since 1.0.0
34   *
35   */
36  public class JavaModuleDescriptor {
37      private String name;
38  
39      private boolean automatic;
40  
41      private Set<JavaRequires> requires = new LinkedHashSet<>();
42  
43      private Set<JavaExports> exports = new LinkedHashSet<>();
44  
45      private Set<String> uses = new LinkedHashSet<>();
46  
47      private Set<JavaProvides> provides = new LinkedHashSet<>();
48  
49      public String name() {
50          return name;
51      }
52  
53      public boolean isAutomatic() {
54          return automatic;
55      }
56  
57      public Set<JavaRequires> requires() {
58          return Collections.unmodifiableSet(requires);
59      }
60  
61      public Set<JavaExports> exports() {
62          return Collections.unmodifiableSet(exports);
63      }
64  
65      public Set<JavaProvides> provides() {
66          return Collections.unmodifiableSet(provides);
67      }
68  
69      public Set<String> uses() {
70          return Collections.unmodifiableSet(uses);
71      }
72  
73      public static JavaModuleDescriptor.Builder newModule(String name) {
74          return new Builder(name).setAutomatic(false);
75      }
76  
77      public static Builder newAutomaticModule(String name) {
78          return new Builder(name).setAutomatic(true);
79      }
80  
81      @Override
82      public int hashCode() {
83          return Objects.hash(name, automatic, requires, exports);
84      }
85  
86      @Override
87      public boolean equals(Object obj) {
88          if (this == obj) {
89              return true;
90          }
91          if (obj == null) {
92              return false;
93          }
94          if (getClass() != obj.getClass()) {
95              return false;
96          }
97  
98          JavaModuleDescriptor other = (JavaModuleDescriptor) obj;
99          if (automatic != other.automatic) {
100             return false;
101         }
102         if (!Objects.equals(name, other.name)) {
103             return false;
104         }
105         if (!Objects.equals(requires, other.requires)) {
106             return false;
107         }
108         if (!Objects.equals(exports, other.exports)) {
109             return false;
110         }
111         return true;
112     }
113 
114     @Override
115     public String toString() {
116         return "JavaModuleDescriptor{" + "name='"
117                 + name + '\'' + ", automatic="
118                 + automatic + ", requires="
119                 + requires + ", exports="
120                 + exports + ", uses="
121                 + uses + ", provides="
122                 + provides + '}';
123     }
124 
125     /**
126      * A JavaModuleDescriptor Builder
127      *
128      * @author Robert Scholte
129      * @since 1.0.0
130      */
131     public static final class Builder {
132         private JavaModuleDescriptor jModule;
133 
134         private Builder(String name) {
135             jModule = new JavaModuleDescriptor();
136             jModule.name = name;
137         }
138 
139         private Builder setAutomatic(boolean isAutomatic) {
140             jModule.automatic = isAutomatic;
141             return this;
142         }
143 
144         /**
145          * Adds a dependence on a module with the given (and possibly empty) set of modifiers.
146          *
147          * @param modifiers The set of modifiers
148          * @param name The module name
149          * @return This builder
150          */
151         public Builder requires(Set<JavaModuleDescriptor.JavaRequires.JavaModifier> modifiers, String name) {
152             jModule.requires.add(new JavaRequires(modifiers, name));
153             return this;
154         }
155 
156         /**
157          * Adds a dependence on a module with an empty set of modifiers.
158          *
159          * @param name The module name
160          * @return This builder
161          */
162         public Builder requires(String name) {
163             jModule.requires.add(new JavaRequires(name));
164             return this;
165         }
166 
167         /**
168          * Adds an exported package. The package is exported to all modules.
169          *
170          * @param source The package name
171          * @return This builder
172          */
173         public Builder exports(String source) {
174             jModule.exports.add(new JavaExports(source));
175             return this;
176         }
177 
178         /**
179          * Adds an exported package. The package is exported to a set of target modules.
180          *
181          * @param source The package name
182          * @param targets  The set of target modules names
183          * @return This builder
184          */
185         public Builder exports(String source, Set<String> targets) {
186             jModule.exports.add(new JavaExports(source, targets));
187             return this;
188         }
189 
190         /**
191          * Adds a service dependence.
192          *
193          * @param service The service type
194          * @return This Builder
195          */
196         public Builder uses(String service) {
197             jModule.uses.add(service);
198             return this;
199         }
200 
201         public Builder provides(String service, List<String> providers) {
202             jModule.provides.add(new JavaProvides(service, providers));
203             return this;
204         }
205 
206         /**
207          * Builds and returns a ModuleDescriptor from its components.
208          *
209          * @return The module descriptor
210          */
211         public JavaModuleDescriptor build() {
212             return jModule;
213         }
214     }
215 
216     /**
217      * Represents ModuleDescriptor.Requires
218      *
219      * @author Robert Scholte
220      * @since 1.0.0
221      */
222     public static class JavaRequires {
223         private final Set<JavaModifier> modifiers;
224 
225         private final String name;
226 
227         private JavaRequires(Set<JavaModifier> modifiers, String name) {
228             this.modifiers = modifiers;
229             this.name = name;
230         }
231 
232         private JavaRequires(String name) {
233             this.modifiers = Collections.emptySet();
234             this.name = name;
235         }
236 
237         public Set<JavaModifier> modifiers() {
238             return modifiers;
239         }
240 
241         public String name() {
242             return name;
243         }
244 
245         /**
246          * Represents ModuleDescriptor.Requires.Modifier
247          *
248          * @author Robert Scholte
249          * @since 1.0.0
250          */
251         public enum JavaModifier {
252             STATIC,
253             TRANSITIVE
254         }
255 
256         @Override
257         public int hashCode() {
258             return Objects.hash(modifiers, name);
259         }
260 
261         @Override
262         public boolean equals(Object obj) {
263             if (this == obj) {
264                 return true;
265             }
266             if (obj == null) {
267                 return false;
268             }
269             if (getClass() != obj.getClass()) {
270                 return false;
271             }
272 
273             JavaRequires other = (JavaRequires) obj;
274             if (!Objects.equals(modifiers, other.modifiers)) {
275                 return false;
276             }
277             if (!Objects.equals(name, other.name)) {
278                 return false;
279             }
280             return true;
281         }
282 
283         @Override
284         public String toString() {
285             return "JavaRequires{" + "modifiers=" + modifiers + ", name='" + name + '\'' + '}';
286         }
287     }
288 
289     /**
290      * Represents ModuleDescriptor.Exports
291      *
292      * @author Robert Scholte
293      * @since 1.0.0
294      */
295     public static class JavaExports {
296         private final String source;
297 
298         private final Set<String> targets;
299 
300         private JavaExports(String source) {
301             this.source = source;
302             this.targets = null;
303         }
304 
305         public JavaExports(String source, Set<String> targets) {
306             this.source = source;
307             this.targets = targets;
308         }
309 
310         public String source() {
311             return source;
312         }
313 
314         public Set<String> targets() {
315             return targets;
316         }
317 
318         @Override
319         public int hashCode() {
320             return Objects.hash(source, targets);
321         }
322 
323         @Override
324         public boolean equals(Object obj) {
325             if (this == obj) {
326                 return true;
327             }
328             if (obj == null) {
329                 return false;
330             }
331             if (getClass() != obj.getClass()) {
332                 return false;
333             }
334 
335             JavaExports other = (JavaExports) obj;
336             if (!Objects.equals(source, other.source)) {
337                 return false;
338             }
339             if (!Objects.equals(targets, other.targets)) {
340                 return false;
341             }
342             return true;
343         }
344 
345         @Override
346         public String toString() {
347             return "JavaExports{" + "source='" + source + '\'' + ", targets=" + targets + '}';
348         }
349     }
350 
351     /**
352      * Represents ModuleDescriptor.Provides
353      *
354      * @author Robert Scholte
355      * @since 1.0.0
356      */
357     public static class JavaProvides {
358         private final String service;
359 
360         private final List<String> providers;
361 
362         private JavaProvides(String service, List<String> providers) {
363             this.service = service;
364             this.providers = providers;
365         }
366 
367         public String service() {
368             return service;
369         }
370 
371         public List<String> providers() {
372             return providers;
373         }
374 
375         @Override
376         public int hashCode() {
377             return Objects.hash(service, providers);
378         }
379 
380         @Override
381         public boolean equals(Object obj) {
382             if (this == obj) {
383                 return true;
384             }
385             if (obj == null) {
386                 return false;
387             }
388             if (getClass() != obj.getClass()) {
389                 return false;
390             }
391 
392             JavaProvides other = (JavaProvides) obj;
393             if (!Objects.equals(service, other.service)) {
394                 return false;
395             }
396             if (!Objects.equals(providers, other.providers)) {
397                 return false;
398             }
399             return true;
400         }
401 
402         @Override
403         public String toString() {
404             return "JavaProvides{" + "service='" + service + '\'' + ", providers=" + providers + '}';
405         }
406     }
407 }