| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.web.client.rest.wizard; |
| |
| import java.io.IOException; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.EnumMap; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Future; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import javax.lang.model.element.AnnotationMirror; |
| import javax.lang.model.element.AnnotationValue; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ExecutableElement; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.element.VariableElement; |
| import javax.lang.model.type.DeclaredType; |
| import javax.lang.model.type.TypeMirror; |
| import javax.lang.model.util.ElementFilter; |
| |
| import org.netbeans.api.java.source.CompilationController; |
| import org.netbeans.api.java.source.JavaSource; |
| import org.netbeans.api.java.source.JavaSource.Phase; |
| import org.netbeans.api.java.source.Task; |
| import org.netbeans.modules.web.client.rest.wizard.RestPanel.JsUi; |
| import org.netbeans.modules.websvc.rest.model.api.RestServiceDescription; |
| import org.openide.filesystems.FileObject; |
| |
| |
| /** |
| * @author ads |
| * |
| */ |
| class JSClientGenerator { |
| |
| static final String TABLESORTER_URL = |
| "http://mottie.github.com/tablesorter/"; // NOI18N |
| |
| |
| enum MethodType { |
| GET, |
| SET |
| } |
| |
| enum HttpRequests { |
| POST("create"), // NOI18N |
| PUT("update"), // NOI18N |
| DELETE("delete"); // NOI18N |
| |
| HttpRequests(String method){ |
| myBackboneMethod = method; |
| } |
| @Override |
| public String toString(){ |
| return myBackboneMethod; |
| } |
| |
| private final String myBackboneMethod; |
| } |
| |
| private static final Logger LOG = Logger.getLogger( JSClientGenerator.class.getName()); |
| |
| private static final String PATH = "javax.ws.rs.Path"; // NOI18N |
| private static final String PATH_PARAM = "javax.ws.rs.PathParam";// NOI18N |
| private static final String GET = "javax.ws.rs.GET"; // NOI18N |
| private static final String PUT = "javax.ws.rs.PUT"; // NOI18N |
| private static final String POST = "javax.ws.rs.POST"; // NOI18N |
| private static final String DELETE = "javax.ws.rs.DELETE"; // NOI18N |
| private static final String PRODUCES = "javax.ws.rs.Produces"; // NOI18N |
| private static final String CONSUMES = "javax.ws.rs.Consumes"; // NOI18N |
| private static final String JSON = "application/json"; // NOI18N |
| |
| private static final String XML_ROOT_ELEMENT = |
| "javax.xml.bind.annotation.XmlRootElement"; // NOI18N |
| |
| private JSClientGenerator(RestServiceDescription description, JsUi ui){ |
| myDescription = description; |
| myUi = ui; |
| } |
| |
| static JSClientGenerator create( RestServiceDescription description, JsUi ui ) |
| { |
| return new JSClientGenerator(description, ui); |
| } |
| |
| public Map<String,String> generate( ) { |
| FileObject restSource = myDescription.getFile(); |
| if ( restSource == null ){ |
| return Collections.emptyMap(); |
| } |
| Map<String,String> result = new HashMap<String, String>(); |
| myModels = new StringBuilder(); |
| myRouters = new StringBuilder(); |
| myContent = new StringBuilder(); |
| myHeader = new StringBuilder(); |
| mySidebar = new StringBuilder(); |
| myTmplCreate = new StringBuilder(); |
| myTmplList = new StringBuilder(); |
| myTmplDetails = new StringBuilder(); |
| |
| JavaSource javaSource = JavaSource.forFileObject( restSource); |
| final String restClass = myDescription.getClassName(); |
| Task<CompilationController> task = new Task<CompilationController>(){ |
| |
| @Override |
| public void run( CompilationController controller ) throws Exception { |
| controller.toPhase( Phase.ELEMENTS_RESOLVED ); |
| |
| List<ExecutableElement> getMethods = new LinkedList<ExecutableElement>(); |
| List<ExecutableElement> postMethods = new LinkedList<ExecutableElement>(); |
| List<ExecutableElement> putMethods = new LinkedList<ExecutableElement>(); |
| List<ExecutableElement> deleteMethods = new LinkedList<ExecutableElement>(); |
| |
| TypeElement restResource = controller.getElements().getTypeElement( |
| restClass ); |
| List<ExecutableElement> methods = ElementFilter.methodsIn( |
| restResource.getEnclosedElements()); |
| for (ExecutableElement method : methods) { |
| List<? extends AnnotationMirror> annotations = |
| method.getAnnotationMirrors(); |
| if ( getAnnotation( annotations , DELETE)!= null ){ |
| deleteMethods.add( method ); |
| continue; |
| } |
| if ( !hasJsonMedia( annotations) ){ |
| continue; |
| } |
| if ( getAnnotation( annotations, GET) != null ){ |
| getMethods.add( method); |
| } |
| else if ( getAnnotation( annotations , POST)!= null ){ |
| postMethods.add( method ); |
| } |
| else if ( getAnnotation( annotations , PUT)!= null ){ |
| putMethods.add( method ); |
| } |
| } |
| |
| try { |
| handleRestMethods(controller , getMethods, postMethods, |
| putMethods, deleteMethods); |
| } |
| catch( IOException e ){ |
| LOG.log(Level.WARNING , null ,e ); |
| } |
| } |
| |
| }; |
| try { |
| Future<Void> future = javaSource.runWhenScanFinished( task, true); |
| future.get(); |
| } |
| catch (IOException e) { |
| LOG.log(Level.INFO , null ,e ); |
| } |
| catch (InterruptedException e) { |
| LOG.log(Level.INFO , null ,e ); |
| } |
| catch (ExecutionException e) { |
| LOG.log(Level.INFO , null ,e ); |
| } |
| |
| if ( !isModelGenerated ){ |
| myModels.append("// No JSON media type is detected in GET RESTful methods\n"); |
| } |
| result.put("models",myModels.toString()); // NOI18N |
| result.put("routers", myRouters.toString()); // NOI18N |
| result.put("header", myHeader.toString()); // NOI18N |
| result.put("sidebar", mySidebar.toString()); // NOI18N |
| result.put("content", myContent.toString()); // NOI18N |
| result.put("tpl_create", myTmplCreate.toString()); // NOI18N |
| result.put("tpl_list_item", myTmplList.toString()); // NOI18N |
| result.put("tpl_details", myTmplDetails.toString());// NOI18N |
| if ( hasUi() ){ |
| result.put("ui", Boolean.TRUE.toString()); // NOI18N |
| } |
| |
| return result; |
| } |
| |
| boolean hasUi(){ |
| return hasUi; |
| } |
| |
| private void handleRestMethods( CompilationController controller, |
| List<ExecutableElement> getMethods, |
| List<ExecutableElement> postMethods, |
| List<ExecutableElement> putMethods, |
| List<ExecutableElement> deleteMethods ) throws IOException |
| { |
| Map<String,ExecutableElement> noParamGetMethods = |
| new HashMap<String, ExecutableElement>(); |
| Map<String,ExecutableElement> oneParamGetMethods = |
| new HashMap<String, ExecutableElement>(); |
| for(ExecutableElement method : getMethods){ |
| List<? extends VariableElement> parameters = method.getParameters(); |
| if ( parameters.size() > 1){ |
| // TODO : handle methods with more than one param |
| continue; |
| } |
| |
| AnnotationMirror annotation = getAnnotation(method, PATH); |
| String path = getValue( annotation ); |
| if ( parameters.isEmpty() ){ |
| if ( path == null ){ |
| path = ""; // NOI18N |
| } |
| noParamGetMethods.put( path, method ); |
| continue; |
| } |
| |
| VariableElement param = parameters.get(0); |
| annotation = getAnnotation(param, PATH_PARAM); |
| if ( annotation == null ){ |
| continue; |
| } |
| String pathNoParam = removeParamTemplate( path , getValue(annotation)); |
| oneParamGetMethods.put(pathNoParam, method ); |
| } |
| Map<String,String> fqn2Path = new HashMap<String, String>(); |
| for(Entry<String,ExecutableElement> entry : noParamGetMethods.entrySet()){ |
| String path = entry.getKey(); |
| ExecutableElement method = entry.getValue(); |
| |
| TypeMirror returnType = method.getReturnType(); |
| Element returnElement = controller.getTypes().asElement( returnType ); |
| TypeMirror entityCollectionType = getCollectionType(returnType, controller); |
| if ( entityCollectionType == null && |
| returnElement instanceof TypeElement) // skip primitives ( consider just type element ) |
| { |
| if ( getAnnotation( returnElement, XML_ROOT_ELEMENT) == null ){ |
| /* TODO : here is only @XmlRootElement annotated elements |
| * are considered as JSON serializable ( that's true for |
| * NB generated entities ) but there could be probably |
| * other ways to serialize ( read/write REST providers ) |
| * POJO classes |
| */ |
| continue; |
| } |
| EnumMap<HttpRequests, String> paths = |
| new EnumMap<HttpRequests, String>(HttpRequests.class); |
| paths.put(HttpRequests.POST, parseNoIdPath(postMethods, |
| returnType, controller )); |
| paths.put(HttpRequests.PUT, parseNoIdPath(putMethods , |
| returnType , controller)); |
| paths.put(HttpRequests.DELETE, parseNoIdPath(deleteMethods, |
| returnType, controller )); |
| generate( (TypeElement)returnElement , path , |
| null, paths , Collections.<HttpRequests, Boolean>emptyMap(), |
| controller ); |
| } |
| else { |
| // collection of entities |
| Element entityType = controller.getTypes().asElement(entityCollectionType); |
| if ( entityType instanceof TypeElement ){ |
| String fqn = ((TypeElement)entityType).getQualifiedName().toString(); |
| fqn2Path.put(fqn, path); |
| } |
| } |
| } |
| for(Entry<String,ExecutableElement> entry : oneParamGetMethods.entrySet()){ |
| String path = entry.getKey(); |
| ExecutableElement method = entry.getValue(); |
| |
| TypeMirror returnType = method.getReturnType(); |
| Element returnElement = controller.getTypes().asElement( returnType ); |
| if ( returnElement instanceof TypeElement ){ |
| // TODO: return type could be a primitive type. How it should be handled ? |
| if ( getAnnotation( returnElement, XML_ROOT_ELEMENT) == null ){ |
| /* TODO : here is only @XmlRootElement annotated elements |
| * are considered as JSON serializable ( that's true for |
| * NB generated entities ) but there could be probably |
| * other ways to serialize ( read/write REST providers ) |
| * POJO classes |
| */ |
| continue; |
| } |
| String fqn = ((TypeElement)returnElement).getQualifiedName().toString(); |
| String collectionPath = fqn2Path.get(fqn); |
| EnumMap<HttpRequests, String> paths = |
| new EnumMap<HttpRequests, String>(HttpRequests.class); |
| EnumMap<HttpRequests, Boolean> ids = |
| new EnumMap<HttpRequests, Boolean>(HttpRequests.class); |
| parsePath(postMethods, returnType, paths, ids, |
| HttpRequests.POST, controller ); |
| parsePath(putMethods, returnType, paths, ids, |
| HttpRequests.PUT, controller ); |
| parsePath(deleteMethods, returnType, paths, ids, |
| HttpRequests.DELETE, controller ); |
| generate( (TypeElement)returnElement , path , |
| collectionPath, paths, ids, controller ); |
| } |
| } |
| } |
| |
| private String parseNoIdPath( List<ExecutableElement> methods , |
| TypeMirror type , CompilationController controller) |
| { |
| for (ExecutableElement method : methods) { |
| List<? extends VariableElement> parameters = method.getParameters(); |
| boolean matches = false; |
| if (parameters.isEmpty()) { |
| matches = true; |
| } |
| else if ( parameters.size() == 1){ |
| VariableElement param = parameters.get(0); |
| if ( controller.getTypes().isSameType(param.asType(),type)){ |
| matches = true; |
| } |
| } |
| else { |
| continue; |
| } |
| if ( matches ){ |
| AnnotationMirror annotation = getAnnotation(method, PATH); |
| if ( annotation == null ){ |
| return ""; // NOI18N |
| } |
| else { |
| return getValue(annotation); |
| } |
| } |
| } |
| return null; |
| } |
| |
| private void parsePath( List<ExecutableElement> methods , TypeMirror type , |
| EnumMap<HttpRequests, String> paths, |
| EnumMap<HttpRequests, Boolean> ids, HttpRequests request, |
| CompilationController controller) |
| { |
| for (ExecutableElement method : methods) { |
| List<? extends VariableElement> parameters = method.getParameters(); |
| boolean matches = false; |
| String pathParam = null; |
| if ( parameters.size() == 1){ |
| VariableElement param = parameters.get(0); |
| if ( controller.getTypes().isSameType(param.asType(),type)){ |
| matches = true; |
| } |
| else if ( getAnnotation(param, PATH_PARAM) != null ){ |
| pathParam = getValue(getAnnotation(param, PATH_PARAM)); |
| matches = true; |
| ids.put(request, Boolean.TRUE); |
| } |
| } |
| else if (parameters.size() == 2) { |
| VariableElement param1 = parameters.get(0); |
| VariableElement param2 = parameters.get(1); |
| if ( getAnnotation(param1, PATH_PARAM) != null ){ |
| pathParam = getValue(getAnnotation(param1, PATH_PARAM)); |
| if ( controller.getTypes().isSameType(param2.asType(),type)){ |
| matches = true; |
| } |
| } |
| else if ( controller.getTypes().isSameType(param1.asType(),type)){ |
| if ( getAnnotation(param2, PATH_PARAM) != null ){ |
| pathParam = getValue(getAnnotation(param2, PATH_PARAM)); |
| matches = true; |
| } |
| } |
| if ( matches ){ |
| ids.put(request, Boolean.TRUE); |
| } |
| } |
| else { |
| continue; |
| } |
| if ( matches ){ |
| AnnotationMirror annotation = getAnnotation(method, PATH); |
| if ( annotation == null ){ |
| paths.put(request, ""); // NOI18N |
| } |
| else { |
| String path = getValue(annotation); |
| if ( pathParam != null ){ |
| path = removeParamTemplate(path, pathParam); |
| } |
| paths.put(request,path); |
| } |
| break; |
| } |
| } |
| } |
| |
| private void generate( TypeElement entity, String path, |
| String collectionPath, Map<HttpRequests, String> httpPaths , |
| Map<HttpRequests, Boolean> useIds, |
| CompilationController controller ) throws IOException |
| { |
| isModelGenerated = true; |
| ModelGenerator generator = new ModelGenerator(myDescription, |
| myModels, myEntities, myUi); |
| generator.generateModel(entity, path, |
| collectionPath, httpPaths, useIds, controller); |
| generateRouter(entity, path, collectionPath, httpPaths, controller, |
| generator); |
| } |
| |
| private void generateRouter( TypeElement entity, String path, |
| String collectionPath, Map<HttpRequests, String> httpPaths, |
| CompilationController controller, ModelGenerator modelGenerator ) |
| { |
| if ( myModelsCount >0 ){ |
| myRouters.append("/*"); // NOI18N |
| } |
| String name = "AppRouter"; // NOI18N |
| if ( myModelsCount >0 ){ |
| name += myModelsCount; |
| } |
| RouterGenerator generator = new RouterGenerator(myRouters, name, |
| modelGenerator); |
| generator.generateRouter(entity, path, collectionPath, httpPaths,controller ); |
| |
| if ( myModelsCount == 0 ){ |
| // Create HTML "view" for header identifier |
| myHeader.append("<div id='"); // NOI18N |
| myHeader.append(generator.getHeaderId()); |
| myHeader.append("'></div>\n"); // NOI18N |
| |
| if ( generator.getSideBarId()!= null) { |
| // Create HTML "view" for sidebar identifier |
| generateCollection(generator); |
| } |
| |
| // Create HTML "view" for content identifier |
| generateContent(generator); |
| |
| if ( generator.getCreateTemplate()!= null){ |
| // Create HTML "view" for "create new item" template |
| myTmplCreate.append("<script type='text/template' id='"); // NOI18N |
| myTmplCreate.append(generator.getCreateTemplate()); |
| myTmplCreate.append("'>\n"); // NOI18N |
| myTmplCreate.append("<!--\n"); // NOI18N |
| myTmplCreate.append("\tPut your controls to create new entity here.\n\n");// NOI18N |
| myTmplCreate.append("\tClass 'new' is used to listen on events in JS code.\n");// NOI18N |
| myTmplCreate.append("-->\n"); // NOI18N |
| myTmplCreate.append("<button class='new'>Create</button>\n"); // NOI18N |
| myTmplCreate.append("</script>\n"); // NOI18N |
| } |
| |
| if ( generator.getListItemTemplate()!= null){ |
| // Create HTML "view" for list item |
| if ( generator.useUi() ){ |
| generateHeadTemplate(generator); |
| } |
| myTmplList.append("<script type='text/template' id='"); // NOI18N |
| myTmplList.append(generator.getListItemTemplate()); |
| myTmplList.append("'>\n"); // NOI18N |
| generateItemContent(generator); |
| myTmplList.append("</script>\n"); // NOI18N |
| } |
| |
| if ( generator.getDetailsTemplate()!= null){ |
| // Create HTML "view" for details of chosen item |
| myTmplDetails.append("<script type='text/template' id='"); // NOI18N |
| myTmplDetails.append(generator.getDetailsTemplate()); |
| myTmplDetails.append("'>\n"); // NOI18N |
| myTmplDetails.append("<div>\n"); // NOI18N |
| String idAttribute = null; |
| if ( generator.useUi()){ |
| myTmplDetails.append("<table>\n<tbody>\n"); // NOI18N |
| } |
| if ( modelGenerator.getIdAttribute()!= null ){ |
| idAttribute = modelGenerator.getIdAttribute().getName(); |
| if ( generator.useUi()){ |
| myTmplDetails.append("<tr><td>Id</td>\n<td>\n"); // NOI18N |
| } |
| else { |
| myTmplDetails.append("<label>Id:</label>\n"); // NOI18N |
| } |
| myTmplDetails.append("<input type='text' id='"); // NOI18N |
| myTmplDetails.append(idAttribute); |
| myTmplDetails.append("' name='id' value='<%= typeof("); // NOI18N |
| myTmplDetails.append(idAttribute); |
| myTmplDetails.append(")!== \"undefined\" ? "); // NOI18N |
| myTmplDetails.append(idAttribute); |
| myTmplDetails.append(" : \"\" %>' />\n"); // NOI18N |
| if ( generator.useUi()){ |
| myTmplDetails.append("</td>\n</tr>\n"); // NOI18N |
| } |
| } |
| String nameAttribute = modelGenerator.getDisplayNameAlias(); |
| if ( !generator.useUi()){ |
| if ( nameAttribute != null && !nameAttribute.equals( idAttribute )){ |
| myTmplDetails.append("<label>Name:</label>\n"); // NOI18N |
| myTmplDetails.append("<input type='text' id='"); // NOI18N |
| myTmplDetails.append(nameAttribute); |
| myTmplDetails.append("' name='"); // NOI18N |
| myTmplDetails.append(nameAttribute); |
| myTmplDetails.append("' value='<%= "); // NOI18N |
| myTmplDetails.append(nameAttribute); |
| myTmplDetails.append(" %>'/>\n"); // NOI18N |
| } |
| myTmplDetails.append("<!--\n"); // NOI18N |
| myTmplDetails.append("\tPut your editing controls for model\n"); // NOI18N |
| myTmplDetails.append("attribute data (text fields, ...) here\n"); // NOI18N |
| } |
| |
| Set<ModelAttribute> attributes = modelGenerator.getAttributes(); |
| for (ModelAttribute attribute : attributes) { |
| String attrName = attribute.getName(); |
| if ( !generator.useUi() && attrName.equals( nameAttribute)|| |
| attrName.equals(idAttribute)) |
| { |
| continue; |
| } |
| if ( generator.useUi() ){ |
| myTmplDetails.append("<tr>\n<td>"); // NOI18N |
| } |
| else { |
| myTmplDetails.append("<label>"); // NOI18N |
| } |
| myTmplDetails.append(attrName); |
| if ( generator.useUi() ){ |
| myTmplDetails.append("</td><td>"); // NOI18N |
| } |
| else { |
| myTmplDetails.append(":</label>\n"); // NOI18N |
| } |
| myTmplDetails.append("<input type='text' id='"); // NOI18N |
| myTmplDetails.append(attrName); |
| myTmplDetails.append("' name='"); // NOI18N |
| myTmplDetails.append(attrName); |
| myTmplDetails.append("' value='<%= "); // NOI18N |
| myTmplDetails.append(attrName); |
| myTmplDetails.append(" %>'/>"); // NOI18N |
| if ( generator.useUi() ){ |
| myTmplDetails.append("</td></tr>\n"); // NOI18N |
| } |
| } |
| if ( generator.useUi()){ |
| myTmplDetails.append("</tbody>\n</table>\n"); // NOI18N |
| } |
| else { |
| myTmplDetails.append("-->\n"); // NOI18N |
| } |
| myTmplDetails.append("<!--\n"); |
| myTmplDetails.append("\tPut your controls to create new entity here.\n");// NOI18N |
| myTmplDetails.append("\tClasses 'save' and 'delete' are used "); // NOI18N |
| myTmplDetails.append("to listen on events in JS code.\n"); // NOI18N |
| myTmplDetails.append("-->\n"); // NOI18N |
| myTmplDetails.append("<button class='save'>Save</button>\n"); // NOI18N |
| myTmplDetails.append("<button class='delete'>Delete</button>\n"); // NOI18N |
| myTmplDetails.append("</div>\n"); // NOI18N |
| myTmplDetails.append("</script>\n"); // NOI18N |
| } |
| } |
| else { |
| myRouters.append("*/"); // NOI18N |
| } |
| myModelsCount++; |
| } |
| |
| private void generateHeadTemplate( RouterGenerator generator ) { |
| myTmplList.append("<script type='text/template' id='"); // NOI18N |
| myTmplList.append(generator.getTableHeadId()); |
| myTmplList.append("'>\n<thead>\n<tr>\n"); // NOI18N |
| |
| if (generator.getModelGenerator().getIdAttribute() != null) { |
| String id = generator.getModelGenerator().getIdAttribute() |
| .getName(); |
| myTmplList.append("<th>"); // NOI18N |
| myTmplList.append(id); |
| myTmplList.append("</th>\n"); // NOI18N |
| } |
| Set<ModelAttribute> attributes = generator.getModelGenerator() |
| .getAttributes(); |
| for (ModelAttribute attribute : attributes) { |
| myTmplList.append("<th>"); // NOI18N |
| myTmplList.append(attribute.getName()); |
| myTmplList.append("</th>\n"); // NOI18N |
| } |
| |
| myTmplList.append("</tr>\n</thead>\n</script>\n"); // NOI18N |
| } |
| |
| private void generateItemContent( RouterGenerator generator ) { |
| if ( generator.useUi()){ |
| if ( generator.getModelGenerator().getIdAttribute() != null ){ |
| String id = generator.getModelGenerator().getIdAttribute().getName(); |
| myTmplList.append("<td><a href='#<%= "); // NOI18N |
| myTmplList.append(id); |
| myTmplList.append(" %>'><%= "); // NOI18N |
| myTmplList.append(id); |
| myTmplList.append(" %></a></td>\n"); // NOI18N |
| } |
| Set<ModelAttribute> attributes = generator.getModelGenerator().getAttributes(); |
| for( ModelAttribute attribute : attributes ){ |
| myTmplList.append("<td><%= "); // NOI18N |
| myTmplList.append(attribute.getName()); |
| myTmplList.append(" %></td>\n"); // NOI18N |
| } |
| } |
| else { |
| myTmplList.append("<!-- modify output display name for item here"); // NOI18N |
| myTmplList.append(" or change displayName in the JS model code -->\n"); // NOI18N |
| if (generator.getModelGenerator().getIdAttribute()!= null){ |
| myTmplList.append("<a href='#<%= "); // NOI18N |
| myTmplList.append(generator.getModelGenerator().getIdAttribute().getName()); |
| myTmplList.append(" %>'><%= displayName %></a>\n"); // NOI18N |
| } |
| else { |
| myTmplList.append("<%= displayName %>\n"); // NOI18N |
| } |
| } |
| } |
| |
| private void generateCollection( RouterGenerator generator ) { |
| if ( generator.useUi()){ |
| hasUi = true; |
| mySidebar.append("<table id='"); // NOI18N |
| mySidebar.append(generator.getSideBarId()); |
| mySidebar.append("' class='tablesorter-blue'>\n</table>\n"); // NOI18N |
| mySidebar.append("<div class='pager' id='pager'>\n"); // NOI18N |
| mySidebar.append("<img src='"); // NOI18N |
| mySidebar.append(TABLESORTER_URL); |
| mySidebar.append("addons/pager/icons/first.png' class='first' ");// NOI18N |
| mySidebar.append("alt='First'/>\n"); // NOI18N |
| mySidebar.append("<img src='"); // NOI18N |
| mySidebar.append(TABLESORTER_URL); |
| mySidebar.append("addons/pager/icons/prev.png' class='prev' "); // NOI18N |
| mySidebar.append("alt='Prev'/>\n"); // NOI18N |
| mySidebar.append("<span class='pagedisplay'></span>"); // NOI18N |
| mySidebar.append(" <!-- this can be any element, including an input -->\n");// NOI18N |
| mySidebar.append("<img src='"); // NOI18N |
| mySidebar.append(TABLESORTER_URL); |
| mySidebar.append("addons/pager/icons/next.png' class='next' "); // NOI18N |
| mySidebar.append("alt='Next'/>\n"); // NOI18N |
| mySidebar.append("<img src='"); // NOI18N |
| mySidebar.append(TABLESORTER_URL); |
| mySidebar.append("addons/pager/icons/last.png' class='last' "); // NOI18N |
| mySidebar.append("alt='Last'/>\n"); // NOI18N |
| mySidebar.append("<select class='pagesize'>\n"); // NOI18N |
| mySidebar.append("<option selected='selected' value='10'>"); // NOI18N |
| mySidebar.append("10</option>\n"); // NOI18N |
| mySidebar.append("<option value='20'>20</option>\n"); // NOI18N |
| mySidebar.append("<option value='30'>30</option>\n"); // NOI18N |
| mySidebar.append("<option value='40'>40</option>\n"); // NOI18N |
| mySidebar.append("</select>\n</div>\n<br>\n"); // NOI18N |
| } |
| else { |
| mySidebar.append("<div id='"); // NOI18N |
| mySidebar.append(generator.getSideBarId()); |
| mySidebar.append("'></div>\n"); // NOI18N |
| } |
| } |
| |
| private void generateContent( RouterGenerator generator ) { |
| myContent.append("<div id='"); // NOI18N |
| myContent.append(generator.getContentId()); |
| myContent.append("'></div>\n"); // NOI18N |
| } |
| |
| private String removeParamTemplate( String path, String param ) { |
| int index = path.indexOf('{'); |
| String template; |
| if ( index == -1 ){ |
| return path; |
| } |
| else { |
| template = path.substring(index+1).trim(); |
| int lastIndex = template.lastIndexOf('}'); |
| if ( lastIndex == -1 ){ |
| return path; |
| } |
| template = template.substring( 0, lastIndex ).trim(); |
| } |
| if ( !template.startsWith(param) ){ |
| return path; |
| } |
| template = template.substring(param.length()).trim(); |
| if ( template.length() == 0 || template.charAt(0)==':'){ |
| return path.substring( 0, index ); |
| } |
| return path; |
| } |
| |
| private TypeMirror getCollectionType (TypeMirror type , |
| CompilationController controller) |
| { |
| TypeElement collectionElement = controller.getElements().getTypeElement( |
| Collection.class.getName()); |
| TypeMirror collectionType = controller.getTypes().erasure( |
| collectionElement.asType()); |
| TypeMirror erasure = controller.getTypes().erasure(type); |
| if (!controller.getTypes().isSubtype(erasure, collectionType)) { |
| return null; |
| } |
| List<? extends TypeMirror> supers = controller.getTypes().directSupertypes( type ); |
| for (TypeMirror superType : supers) { |
| erasure = controller.getTypes().erasure(superType); |
| if ( controller.getTypes().isSameType(erasure, collectionType)){ |
| return getParameterType( superType); |
| } |
| TypeMirror found = getCollectionType(superType, controller); |
| if ( found != null ){ |
| return found; |
| } |
| } |
| return null; |
| } |
| |
| private TypeMirror getParameterType( TypeMirror type ){ |
| if ( type instanceof DeclaredType ){ |
| List<? extends TypeMirror> typeArguments = ((DeclaredType)type).getTypeArguments(); |
| if (typeArguments.isEmpty()) { |
| return null; |
| } |
| return typeArguments.get(0); |
| } |
| return null; |
| } |
| |
| private String getValue( AnnotationMirror annotation ){ |
| if ( annotation == null ){ |
| return null; |
| } |
| Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = |
| annotation.getElementValues(); |
| for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : |
| elementValues.entrySet()) |
| { |
| ExecutableElement annotationMethod = entry.getKey(); |
| AnnotationValue value = entry.getValue(); |
| if (annotationMethod.getSimpleName().contentEquals("value")) { // NOI18N |
| Object val = value.getValue(); |
| if ( val != null ){ |
| return val.toString(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| private boolean hasJsonMedia( List<? extends AnnotationMirror> annotations) { |
| AnnotationMirror consumes = getAnnotation(annotations, CONSUMES); |
| AnnotationMirror produces = getAnnotation(annotations, PRODUCES); |
| AnnotationMirror mimeTypeDecl = consumes==null ? produces: consumes; |
| if ( mimeTypeDecl == null ){ |
| return false; |
| } |
| Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = |
| mimeTypeDecl.getElementValues(); |
| for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : |
| elementValues.entrySet()) |
| { |
| ExecutableElement annotationMethod = entry.getKey(); |
| AnnotationValue value = entry.getValue(); |
| if ( annotationMethod.getSimpleName().contentEquals("value")){ // NOI18N |
| Object mediaType = value.getValue(); |
| if ( mediaType instanceof List<?>){ |
| List<?> types = (List<?>)mediaType; |
| for (Object type : types) { |
| if ( type instanceof AnnotationValue ){ |
| mediaType = ((AnnotationValue)type).getValue(); |
| if ( JSON.equals( mediaType )){ |
| return true; |
| } |
| } |
| } |
| } |
| else if ( JSON.equals( mediaType )){ |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| static AnnotationMirror getAnnotation( List<? extends AnnotationMirror> annotations, |
| String annotation ) |
| { |
| for (AnnotationMirror annotationMirror : annotations) { |
| Element annotationElement = annotationMirror.getAnnotationType().asElement(); |
| if ( annotationElement instanceof TypeElement){ |
| TypeElement annotationDecl = (TypeElement) annotationElement; |
| if ( annotationDecl.getQualifiedName().contentEquals( annotation)){ |
| return annotationMirror; |
| } |
| } |
| } |
| return null; |
| } |
| |
| static AnnotationMirror getAnnotation( Element element, String annotation ) |
| { |
| List<? extends AnnotationMirror> annotations = element.getAnnotationMirrors(); |
| return getAnnotation(annotations, annotation); |
| } |
| |
| private final RestServiceDescription myDescription; |
| private final JsUi myUi; |
| private StringBuilder myModels; |
| private StringBuilder myRouters; |
| private StringBuilder myHeader; |
| private StringBuilder myContent; |
| private StringBuilder mySidebar; |
| private StringBuilder myTmplCreate; |
| private StringBuilder myTmplList; |
| private StringBuilder myTmplDetails; |
| private final Set<String> myEntities = new HashSet<String>(); |
| private boolean isModelGenerated; |
| private int myModelsCount; |
| private boolean hasUi; |
| |
| } |