1/*
2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.lang.model.element;
27
28import java.util.List;
29
30/**
31 * Represents a module program element.  Provides access to
32 * information about the module, its directives, and its members.
33 *
34 * @see javax.lang.model.util.Elements#getModuleOf
35 * @since 9
36 * @jls 7.7 Module Declarations
37 * @spec JPMS
38 */
39public interface ModuleElement extends Element, QualifiedNameable {
40
41    /**
42     * Returns the fully qualified name of this module.  For an
43     * {@linkplain #isUnnamed() unnamed module}, an empty name is returned.
44     *
45     * @apiNote If the module name consists of one identifier, then
46     * this method returns that identifier, which is deemed to be
47     * module's fully qualified name despite not being in qualified
48     * form.  If the module name consists of more than one identifier,
49     * then this method returns the entire name.
50     *
51     * @return the fully qualified name of this module, or an
52     * empty name if this is an unnamed module
53     *
54     * @jls 6.2 Names and Identifiers
55     */
56    @Override
57    Name getQualifiedName();
58
59    /**
60     * Returns the simple name of this module.  For an {@linkplain
61     * #isUnnamed() unnamed module}, an empty name is returned.
62     *
63     * @apiNote If the module name consists of one identifier, then
64     * this method returns that identifier.  If the module name
65     * consists of more than one identifier, then this method returns
66     * the rightmost such identifier, which is deemed to be the
67     * module's simple name.
68     *
69     * @return the simple name of this module or an empty name if
70     * this is an unnamed module
71     *
72     * @jls 6.2 Names and Identifiers
73     */
74    @Override
75    Name getSimpleName();
76
77    /**
78     * Returns the packages within this module.
79     * @return the packages within this module
80     */
81    @Override
82    List<? extends Element> getEnclosedElements();
83
84    /**
85     * Returns {@code true} if this is an open module and {@code
86     * false} otherwise.
87     *
88     * @return {@code true} if this is an open module and {@code
89     * false} otherwise
90     */ // TODO: add @jls to unnamed module section
91    boolean isOpen();
92
93    /**
94     * Returns {@code true} if this is an unnamed module and {@code
95     * false} otherwise.
96     *
97     * @return {@code true} if this is an unnamed module and {@code
98     * false} otherwise
99     */ // TODO: add @jls to unnamed module section
100    boolean isUnnamed();
101
102    /**
103     * Returns {@code null} since a module is not enclosed by another
104     * element.
105     *
106     * @return {@code null}
107     */
108    @Override
109    Element getEnclosingElement();
110
111    /**
112     * Returns the directives contained in the declaration of this module.
113     * @return  the directives in the declaration of this module
114     */
115    List<? extends Directive> getDirectives();
116
117    /**
118     * The {@code kind} of a directive.
119     *
120     * <p>Note that it is possible additional directive kinds will be added
121     * to accommodate new, currently unknown, language structures added to
122     * future versions of the Java&trade; programming language.
123     *
124     * @since 9
125     * @spec JPMS
126     */
127    enum DirectiveKind {
128        /** A "requires (static|transitive)* module-name" directive. */
129        REQUIRES,
130        /** An "exports package-name [to module-name-list]" directive. */
131        EXPORTS,
132        /** An "opens package-name [to module-name-list]" directive. */
133        OPENS,
134        /** A "uses service-name" directive. */
135        USES,
136        /** A "provides service-name with implementation-name" directive. */
137        PROVIDES
138    };
139
140    /**
141     * Represents a directive within the declaration of this
142     * module. The directives of a module declaration configure the
143     * module in the Java Platform Module System.
144     *
145     * @since 9
146     * @spec JPMS
147     */
148    interface Directive {
149        /**
150         * Returns the {@code kind} of this directive.
151         *
152         * @return the kind of this directive
153         */
154        DirectiveKind getKind();
155
156        /**
157         * Applies a visitor to this directive.
158         *
159         * @param <R> the return type of the visitor's methods
160         * @param <P> the type of the additional parameter to the visitor's methods
161         * @param v   the visitor operating on this directive
162         * @param p   additional parameter to the visitor
163         * @return a visitor-specified result
164         */
165        <R, P> R accept(DirectiveVisitor<R, P> v, P p);
166    }
167
168    /**
169     * A visitor of module directives, in the style of the visitor design
170     * pattern.  Classes implementing this interface are used to operate
171     * on a directive when the kind of directive is unknown at compile time.
172     * When a visitor is passed to a directive's {@link Directive#accept
173     * accept} method, the <code>visit<i>Xyz</i></code> method applicable
174     * to that directive is invoked.
175     *
176     * <p> Classes implementing this interface may or may not throw a
177     * {@code NullPointerException} if the additional parameter {@code p}
178     * is {@code null}; see documentation of the implementing class for
179     * details.
180     *
181     * <p> <b>WARNING:</b> It is possible that methods will be added to
182     * this interface to accommodate new, currently unknown, language
183     * structures added to future versions of the Java&trade; programming
184     * language. Methods to accommodate new language constructs will
185     * be added in a source <em>compatible</em> way using
186     * <em>default methods</em>.
187     *
188     * @param <R> the return type of this visitor's methods.  Use {@link
189     *            Void} for visitors that do not need to return results.
190     * @param <P> the type of the additional parameter to this visitor's
191     *            methods.  Use {@code Void} for visitors that do not need an
192     *            additional parameter.
193     *
194     * @since 9
195     * @spec JPMS
196     */
197    interface DirectiveVisitor<R, P> {
198        /**
199         * Visits any directive as if by passing itself to that
200         * directive's {@link Directive#accept accept} method and passing
201         * {@code null} for the additional parameter.
202         * The invocation {@code v.visit(d)} is equivalent to
203         * {@code d.accept(v, null)}.
204         * @param d  the directive to visit
205         * @return a visitor-specified result
206         * @implSpec This implementation is {@code visit(d, null)}
207         */
208        default R visit(Directive d) {
209            return d.accept(this, null);
210        }
211
212        /**
213         * Visits any directive as if by passing itself to that
214         * directive's {@link Directive#accept accept} method.
215         * The invocation {@code v.visit(d, p)} is equivalent to
216         * {@code d.accept(v, p)}.
217         * @param d  the directive to visit
218         * @param p  a visitor-specified parameter
219         * @return a visitor-specified result
220         */
221        default R visit(Directive d, P p) {
222            return d.accept(this, p);
223        }
224
225        /**
226         * Visits a {@code requires} directive.
227         * @param d  the directive to visit
228         * @param p  a visitor-specified parameter
229         * @return a visitor-specified result
230         */
231        R visitRequires(RequiresDirective d, P p);
232
233        /**
234         * Visits an {@code exports} directive.
235         * @param d  the directive to visit
236         * @param p  a visitor-specified parameter
237         * @return a visitor-specified result
238         */
239        R visitExports(ExportsDirective d, P p);
240
241        /**
242         * Visits an {@code opens} directive.
243         * @param d  the directive to visit
244         * @param p  a visitor-specified parameter
245         * @return a visitor-specified result
246         */
247        R visitOpens(OpensDirective d, P p);
248
249        /**
250         * Visits a {@code uses} directive.
251         * @param d  the directive to visit
252         * @param p  a visitor-specified parameter
253         * @return a visitor-specified result
254         */
255        R visitUses(UsesDirective d, P p);
256
257        /**
258         * Visits a {@code provides} directive.
259         * @param d  the directive to visit
260         * @param p  a visitor-specified parameter
261         * @return a visitor-specified result
262         */
263        R visitProvides(ProvidesDirective d, P p);
264
265        /**
266         * Visits an unknown directive.
267         * This can occur if the language evolves and new kinds of directive are added.
268         * @param d  the directive to visit
269         * @param p  a visitor-specified parameter
270         * @return a visitor-specified result
271         * @throws UnknownDirectiveException a visitor implementation may optionally throw this exception
272         * @implSpec This implementation throws {@code new UnknownDirectiveException(d, p)}.
273         */
274        default R visitUnknown(Directive d, P p) {
275            throw new UnknownDirectiveException(d, p);
276        }
277    }
278
279    /**
280     * A dependency of a module.
281     * @since 9
282     * @spec JPMS
283     */
284    interface RequiresDirective extends Directive {
285        /**
286         * Returns whether or not this is a static dependency.
287         * @return whether or not this is a static dependency
288         */
289        boolean isStatic();
290
291        /**
292         * Returns whether or not this is a transitive dependency.
293         * @return whether or not this is a transitive dependency
294         */
295        boolean isTransitive();
296
297        /**
298         * Returns the module that is required
299         * @return the module that is required
300         */
301        ModuleElement getDependency();
302    }
303
304    /**
305     * An exported package of a module.
306     * @since 9
307     * @spec JPMS
308     */
309    interface ExportsDirective extends Directive {
310
311        /**
312         * Returns the package being exported.
313         * @return the package being exported
314         */
315        PackageElement getPackage();
316
317        /**
318         * Returns the specific modules to which the package is being exported,
319         * or null, if the package is exported to all modules which
320         * have readability to this module.
321         * @return the specific modules to which the package is being exported
322         */
323        List<? extends ModuleElement> getTargetModules();
324    }
325
326    /**
327     * An opened package of a module.
328     * @since 9
329     * @spec JPMS
330     */
331    interface OpensDirective extends Directive {
332
333        /**
334         * Returns the package being opened.
335         * @return the package being opened
336         */
337        PackageElement getPackage();
338
339        /**
340         * Returns the specific modules to which the package is being open
341         * or null, if the package is open all modules which
342         * have readability to this module.
343         * @return the specific modules to which the package is being opened
344         */
345        List<? extends ModuleElement> getTargetModules();
346    }
347
348    /**
349     * An implementation of a service provided by a module.
350     * @since 9
351     * @spec JPMS
352     */
353    interface ProvidesDirective extends Directive {
354        /**
355         * Returns the service being provided.
356         * @return the service being provided
357         */
358        TypeElement getService();
359
360        /**
361         * Returns the implementations of the service being provided.
362         * @return the implementations of the service being provided
363         */
364        List<? extends TypeElement> getImplementations();
365    }
366
367    /**
368     * A reference to a service used by a module.
369     * @since 9
370     * @spec JPMS
371     */
372    interface UsesDirective extends Directive {
373        /**
374         * Returns the service that is used.
375         * @return the service that is used
376         */
377        TypeElement getService();
378    }
379}
380