/* * Copyright (C) 2012 The Android Open Source Project * * Licensed 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 com.motorola.studio.android.model.java; import org.eclipse.core.runtime.Assert; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.BodyDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ImportDeclaration; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.PrimitiveType; import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.jdt.core.dom.Type; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jface.text.BadLocationException; import org.eclipse.osgi.util.NLS; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.TextEdit; import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS; import com.motorola.studio.android.common.exception.AndroidException; import com.motorola.studio.android.common.log.StudioLogger; /** * Class used to create an Android Content Provider building block class */ public class ContentProviderClass extends JavaClass { private static final String CP_SUPERCLASS = "android.content.ContentProvider"; private static final String[] URI_CLASS = getFQNAsArray("android.net.Uri"); private static final String[] CONTENTVALUES_CLASS = getFQNAsArray("android.content.ContentValues"); private static final String[] CURSOR_CLASS = getFQNAsArray("android.database.Cursor"); private static final String DELETE_METHOD_NAME = "delete"; private static final String GETTYPE_METHOD_NAME = "getType"; private static final String INSERT_METHOD_NAME = "insert"; private static final String ONCREATE_METHOD_NAME = "onCreate"; private static final String QUERY_METHOD_NAME = "query"; private static final String UPDATE_METHOD_NAME = "update"; private static final String CONTENT_SCHEME = "content://"; private static final String CONTENT_URI_NAME = "CONTENT_URI"; private ASTRewrite rewrite; private String authority; /** * Default constructor * * @param className The simple class name * @param packageName The full-qualified class package name */ public ContentProviderClass(String className, String packageName, String authority) { super(className, packageName, CP_SUPERCLASS); Assert.isNotNull(authority); this.authority = authority; addBasicCPInfo(); } /** * Adds basic information to the content provider class */ @SuppressWarnings("unchecked") private void addBasicCPInfo() { ImportDeclaration importDecl; // Adds import for Uri importDecl = ast.newImportDeclaration(); importDecl.setName(ast.newName(URI_CLASS)); compUnit.imports().add(importDecl); // Adds import for ContentValues importDecl = ast.newImportDeclaration(); importDecl.setName(ast.newName(CONTENTVALUES_CLASS)); compUnit.imports().add(importDecl); // Adds import for Cursor importDecl = ast.newImportDeclaration(); importDecl.setName(ast.newName(CURSOR_CLASS)); compUnit.imports().add(importDecl); // Adds the authorities constants addAuthority(); // Adds the delete method addDeleteMethod(); // Adds the getType method addGetTypeMethod(); // Adds the insert method addInsertMethod(); // Adds the onCreate method addOnCreateMethod(); // Adds the query method addQueryMethod(); // Adds the update method addUpdateMethod(); // Adds JavaDoc to elements addComment(classDecl, CodeUtilsNLS.MODEL_ContentProviderClass_ContentProviderDescription); } /** * Adds the default content provider Uri */ @SuppressWarnings("unchecked") private void addAuthority() { final String URI_PARSE_METHOD = "parse"; String contentUriValue = CONTENT_SCHEME + authority; StringLiteral stringLiteral = ast.newStringLiteral(); stringLiteral.setLiteralValue(contentUriValue); Name uri = ast.newSimpleName(getName(URI_CLASS)); MethodInvocation parse = ast.newMethodInvocation(); parse.setExpression(uri); parse.setName(ast.newSimpleName(URI_PARSE_METHOD)); parse.arguments().add(stringLiteral); VariableDeclarationFragment contentUri = ast.newVariableDeclarationFragment(); contentUri.setName(ast.newSimpleName(CONTENT_URI_NAME)); contentUri.setInitializer(parse); FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(contentUri); fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD)); fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD)); fieldDeclaration.setType(uriType()); classDecl.bodyDeclarations().add(fieldDeclaration); addComment(fieldDeclaration, CodeUtilsNLS.MODEL_ContentProviderClass_ContentUriDescription); } /** * Adds the delete method to the content provider class */ @SuppressWarnings("unchecked") private void addDeleteMethod() { final String SELECTION_PARAM = "selection"; final String SELECTION_ARGS_PARAM = "selectionArgs"; MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(ast.newPrimitiveType(PrimitiveType.INT)); method.setName(ast.newSimpleName(DELETE_METHOD_NAME)); addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType()); addMethodParameter(method, SELECTION_PARAM, stringType()); addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType()); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_DeleteMethodDescription); addMethodReference(method, CP_SUPERCLASS, DELETE_METHOD_NAME, new Type[] { uriType(), stringType(), stringArrayType() }); } /** * Adds the getType method to the content provider class */ @SuppressWarnings("unchecked") private void addGetTypeMethod() { MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(stringType()); method.setName(ast.newSimpleName(GETTYPE_METHOD_NAME)); addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType()); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_GetTypeMethodDescription); addMethodReference(method, CP_SUPERCLASS, GETTYPE_METHOD_NAME, new Type[] { uriType() }); } /** * Adds the insert method to the content provider class */ @SuppressWarnings("unchecked") private void addInsertMethod() { final String VALUES_PARAM = "values"; MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(uriType()); method.setName(ast.newSimpleName(INSERT_METHOD_NAME)); addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType()); addMethodParameter(method, VALUES_PARAM, contentValuesType()); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_InsertMethodDescription); addMethodReference(method, CP_SUPERCLASS, INSERT_METHOD_NAME, new Type[] { uriType(), contentValuesType() }); } /** * Adds the onCreate method to the content provider class */ @SuppressWarnings("unchecked") private void addOnCreateMethod() { MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(ast.newPrimitiveType(PrimitiveType.BOOLEAN)); method.setName(ast.newSimpleName(ONCREATE_METHOD_NAME)); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_OnCreateMethodDescription); addMethodReference(method, CP_SUPERCLASS, ONCREATE_METHOD_NAME, null); } /** * Adds the query method to the content provider class */ @SuppressWarnings("unchecked") private void addQueryMethod() { final String PROJECTION_PARAM = "projection"; final String SELECTION_PARAM = "selection"; final String SELECTION_ARGS_PARAM = "selectionArgs"; final String SORT_ORDER_PARAM = "sortOrder"; MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(cursorType()); method.setName(ast.newSimpleName(QUERY_METHOD_NAME)); addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType()); addMethodParameter(method, PROJECTION_PARAM, stringArrayType()); addMethodParameter(method, SELECTION_PARAM, stringType()); addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType()); addMethodParameter(method, SORT_ORDER_PARAM, stringType()); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_QueryMethodDescription); addMethodReference(method, CP_SUPERCLASS, QUERY_METHOD_NAME, new Type[] { uriType(), stringArrayType(), stringType(), stringArrayType(), stringType() }); } /** * Adds the update method to the content provider class */ @SuppressWarnings("unchecked") private void addUpdateMethod() { final String VALUES_PARAM = "values"; final String SELECTION_PARAM = "selection"; final String SELECTION_ARGS_PARAM = "selectionArgs"; MethodDeclaration method = ast.newMethodDeclaration(); method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD)); method.setReturnType2(ast.newPrimitiveType(PrimitiveType.INT)); method.setName(ast.newSimpleName(UPDATE_METHOD_NAME)); addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType()); addMethodParameter(method, VALUES_PARAM, contentValuesType()); addMethodParameter(method, SELECTION_PARAM, stringType()); addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType()); addEmptyBlock(method); classDecl.bodyDeclarations().add(method); addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_UpdateMethodDescription); addMethodReference(method, CP_SUPERCLASS, UPDATE_METHOD_NAME, new Type[] { uriType(), contentValuesType(), stringType(), stringArrayType() }); } /* (non-Javadoc) * @see com.motorola.studio.android.model.java.JavaClass#addComments() */ @Override protected void addComments() throws AndroidException { ASTNode todoComment; ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setSource(document.get().toCharArray()); compUnit = (CompilationUnit) parser.createAST(null); ast = compUnit.getAST(); rewrite = ASTRewrite.create(ast); todoComment = rewrite.createStringPlaceholder(CodeUtilsNLS.MODEL_Common_ToDoPutYourCodeHere, ASTNode.EMPTY_STATEMENT); TypeDeclaration cpClass = (TypeDeclaration) compUnit.types().get(0); MethodDeclaration method; Block block; // Adds the Override annotation and ToDo comment to all abstract methods for (int i = 0; i < cpClass.bodyDeclarations().size(); i++) { BodyDeclaration bodyDecl = (BodyDeclaration) cpClass.bodyDeclarations().get(i); if (bodyDecl instanceof MethodDeclaration) { method = (MethodDeclaration) bodyDecl; // Adds the Override annotation rewrite.getListRewrite(method, method.getModifiersProperty()).insertFirst( OVERRIDE_ANNOTATION, null); // Adds the ToDo comment block = method.getBody(); rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertFirst(todoComment, null); } } try { // Writes the modifications TextEdit modifications = rewrite.rewriteAST(document, null); modifications.apply(document); } catch (IllegalArgumentException e) { String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className); StudioLogger.error(ContentProviderClass.class, errMsg, e); throw new AndroidException(errMsg); } catch (MalformedTreeException e) { String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className); StudioLogger.error(ContentProviderClass.class, errMsg, e); throw new AndroidException(errMsg); } catch (BadLocationException e) { String errMsg = NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className); StudioLogger.error(ContentProviderClass.class, errMsg, e); throw new AndroidException(errMsg); } } /** * Returns a new Uri type * * @return a new Uri type */ private Type uriType() { return ast.newSimpleType(ast.newSimpleName(getName(URI_CLASS))); } /** * Returns a new ContentValues type * * @return a new ContentValues type */ private Type contentValuesType() { return ast.newSimpleType(ast.newSimpleName(getName(CONTENTVALUES_CLASS))); } /** * Returns a new Cursor type * * @return a new Cursor type */ private Type cursorType() { return ast.newSimpleType(ast.newSimpleName(getName(CURSOR_CLASS))); } }