Directive.java revision 3971:65d446c80cdf
1/*
2 * Copyright (c) 2009, 2016, 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 com.sun.tools.javac.code;
27
28import java.util.Collections;
29import java.util.EnumSet;
30import java.util.Set;
31
32import javax.lang.model.element.ModuleElement;
33import javax.lang.model.element.PackageElement;
34import javax.lang.model.element.TypeElement;
35
36import com.sun.tools.javac.code.Symbol.ClassSymbol;
37import com.sun.tools.javac.code.Symbol.ModuleSymbol;
38import com.sun.tools.javac.code.Symbol.PackageSymbol;
39import com.sun.tools.javac.util.DefinedBy;
40import com.sun.tools.javac.util.DefinedBy.Api;
41import com.sun.tools.javac.util.List;
42
43
44/**
45 *  Root class for the directives that may appear in module compilation units.
46 *
47 *  <p><b>This is NOT part of any supported API.
48 *  If you write code that depends on this, you do so at your own risk.
49 *  This code and its internal interfaces are subject to change or
50 *  deletion without notice.</b>
51 */
52public abstract class Directive implements ModuleElement.Directive {
53
54    /** Flags for RequiresDirective. */
55    public enum RequiresFlag {
56        TRANSITIVE(0x0020),
57        STATIC_PHASE(0x0040),
58        SYNTHETIC(0x1000),
59        MANDATED(0x8000),
60        EXTRA(0x10000);
61
62        // overkill? move to ClassWriter?
63        public static int value(Set<RequiresFlag> s) {
64            int v = 0;
65            for (RequiresFlag f: s)
66                v |= f.value;
67            return v;
68        }
69
70        RequiresFlag(int value) {
71            this.value = value;
72        }
73
74        public final int value;
75    }
76
77    /** Flags for ExportsDirective. */
78    public enum ExportsFlag {
79        SYNTHETIC(0x1000),
80        MANDATED(0x8000);
81
82        // overkill? move to ClassWriter?
83        public static int value(Set<ExportsFlag> s) {
84            int v = 0;
85            for (ExportsFlag f: s)
86                v |= f.value;
87            return v;
88        }
89
90        ExportsFlag(int value) {
91            this.value = value;
92        }
93
94        public final int value;
95    }
96
97    /**
98     * 'exports' Package ';'
99     * 'exports' Package 'to' ModuleList ';'
100     */
101    public static class ExportsDirective extends Directive
102            implements ModuleElement.ExportsDirective {
103        public final PackageSymbol packge;
104        public final List<ModuleSymbol> modules;
105        public final Set<ExportsFlag> flags;
106
107        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
108            this(packge, modules, EnumSet.noneOf(ExportsFlag.class));
109        }
110
111        public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags) {
112            this.packge = packge;
113            this.modules = modules;
114            this.flags = flags;
115        }
116
117        @Override @DefinedBy(Api.LANGUAGE_MODEL)
118        public ModuleElement.DirectiveKind getKind() {
119            return ModuleElement.DirectiveKind.EXPORTS;
120        }
121
122        @Override @DefinedBy(Api.LANGUAGE_MODEL)
123        public PackageSymbol getPackage() {
124            return packge;
125        }
126
127        @Override @DefinedBy(Api.LANGUAGE_MODEL)
128        public java.util.List<ModuleSymbol> getTargetModules() {
129            return modules == null
130                    ? null
131                    : Collections.unmodifiableList(modules);
132        }
133
134        @Override
135        public String toString() {
136            if (modules == null)
137                return "Exports[" + packge + "]";
138            else
139                return "Exports[" + packge + ":" + modules + "]";
140        }
141    }
142
143    /** Flags for OpensDirective. */
144    public enum OpensFlag {
145        SYNTHETIC(0x1000),
146        MANDATED(0x8000);
147
148        // overkill? move to ClassWriter?
149        public static int value(Set<OpensFlag> s) {
150            int v = 0;
151            for (OpensFlag f: s)
152                v |= f.value;
153            return v;
154        }
155
156        OpensFlag(int value) {
157            this.value = value;
158        }
159
160        public final int value;
161    }
162
163    /**
164     * 'opens' Package ';'
165     * 'opens' Package 'to' ModuleList ';'
166     */
167    public static class OpensDirective extends Directive
168            implements ModuleElement.OpensDirective {
169        public final PackageSymbol packge;
170        public final List<ModuleSymbol> modules;
171        public final Set<OpensFlag> flags;
172
173        public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
174            this(packge, modules, EnumSet.noneOf(OpensFlag.class));
175        }
176
177        public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags) {
178            this.packge = packge;
179            this.modules = modules;
180            this.flags = flags;
181        }
182
183        @Override @DefinedBy(Api.LANGUAGE_MODEL)
184        public ModuleElement.DirectiveKind getKind() {
185            return ModuleElement.DirectiveKind.OPENS;
186        }
187
188        @Override @DefinedBy(Api.LANGUAGE_MODEL)
189        public PackageSymbol getPackage() {
190            return packge;
191        }
192
193        @Override @DefinedBy(Api.LANGUAGE_MODEL)
194        public java.util.List<ModuleSymbol> getTargetModules() {
195            return modules == null
196                    ? null
197                    : Collections.unmodifiableList(modules);
198        }
199
200        @Override
201        public String toString() {
202            if (modules == null)
203                return "Opens[" + packge + "]";
204            else
205                return "Opens[" + packge + ":" + modules + "]";
206        }
207    }
208
209    /**
210     * 'provides' ServiceName 'with' QualifiedIdentifer ';'
211     */
212    public static class ProvidesDirective extends Directive
213            implements ModuleElement.ProvidesDirective {
214        public final ClassSymbol service;
215        public final List<ClassSymbol> impls;
216
217        public ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls) {
218            this.service = service;
219            this.impls = impls;
220        }
221
222        @Override @DefinedBy(Api.LANGUAGE_MODEL)
223        public ModuleElement.DirectiveKind getKind() {
224            return ModuleElement.DirectiveKind.PROVIDES;
225        }
226
227        @Override @DefinedBy(Api.LANGUAGE_MODEL)
228        public ClassSymbol getService() {
229            return service;
230        }
231
232        @Override @DefinedBy(Api.LANGUAGE_MODEL)
233        public List<ClassSymbol> getImplementations() {
234            return impls;
235        }
236
237        @Override
238        public String toString() {
239            return "Provides[" + service + "," + impls + "]";
240        }
241
242        // TODO: delete?
243        @Override
244        public boolean equals(Object obj) {
245            if (!(obj instanceof ProvidesDirective)) {
246                return false;
247            }
248            ProvidesDirective other = (ProvidesDirective)obj;
249            return service == other.service && impls.equals(other.impls);
250        }
251
252        // TODO: delete?
253        @Override
254        public int hashCode() {
255            return service.hashCode() * 31 + impls.hashCode() * 37;
256        }
257    }
258
259    /**
260     * 'requires' ('static' | 'transitive')* ModuleName ';'
261     */
262    public static class RequiresDirective extends Directive
263            implements ModuleElement.RequiresDirective {
264        public final ModuleSymbol module;
265        public final Set<RequiresFlag> flags;
266
267        public RequiresDirective(ModuleSymbol module) {
268            this(module, EnumSet.noneOf(RequiresFlag.class));
269        }
270
271        public RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags) {
272            this.module = module;
273            this.flags = flags;
274        }
275
276        @Override @DefinedBy(Api.LANGUAGE_MODEL)
277        public ModuleElement.DirectiveKind getKind() {
278            return ModuleElement.DirectiveKind.REQUIRES;
279        }
280
281        @Override @DefinedBy(Api.LANGUAGE_MODEL)
282        public boolean isStatic() {
283            return flags.contains(RequiresFlag.STATIC_PHASE);
284        }
285
286        @Override @DefinedBy(Api.LANGUAGE_MODEL)
287        public boolean isTransitive() {
288            return flags.contains(RequiresFlag.TRANSITIVE);
289        }
290
291        @Override @DefinedBy(Api.LANGUAGE_MODEL)
292        public ModuleSymbol getDependency() {
293            return module;
294        }
295
296        @Override
297        public String toString() {
298            return "Requires[" + flags + "," + module + "]";
299        }
300    }
301
302    /**
303     * 'uses' ServiceName ';'
304     */
305    public static class UsesDirective extends Directive
306            implements ModuleElement.UsesDirective {
307        public final ClassSymbol service;
308
309        public UsesDirective(ClassSymbol service) {
310            this.service = service;
311        }
312
313        @Override @DefinedBy(Api.LANGUAGE_MODEL)
314        public ModuleElement.DirectiveKind getKind() {
315            return ModuleElement.DirectiveKind.USES;
316        }
317
318        @Override @DefinedBy(Api.LANGUAGE_MODEL)
319        public ClassSymbol getService() {
320            return service;
321        }
322
323        @Override
324        public String toString() {
325            return "Uses[" + service + "]";
326        }
327
328        // TODO: delete?
329        @Override
330        public boolean equals(Object obj) {
331            if (!(obj instanceof UsesDirective)) {
332                return false;
333            }
334            UsesDirective other = (UsesDirective)obj;
335            return service == other.service;
336        }
337
338        // TODO: delete?
339        @Override
340        public int hashCode() {
341            return service.hashCode() * 31;
342        }
343    }
344}
345