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