1/*
2 * Copyright (c) 2015, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package compiler.compilercontrol.share.scenario;
25
26import compiler.compilercontrol.share.JSONFile;
27import compiler.compilercontrol.share.method.MethodDescriptor;
28
29import java.util.List;
30
31/**
32 * Simple directive file writer.
33 */
34public class DirectiveWriter implements AutoCloseable {
35    private final JSONFile jsonFile;
36
37    /**
38     * Builds directive file for the given name
39     *
40     * @param fileName name the file to be created
41     */
42    public DirectiveWriter(String fileName) {
43        jsonFile = new JSONFile(fileName);
44    }
45
46    /**
47     * Emits match block with a given methods
48     *
49     * @param methods methods used for the match
50     * @return this DirectiveWriter instance
51     */
52    public DirectiveWriter match(String... methods) {
53        if (jsonFile.getElement() == null) {
54            write(JSONFile.Element.ARRAY);
55        }
56        write(JSONFile.Element.OBJECT);
57        write(JSONFile.Element.PAIR, "match");
58        writeMethods(methods);
59        return this;
60    }
61
62    /**
63     * Emits match block with a given methods
64     *
65     * @param methodDescriptors method descriptors used for the match
66     * @return this DirectiveWriter instance
67     */
68    public DirectiveWriter match(MethodDescriptor... methodDescriptors) {
69        String[] methods = new String[methodDescriptors.length];
70        for (int i = 0; i < methodDescriptors.length; i++) {
71            methods[i] = methodDescriptors[i].getString();
72        }
73        match(methods);
74        return this;
75    }
76
77    /**
78     * Emits inline block with a given methods to be inlined or not.
79     * Each method should be prepended with + or - to show if it should be
80     * inlined or not.
81     *
82     * @param methods methods used for the inline
83     * @return this DirectiveWriter instance
84     */
85    public DirectiveWriter inline(String... methods) {
86        write(JSONFile.Element.PAIR, "inline");
87        writeMethods(methods);
88        return this;
89    }
90
91    /**
92     * Emits inline block with a given methods to be inlined or not.
93     * Each method should be prepended with + or - to show if it should be
94     * inlined or not.
95     *
96     * @param methods methods used for the inline
97     * @return this DirectiveWriter instance
98     */
99    public DirectiveWriter inline(List<String> methods) {
100        write(JSONFile.Element.PAIR, "inline");
101        writeMethods(methods.toArray(new String[methods.size()]));
102        return this;
103    }
104
105    private void writeMethods(String[] methods) {
106        if (methods.length == 0) {
107            throw new IllegalArgumentException("ERROR: empty methods array");
108        }
109        if (methods.length > 1) {
110            write(JSONFile.Element.ARRAY);
111            for (String method : methods) {
112                write(JSONFile.Element.VALUE, "\"" + method + "\"");
113            }
114            end(); // ends array
115        } else {
116            write(JSONFile.Element.VALUE, "\"" + methods[0] + "\"");
117        }
118    }
119
120    /**
121     * Emits compiler blocks that makes current match to be excluded or not
122     * from compilation with specified compiler
123     *
124     * @param compiler compiler to be excluded or null, for all
125     * @param exclude  shows if compiler should be disabled for this match
126     * @return this DirectiveWriter instance
127     */
128    public DirectiveWriter excludeCompile(Scenario.Compiler compiler,
129                                          boolean exclude) {
130        for (Scenario.Compiler comp : Scenario.Compiler.values()) {
131            emitCompiler(comp);
132            if (comp == compiler || compiler == null) {
133                option(Option.EXCLUDE, exclude);
134            } else {
135                // just make this block be enabled
136                option(Option.ENABLE, true);
137            }
138            end(); // end compiler block
139        }
140        return this;
141    }
142
143    /**
144     * Emits compiler directive block
145     *
146     * @return this DirectiveWriter instance
147     */
148    public DirectiveWriter emitCompiler(Scenario.Compiler compiler) {
149        write(JSONFile.Element.PAIR, compiler.name);
150        write(JSONFile.Element.OBJECT);
151        return this;
152    }
153
154    @Override
155    public void close() {
156        jsonFile.close();
157    }
158
159    /**
160     * Ends current object element. It could be either a
161     * c1 or c2 block, or a whole match block
162     *
163     * @return this DirectiveWriter instance
164     */
165    public DirectiveWriter end() {
166        jsonFile.end();
167        return this;
168    }
169
170    public DirectiveWriter write(JSONFile.Element element, String... value) {
171        jsonFile.write(element, value);
172        return this;
173    }
174
175    /**
176     * Emits directive option with a given value
177     *
178     * @param option directive to be set
179     * @param value value of the directive
180     * @return this DirectiveWriter instance
181     */
182    public DirectiveWriter option(Option option, Object value) {
183        write(JSONFile.Element.PAIR, option.string);
184        write(JSONFile.Element.VALUE, String.valueOf(value));
185        return this;
186    }
187
188    /**
189     * Directive option list
190     */
191    public enum Option {
192        PRINT_ASSEMBLY("PrintAssembly"),
193        LOG("Log"),
194        EXCLUDE("Exclude"),
195        ENABLE("Enable");
196
197        public final String string;
198
199        private Option(String directive) {
200            this.string = directive;
201        }
202    }
203}
204