/* * Copyright 2013 cruxframework.org. * * 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 org.cruxframework.crux.core.rebind.database.sql; import java.io.PrintWriter; import java.util.HashSet; import java.util.Set; import org.cruxframework.crux.core.client.collection.Array; import org.cruxframework.crux.core.client.db.DatabaseCallback; import org.cruxframework.crux.core.client.db.DatabaseErrorHandler; import org.cruxframework.crux.core.client.db.WSQLAbstractDatabase; import org.cruxframework.crux.core.client.db.WSQLAbstractObjectStore; import org.cruxframework.crux.core.client.db.WSQLTransaction; import org.cruxframework.crux.core.client.db.annotation.DatabaseDef.ObjectStoreDef; import org.cruxframework.crux.core.client.db.websql.SQLTransaction; import org.cruxframework.crux.core.client.utils.EscapeUtils; import org.cruxframework.crux.core.client.utils.StringUtils; import org.cruxframework.crux.core.rebind.CruxGeneratorException; import org.cruxframework.crux.core.rebind.context.RebindContext; import org.cruxframework.crux.core.rebind.database.AbstractDatabaseProxyCreator; import com.google.gwt.core.client.GWT; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JPackage; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; /** * This class creates a client proxy for access a database * * @author Thiago da Rosa de Bustamante * */ public class SQLDatabaseProxyCreator extends AbstractDatabaseProxyCreator { public SQLDatabaseProxyCreator(RebindContext context, JClassType baseIntf) { super(context, baseIntf); } @Override protected void generateProxyMethods(SourcePrinter srcWriter) { generateUpdateDatabaseStructureMethod(srcWriter); generateGetObjectStoreMethod(srcWriter); } protected void generateUpdateDatabaseStructureMethod(SourcePrinter srcWriter) { srcWriter.println("protected void updateDatabaseStructure(final "+SQLTransaction.class.getCanonicalName()+" tx, final DatabaseCallback callback){"); generateObjectStoresCreation(srcWriter, "callback"); srcWriter.println("}"); srcWriter.println(); } protected void generateObjectStoresCreation(SourcePrinter srcWriter, String callback) { srcWriter.println("deleteDBTables(tx, new DatabaseCallback(){"); srcWriter.println("public void onSuccess(){"); ObjectStoreDef[] objectStores = databaseMetadata.objectStores(); Set<String> addedObjectStores = new HashSet<String>(); String objectStoreVar = "objectStore"; String indexNamesVar = "indexNames"; srcWriter.println("WSQLAbstractObjectStore "+objectStoreVar+";"); srcWriter.println("Array<String> "+indexNamesVar+";"); for (ObjectStoreDef objectStoreMetadata : objectStores) { JClassType objectStoreTarget = getObjectStoreTarget(objectStoreMetadata); String objectStoreName = getObjectStoreName(objectStoreMetadata, objectStoreTarget); if (addedObjectStores.contains(objectStoreName)) { throw new CruxGeneratorException("Duplicated objectstore declared on Datasource ["+databaseMetadata.name()+"]"); } addedObjectStores.add(objectStoreName); srcWriter.println(objectStoreVar +" = getObjectStore("+EscapeUtils.quote(objectStoreName)+", null);"); srcWriter.println(objectStoreVar+".createTable(tx, null);"); } srcWriter.println("createFileStore(tx);"); srcWriter.println("}"); srcWriter.println("}, getDeleteErrorHandler(callback), false);"); } protected void generateGetObjectStoreMethod(SourcePrinter srcWriter) { srcWriter.println("protected <K, V> WSQLAbstractObjectStore<K, V> getObjectStore(String storeName, WSQLTransaction transaction){"); boolean first = true; ObjectStoreDef[] objectStores = databaseMetadata.objectStores(); for (ObjectStoreDef objectStoreMetadata : objectStores) { JClassType objectStoreTarget = getObjectStoreTarget(objectStoreMetadata); String objectStoreName = getObjectStoreName(objectStoreMetadata, objectStoreTarget); if (!first) { srcWriter.print("else "); } first = false; Set<IndexData> indexes = getIndexes(objectStoreMetadata.indexes(), objectStoreTarget, objectStoreName); srcWriter.println("if (StringUtils.unsafeEquals(storeName, "+EscapeUtils.quote(objectStoreName)+")){"); String[] keyPath = getKeyPath(objectStoreMetadata, objectStoreTarget); String objectStore = new SQLObjectStoreProxyCreator(context, objectStoreTarget, objectStoreName, keyPath, isAutoIncrement(objectStoreTarget), indexes).create(); srcWriter.println("return (WSQLAbstractObjectStore<K, V>) new "+objectStore+"(this, storeName, transaction);"); srcWriter.println("}"); } srcWriter.println("return null;"); srcWriter.println("}"); srcWriter.println(); } @Override protected String[] getImports() { return new String[]{ DatabaseCallback.class.getCanonicalName(), WSQLAbstractObjectStore.class.getCanonicalName(), WSQLTransaction.class.getCanonicalName(), DatabaseErrorHandler.class.getCanonicalName(), Array.class.getCanonicalName(), StringUtils.class.getCanonicalName(), GWT.class.getCanonicalName() }; } /** * @return the simple name of the proxy object. */ @Override public String getProxySimpleName() { JClassType enclosingType = baseIntf.getEnclosingType(); String enclosingTypeName = (enclosingType==null?"":enclosingType.getSimpleSourceName()+"_"); return enclosingTypeName+baseIntf.getSimpleSourceName() + "_SQL_Impl"; } /** * @return a sourceWriter for the proxy class */ @Override protected SourcePrinter getSourcePrinter() { JPackage pkg = baseIntf.getPackage(); String packageName = pkg == null ? "" : pkg.getName(); PrintWriter printWriter = context.getGeneratorContext().tryCreate(context.getLogger(), packageName, getProxySimpleName()); if (printWriter == null) { return null; } ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, getProxySimpleName()); String[] imports = getImports(); for (String imp : imports) { composerFactory.addImport(imp); } composerFactory.setSuperclass(WSQLAbstractDatabase.class.getCanonicalName()); composerFactory.addImplementedInterface(baseIntf.getQualifiedSourceName()); return new SourceCodePrinter(composerFactory.createSourceWriter(context.getGeneratorContext(), printWriter), context.getLogger()); } }