1 /* 2 * Copyright (C) 2016 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.googlecode.android_scripting.language; 18 19 import com.googlecode.android_scripting.rpc.MethodDescriptor; 20 import com.googlecode.android_scripting.rpc.ParameterDescriptor; 21 22 import java.util.HashMap; 23 import java.util.Map; 24 25 /** 26 * Represents the programming language supported by the SL4A. 27 * 28 * @author igor.v.karp@gmail.com (Igor Karp) 29 */ 30 public class Language { 31 32 private final static Map<Character, String> AUTO_CLOSE_MAP = buildAutoCloseMap('[', "[]", '{', 33 "{}", '(', "()", '\'', "''", '"', "\"\""); 34 35 /** Returns the initial template for newly created script. */ getContentTemplate()36 public String getContentTemplate() { 37 StringBuilder content = new StringBuilder(getImportStatement()); 38 if (content.length() != 0) { 39 content.append('\n'); 40 } 41 content.append(getRpcReceiverDeclaration(getDefaultRpcReceiver())); 42 return content.toString(); 43 } 44 45 /** Returns the Android package import statement. */ getImportStatement()46 protected String getImportStatement() { 47 return ""; 48 } 49 50 /** Returns the RPC receiver declaration. */ getRpcReceiverDeclaration(String rpcReceiver)51 protected String getRpcReceiverDeclaration(String rpcReceiver) { 52 return ""; 53 } 54 55 /** Returns the default RPC receiver name. */ getDefaultRpcReceiver()56 protected String getDefaultRpcReceiver() { 57 return "droid"; 58 } 59 60 /** 61 * Returns the string containing opening and closing tokens if the input is an opening token. 62 * Returns {@code null} otherwise. 63 */ autoClose(char token)64 public String autoClose(char token) { 65 return AUTO_CLOSE_MAP.get(token); 66 } 67 68 /** Returns the RPC call text with given parameter values. */ getRpcText(String content, MethodDescriptor rpc, String[] values)69 public final String getRpcText(String content, MethodDescriptor rpc, String[] values) { 70 return getMethodCallText(getRpcReceiverName(content), rpc.getName(), 71 rpc.getParameterValues(values)); 72 } 73 74 /** Returns the RPC receiver found in the given script. */ getRpcReceiverName(String content)75 protected String getRpcReceiverName(String content) { 76 return getDefaultRpcReceiver(); 77 } 78 79 /** Returns the method call text in the language. */ getMethodCallText(String receiver, String method, ParameterDescriptor[] parameters)80 protected String getMethodCallText(String receiver, String method, 81 ParameterDescriptor[] parameters) { 82 StringBuilder result = 83 new StringBuilder().append(getApplyReceiverText(receiver)).append(getApplyOperatorText()) 84 .append(method).append(getLeftParametersText()); 85 String separator = ""; 86 for (ParameterDescriptor parameter : parameters) { 87 result.append(separator).append(getValueText(parameter)); 88 separator = getParameterSeparator(); 89 } 90 result.append(getRightParametersText()); 91 92 return result.toString(); 93 } 94 95 /** Returns the apply receiver text. */ getApplyReceiverText(String receiver)96 protected String getApplyReceiverText(String receiver) { 97 return receiver; 98 } 99 100 /** Returns the apply operator text. */ getApplyOperatorText()101 protected String getApplyOperatorText() { 102 return "."; 103 } 104 105 /** Returns the text to the left of the parameters. */ getLeftParametersText()106 protected String getLeftParametersText() { 107 return "("; 108 } 109 110 /** Returns the text to the right of the parameters. */ getRightParametersText()111 protected String getRightParametersText() { 112 return ")"; 113 } 114 115 /** Returns the parameter separator text. */ getParameterSeparator()116 protected String getParameterSeparator() { 117 return ", "; 118 } 119 120 /** Returns the text of the quotation. */ getQuote()121 protected String getQuote() { 122 return "\""; 123 } 124 125 /** Returns the text of the {@code null} value. */ getNull()126 protected String getNull() { 127 return "null"; 128 } 129 130 /** Returns the text of the {{@code true} value. */ getTrue()131 protected String getTrue() { 132 return "true"; 133 } 134 135 /** Returns the text of the false value. */ getFalse()136 protected String getFalse() { 137 return "false"; 138 } 139 140 /** Returns the parameter value suitable for code generation. */ getValueText(ParameterDescriptor parameter)141 protected String getValueText(ParameterDescriptor parameter) { 142 if (parameter.getValue() == null) { 143 return getNullValueText(); 144 } else if (parameter.getType().equals(String.class)) { 145 return getStringValueText(parameter.getValue()); 146 } else if (parameter.getType().equals(Boolean.class)) { 147 return getBooleanValueText(parameter.getValue()); 148 } else { 149 return parameter.getValue(); 150 } 151 } 152 153 /** Returns the null value suitable for code generation. */ getNullValueText()154 private String getNullValueText() { 155 return getNull(); 156 } 157 158 /** Returns the string parameter value suitable for code generation. */ getStringValueText(String value)159 protected String getStringValueText(String value) { 160 // TODO(igorkarp): do not quote expressions once they could be detected. 161 return getQuote() + value + getQuote(); 162 } 163 164 /** Returns the boolean parameter value suitable for code generation. */ getBooleanValueText(String value)165 protected String getBooleanValueText(String value) { 166 if (value.equals(Boolean.TRUE.toString())) { 167 return getTrue(); 168 } else if (value.equals(Boolean.FALSE.toString())) { 169 return getFalse(); 170 } else { 171 // If it is neither true nor false it is must be an expression. 172 return value; 173 } 174 } 175 buildAutoCloseMap(char c1, String s1, char c2, String s2, char c3, String s3, char c4, String s4, char c5, String s5)176 private static Map<Character, String> buildAutoCloseMap(char c1, String s1, char c2, String s2, 177 char c3, String s3, char c4, String s4, char c5, String s5) { 178 Map<Character, String> map = new HashMap<Character, String>(5); 179 map.put(c1, s1); 180 map.put(c2, s2); 181 map.put(c3, s3); 182 map.put(c4, s4); 183 map.put(c5, s5); 184 return map; 185 } 186 } 187