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 
  24 package compiler.compilercontrol.share.scenario;
  25 
  26 import compiler.compilercontrol.share.JSONFile;
  27 import compiler.compilercontrol.share.method.MethodDescriptor;
  28 
  29 /**
  30  * Simple directive file writer.
  31  */
  32 public class DirectiveWriter implements AutoCloseable {
  33     private final JSONFile jsonFile;
  34 
  35     /**
  36      * Builds directive file for the given name
  37      *
  38      * @param fileName name the file to be created
  39      */
  40     public DirectiveWriter(String fileName) {
  41         jsonFile = new JSONFile(fileName);
  42     }
  43 
  44     /**
  45      * Emits match block with a given methods
  46      *
  47      * @param methods methods used for the match
  48      * @return this DirectiveWriter instance
  49      */
  50     public DirectiveWriter match(String... methods) {
  51         if (jsonFile.getElement() == null) {
  52             write(JSONFile.Element.ARRAY);
  53         }
  54         write(JSONFile.Element.OBJECT);
  55         write(JSONFile.Element.PAIR, "match");
  56         writeMethods(methods);
  57         return this;
  58     }
  59 
  60     /**
  61      * Emits match block with a given methods
  62      *
  63      * @param methodDescriptors method descriptors used for the match
  64      * @return this DirectiveWriter instance
  65      */
  66     public DirectiveWriter match(MethodDescriptor... methodDescriptors) {
  67         String[] methods = new String[methodDescriptors.length];
  68         for (int i = 0; i < methodDescriptors.length; i++) {
  69             methods[i] = methodDescriptors[i].getString();
  70         }
  71         match(methods);
  72         return this;
  73     }
  74 
  75     /**
  76      * Emits inline block with a given methods to be inlined or not.
  77      * Each method should be prepended with + or - to show if it should be
  78      * inlined or not.
  79      *
  80      * @param methods methods used for the inline
  81      * @return this DirectiveWriter instance
  82      */
  83     public DirectiveWriter inline(String... methods) {
  84         write(JSONFile.Element.PAIR, "inline");
  85         writeMethods(methods);
  86         return this;
  87     }
  88 
  89     private void writeMethods(String[] methods) {
  90         if (methods.length == 0) {
  91             throw new IllegalArgumentException("ERROR: empty methods array");
  92         }
  93         if (methods.length > 1) {
  94             write(JSONFile.Element.ARRAY);
  95             for (String method : methods) {
  96                 write(JSONFile.Element.VALUE, "\"" + method + "\"");
  97             }
  98             end(); // ends array
  99         } else {
 100             write(JSONFile.Element.VALUE, "\"" + methods[0] + "\"");
 101         }
 102     }
 103 
 104     /**
 105      * Emits compiler blocks that makes current match to be excluded or not
 106      * from compilation with specified compiler
 107      *
 108      * @param compiler compiler to be excluded or null, for all
 109      * @param exclude  shows if compiler should be disabled for this match
 110      * @return this DirectiveWriter instance
 111      */
 112     public DirectiveWriter excludeCompile(Scenario.Compiler compiler,
 113                                           boolean exclude) {
 114         if (compiler != null) {
 115             emitCompiler(compiler);
 116             option(Option.EXCLUDE, exclude);
 117             end();
 118         } else {
 119             for (Scenario.Compiler comp : Scenario.Compiler.values()) {
 120                 emitCompiler(comp);
 121                 option(Option.EXCLUDE, exclude);
 122                 end(); // end compiler block
 123             }
 124         }
 125         return this;
 126     }
 127 
 128     /**
 129      * Emits compiler directive block
 130      *
 131      * @return this DirectiveWriter instance
 132      */
 133     public DirectiveWriter emitCompiler(Scenario.Compiler compiler) {
 134         write(JSONFile.Element.PAIR, compiler.name);
 135         write(JSONFile.Element.OBJECT);
 136         return this;
 137     }
 138 
 139     @Override
 140     public void close() {
 141         jsonFile.close();
 142     }
 143 
 144     /**
 145      * Ends current object element. It could be either a
 146      * c1 or c2 block, or a whole match block
 147      *
 148      * @return this DirectiveWriter instance
 149      */
 150     public DirectiveWriter end() {
 151         jsonFile.end();
 152         return this;
 153     }
 154 
 155     public DirectiveWriter write(JSONFile.Element element, String... value) {
 156         jsonFile.write(element, value);
 157         return this;
 158     }
 159 
 160     /**
 161      * Emits directive option with a given value
 162      *
 163      * @param option directive to be set
 164      * @param value value of the directive
 165      * @return this DirectiveWriter instance
 166      */
 167     public DirectiveWriter option(Option option, Object value) {
 168         write(JSONFile.Element.PAIR, option.string);
 169         write(JSONFile.Element.VALUE, String.valueOf(value));
 170         return this;
 171     }
 172 
 173     /**
 174      * Directive option list
 175      */
 176     public enum Option {
 177         PRINT_ASSEMBLY("PrintAssembly"),
 178         LOG("Log"),
 179         EXCLUDE("Exclude");
 180 
 181         public final String string;
 182 
 183         private Option(String directive) {
 184             this.string = directive;
 185         }
 186     }
 187 }