001 /* 002 * Copyright © 2008, 2009 Pedro Agulló Soliveres. 003 * 004 * This file is part of DirectJNgine. 005 * 006 * DirectJNgine is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU Lesser General Public License as published by 008 * the Free Software Foundation, either version 3 of the License. 009 * 010 * Commercial use is permitted to the extent that the code/component(s) 011 * do NOT become part of another Open Source or Commercially developed 012 * licensed development library or toolkit without explicit permission. 013 * 014 * DirectJNgine is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU Lesser General Public License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public License 020 * along with DirectJNgine. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * This software uses the ExtJs library (http://extjs.com), which is 023 * distributed under the GPL v3 license (see http://extjs.com/license). 024 */ 025 026 package com.softwarementors.extjs.djn.jscodegen; 027 028 import java.lang.reflect.Method; 029 import java.util.List; 030 031 import com.softwarementors.extjs.djn.ClassUtils; 032 import com.softwarementors.extjs.djn.api.RegisteredAction; 033 import com.softwarementors.extjs.djn.api.RegisteredApi; 034 import com.softwarementors.extjs.djn.api.RegisteredPollMethod; 035 import com.softwarementors.extjs.djn.api.RegisteredStandardMethod; 036 import com.softwarementors.extjs.djn.config.GlobalConfiguration; 037 import com.softwarementors.extjs.djn.router.processor.poll.PollRequestProcessor; 038 039 import edu.umd.cs.findbugs.annotations.NonNull; 040 041 public class ApiCodeGenerator { 042 043 private static final String REMOTING_TYPE = "remoting"; 044 @NonNull private RegisteredApi api; 045 @NonNull private GlobalConfiguration globalConfiguration; 046 047 public ApiCodeGenerator( GlobalConfiguration globalConfiguration, RegisteredApi api ) { 048 assert globalConfiguration != null; 049 assert api != null; 050 051 this.globalConfiguration = globalConfiguration; 052 this.api = api; 053 } 054 055 private static final String TABS_1 = " "; 056 private static final String TABS_2 = " "; 057 private static final String TABS_3 = " "; 058 059 public void appendCode( StringBuilder result, boolean minify) { 060 assert result != null; 061 062 if( !minify ) { 063 result.append( "/**********************************************************************\n"); 064 result.append( " * \n"); 065 result.append( " * Code generated automatically by DirectJNgine\n"); 066 result.append( " * Copyright (c) 2009, Pedro Agulló Soliveres\n"); 067 result.append( " * \n"); 068 result.append( " * DO NOT MODIFY MANUALLY!!\n"); 069 result.append( " * \n"); 070 result.append( " **********************************************************************/\n"); 071 result.append( "\n"); 072 } 073 appendNamespaceAndProviderUrlSection(result); 074 appendPollingUrlsSection(result, minify); 075 appendActionsSection(result, minify); 076 } 077 078 private void appendNamespaceAndProviderUrlSection(StringBuilder result) { 079 assert result != null; 080 081 result.append( "Ext.namespace( '"); result.append( this.api.getApiNamespace()); result.append("');\n" ); 082 if( !this.api.getActionsNamespace().equals("")) { 083 result.append( "Ext.namespace( '"); result.append( this.api.getActionsNamespace()); result.append("');\n" ); 084 } 085 result.append('\n'); 086 result.append( this.api.getApiNamespace() ); result.append( ".PROVIDER_BASE_URL=" ); appendJsExpressionToGetBaseUrl(result); result.append( this.globalConfiguration.getProvidersUrl() ); result.append( "';"); 087 result.append('\n'); 088 result.append('\n'); 089 } 090 091 private void appendJsExpressionToGetBaseUrl(StringBuilder result) { 092 assert result != null; 093 094 String contextPath = this.globalConfiguration.getContextPath(); 095 if( contextPath == null ) { 096 String JSCRIPT_CALCULATED_CONTEXT_PATH = "(window.location.pathname.split('/').length>2 ? window.location.pathname.split('/')[1]+ '/' : '') + '"; 097 result.append( "window.location.protocol + '//' + window.location.host + '/' + " + JSCRIPT_CALCULATED_CONTEXT_PATH ); 098 } 099 else { 100 if( !contextPath.startsWith("/")) { 101 contextPath = "/" + contextPath; 102 } 103 if( !contextPath.endsWith("/")) { 104 contextPath += "/"; 105 } 106 result.append( "window.location.protocol + '//' + window.location.host + '" + contextPath + "' + '" ); 107 } 108 } 109 110 private void appendPollingUrlsSection(StringBuilder result, boolean minify) { 111 assert result != null; 112 113 result.append( this.api.getApiNamespace() ); result.append( ".POLLING_URLS = {\n"); 114 List<RegisteredPollMethod> pollMethods = this.api.getPollMethods(); 115 for( int i = 0; i < pollMethods.size(); i++ ) { 116 RegisteredPollMethod pollMethod = pollMethods.get(i); 117 boolean isLast = i == pollMethods.size() - 1; 118 appendPollUrl(result, pollMethod, minify); 119 if( !isLast ) { 120 result.append( ", "); 121 } 122 result.append( "\n"); 123 } 124 result.append( "}\n"); 125 result.append( "\n"); 126 } 127 128 private void appendPollUrl(StringBuilder result, RegisteredPollMethod pollMethod, boolean minify) { 129 assert result != null; 130 assert pollMethod != null; 131 132 result.append( TABS_1 ); result.append( pollMethod.getName()); result.append( " : "); 133 result.append( this.api.getApiNamespace() ); result.append( ".PROVIDER_BASE_URL + " ); result.append( "'" ); result.append( PollRequestProcessor.PATHINFO_POLL_PREFIX); result.append( pollMethod.getName() ); result.append( "' " ); 134 if( !minify ) { 135 appendPollUrlExtraInformation(result, pollMethod); 136 } 137 } 138 139 private void appendPollUrlExtraInformation(StringBuilder result, RegisteredPollMethod pollMethod) { 140 result.append( "/* "); appendMethodExtraInformation(pollMethod.getMethod(), pollMethod.getActionClass(), false, result); 141 result.append( " -- calls "); result.append( ClassUtils.getNicePrintableName(pollMethod.getActionClass()) ); result.append( "."); result.append( pollMethod.getMethod().getName() ); 142 result.append( " */"); 143 } 144 145 private void appendActionsSection(StringBuilder result, boolean minify) { 146 assert result != null; 147 148 appendActionsStart(result); 149 List<RegisteredAction> actions = this.api.getActions(); 150 151 for( int i = 0; i < actions.size(); i++ ) { 152 boolean isLast = i == actions.size() - 1; 153 appendAction( actions.get(i), result, isLast, minify ); 154 } 155 appendActionsEnd(result); 156 } 157 158 private void appendActionsStart( StringBuilder result ) { 159 assert result != null; 160 161 result.append( this.api.getApiNamespace() ); result.append( ".REMOTING_API"); result.append( " = {\n" ); 162 163 result.append(" url: " ); result.append( this.api.getApiNamespace() ); result.append( ".PROVIDER_BASE_URL") ; result.append( ",\n" ); 164 result.append(" type: '" ); result.append( REMOTING_TYPE ); result.append( "',\n" ); 165 if( !this.api.getActionsNamespace().equals("")) { 166 result.append( " namespace: " ); result.append( this.api.getActionsNamespace()); result.append( ",\n"); 167 } 168 result.append(" actions: {\n" ); 169 } 170 171 private void appendActionsEnd( StringBuilder result ) { 172 assert result != null; 173 174 result.append( " }\n" ); 175 result.append( "}\n" ); 176 result.append( '\n'); 177 } 178 179 private void appendAction(RegisteredAction action, StringBuilder result, boolean isLast, boolean minify ) { 180 assert action != null; 181 assert result != null; 182 183 result.append( TABS_2 ); result.append( action.getName() ); result.append( ": [\n"); 184 185 List<RegisteredStandardMethod> methods = action.getStandardMethods(); 186 for( int i = 0; i < methods.size(); i++ ) { 187 boolean isLastMethod = i == methods.size() - 1; 188 appendMethod( methods.get(i), result, isLastMethod, minify ); 189 } 190 191 result.append( TABS_2 ); result.append( "]" ); if( !isLast ) { result.append(","); } result.append('\n'); 192 } 193 194 private void appendMethod(RegisteredStandardMethod method, StringBuilder result, boolean isLast, boolean minify) { 195 assert method != null; 196 assert result != null; 197 198 result.append( TABS_3 ); result.append( "{\n"); 199 result.append( TABS_3 ); result.append( " name: '"); result.append( method.getName() ); result.append( "'" ); 200 if( !minify ) { 201 appendMethodExtraInformation(method, result); 202 } 203 result.append( ",\n"); 204 result.append( TABS_3 ); result.append( " len: "); result.append( method.getClientParameterCount() ); result.append( ",\n"); 205 result.append( TABS_3 ); result.append( " formHandler: "); result.append( method.isFormHandler() ); result.append( "\n"); 206 result.append( TABS_3 ); result.append( "}" ); if( !isLast ) { result.append(","); } result.append( '\n'); 207 } 208 209 private void appendMethodExtraInformation(RegisteredStandardMethod method, StringBuilder result) { 210 assert method != null; 211 assert result != null; 212 213 result.append( "/*"); 214 215 appendMethodExtraInformation( method.getMethod(), method.getActionClass(), !method.isFormHandler(), result ); 216 217 if( method.isFormHandler()) { 218 result.append( " -- FORM HANDLER"); 219 } 220 result.append( " */"); 221 } 222 223 private void appendMethodExtraInformation( Method method, Class<?> classOwningMethod, boolean writeJavaParameterTypes, StringBuilder result ) { 224 assert method != null; 225 assert classOwningMethod != null; 226 assert result != null; 227 228 // Append parameters 229 result.append( "("); 230 if( writeJavaParameterTypes ) { 231 Class<?>[] parameterTypes = method.getParameterTypes(); 232 for( int i=0; i < parameterTypes.length; i++ ) { 233 boolean isLast = i == parameterTypes.length - 1; 234 Class<?> cls = parameterTypes[i]; 235 result.append( ClassUtils.getNicePrintableName(cls) ); 236 if( !isLast ) { 237 result.append( ", "); 238 } 239 } 240 } 241 result.append( ")"); 242 243 // Append result type 244 Class<?> resultType = method.getReturnType(); 245 if( !resultType.equals(Void.class)) { 246 result.append( " => "); 247 result.append( ClassUtils.getNicePrintableName(resultType)); 248 } 249 250 } 251 }