blob: ec6405eeb14d244c978417e4adf4ff22ab143316 [file] [log] [blame]
/*
* 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;
}