/*
* 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.Date;
import java.util.Set;
import org.cruxframework.crux.core.client.collection.Array;
import org.cruxframework.crux.core.client.db.Cursor.CursorDirection;
import org.cruxframework.crux.core.client.db.WSQLAbstractDatabase;
import org.cruxframework.crux.core.client.db.WSQLCursor;
import org.cruxframework.crux.core.client.db.WSQLKeyRange;
import org.cruxframework.crux.core.client.db.WSQLTransaction;
import org.cruxframework.crux.core.client.utils.EscapeUtils;
import org.cruxframework.crux.core.client.utils.JsUtils;
import org.cruxframework.crux.core.rebind.CruxGeneratorException;
import org.cruxframework.crux.core.rebind.context.RebindContext;
import org.cruxframework.crux.core.utils.JClassUtils;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayMixed;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class SQLCursorProxyCreator extends SQLAbstractKeyValueProxyCreator
{
protected JClassType cursorType;
protected final String cursorName;
protected final String[] objectStoreKeyPath;
protected final Set<String> objectStoreIndexColumns;
protected final boolean autoIncrement;
public SQLCursorProxyCreator(RebindContext context, JClassType targetObjectType, String objectStoreName,
boolean autoIncrement, Set<String> objectStoreIndexColumns, String[] keyPath, String[] objectStoreKeyPath,
String cursorName)
{
super(context, targetObjectType, objectStoreName, keyPath);
this.autoIncrement = autoIncrement;
this.objectStoreIndexColumns = objectStoreIndexColumns;
this.objectStoreKeyPath = objectStoreKeyPath;
this.cursorName = cursorName;
this.cursorType = context.getGeneratorContext().getTypeOracle().findType(WSQLCursor.class.getCanonicalName());
}
@Override
protected void generateProxyContructor(SourcePrinter srcWriter) throws CruxGeneratorException
{
srcWriter.println("public "+getProxySimpleName()+"(WSQLAbstractDatabase db, WSQLKeyRange<"+getKeyTypeName()+"> range, CursorDirection direction, WSQLTransaction transaction){");
srcWriter.println("super(db, range, "+EscapeUtils.quote(objectStoreName)+", "+autoIncrement+", direction, transaction);");
srcWriter.println("}");
}
@Override
protected void generateProxyMethods(SourcePrinter srcWriter) throws CruxGeneratorException
{
generateGetNativeKeyMethod(srcWriter);
generateGetKeyMethod(srcWriter);
generateGetPrimaryKeyMethod(srcWriter);
if (hasCompositeKey())
{
generateFromNativeValueMethod(srcWriter, keyPath);
}
generateGetIndexedColumnNamesMethod(srcWriter, objectStoreIndexColumns);
generateGetKeyPathMethod(srcWriter);
generateAddKeyRangeToQueryMethod(srcWriter);
generateAddKeyToQueryMethod(srcWriter);
generateAddPrimaryKeyToQueryMethod(srcWriter);
generateDecodeObjectMethod(srcWriter);
generateEncodeObjectMethod(srcWriter);
generateSetObjectKeyMethod(srcWriter);
}
protected void generateSetObjectKeyMethod(SourcePrinter srcWriter)
{
srcWriter.println("protected void setObjectKey("+getTargetObjectClassName()+" object, "+getKeyTypeName(objectStoreKeyPath)+" key){");
if (objectStoreKeyPath.length > 1)
{
for (int i = 0; i < objectStoreKeyPath.length; i++)
{
String k = objectStoreKeyPath[i];
JType jType = JClassUtils.getTypeForProperty(k, targetObjectType);
String setterMethod = JClassUtils.getSetterMethod(k, targetObjectType, jType);
srcWriter.println("object."+setterMethod+"((key==null?null:("+jType.getParameterizedQualifiedSourceName()+")key["+i+"]));");
}
}
else
{
String k = objectStoreKeyPath[0];
JType jType = JClassUtils.getTypeForProperty(k, targetObjectType);
String setterMethod = JClassUtils.getSetterMethod(k, targetObjectType, jType);
srcWriter.println("object."+setterMethod+"(key);");
}
srcWriter.println("}");
srcWriter.println();
}
protected void generateAddPrimaryKeyToQueryMethod(SourcePrinter srcWriter)
{
generateGetNativeKeyMethod(srcWriter, objectStoreKeyPath, "getNativePrimaryKey");
srcWriter.println("protected void addPrimaryKeyToQuery(final "+getKeyTypeName(objectStoreKeyPath)+" key, "+
StringBuilder.class.getCanonicalName()+" sql, "+JsArrayMixed.class.getCanonicalName()+" args){");
boolean first = true;
for(String path: objectStoreKeyPath)
{
if (!first)
{
srcWriter.print("sql.append(\" AND \");");
}
srcWriter.println("sql.append(\""+path+" = ?\");");
first = false;
}
srcWriter.println("getNativePrimaryKey(key, args);");
srcWriter.println("}");
srcWriter.println();
}
protected void generateGetKeyMethod(SourcePrinter srcWriter)
{
String keyTypeName = getKeyTypeName();
srcWriter.println("public "+keyTypeName+" getKey(){");
srcWriter.println("if (offset >= length) return null;");
srcWriter.println(JavaScriptObject.class.getCanonicalName()+" object = resultSet.getRows().itemObject(offset);");
if (hasCompositeKey())
{
srcWriter.println(JsArrayMixed.class.getCanonicalName() + " k = "+JsArrayMixed.class.getCanonicalName()+".createArray().cast(); ");
for(String key: keyPath)
{
srcWriter.println(JsUtils.class.getCanonicalName()+".readPropertyValue(object, "+EscapeUtils.quote(key)+", k, true);");
}
srcWriter.println("return fromNativeValue(k);");
}
else if (keyTypeName.equals("String"))
{
srcWriter.println("return "+JsUtils.class.getCanonicalName()+".readStringPropertyValue(object, "+EscapeUtils.quote(keyPath[0])+");");
}
else if (keyTypeName.equals("Integer"))
{
srcWriter.println("return ("+JsUtils.class.getCanonicalName()+".hasPropertyValue(object, "+EscapeUtils.quote(keyPath[0])+")?"+JsUtils.class.getCanonicalName()+".readIntPropertyValue(object, "+EscapeUtils.quote(keyPath[0])+"):null);");
}
else if (keyTypeName.equals("Double"))
{
srcWriter.println("return "+JsUtils.class.getCanonicalName()+".readDoublePropertyValue(object, "+EscapeUtils.quote(keyPath[0])+");");
}
else if (keyTypeName.equals(Date.class.getCanonicalName()))
{
srcWriter.println("return new "+Date.class.getCanonicalName()+"((long)"+JsUtils.class.getCanonicalName()+".readDoublePropertyValue(object, "+EscapeUtils.quote(keyPath[0])+"));");
}
else
{
srcWriter.println("return object.cast();");
}
srcWriter.println("}");
}
protected void generateGetPrimaryKeyMethod(SourcePrinter srcWriter)
{
String keyTypeName = getKeyTypeName(objectStoreKeyPath);
srcWriter.println("public "+keyTypeName+" getPrimaryKey(){");
srcWriter.println("if (offset >= length) return null;");
srcWriter.println(JavaScriptObject.class.getCanonicalName()+" object = resultSet.getRows().itemObject(offset);");
if (objectStoreKeyPath.length > 1 && !isEmptyType())
{
srcWriter.println(JsArrayMixed.class.getCanonicalName() + " k = "+JsArrayMixed.class.getCanonicalName()+".createArray().cast(); ");
for(String key: objectStoreKeyPath)
{
srcWriter.println(JsUtils.class.getCanonicalName()+".readPropertyValue(object, "+EscapeUtils.quote(key)+", k, true);");
}
srcWriter.println("return fromNativeKey(k);");
}
else if (keyTypeName.equals("String"))
{
srcWriter.println("return "+JsUtils.class.getCanonicalName()+".readStringPropertyValue(object, "+EscapeUtils.quote(objectStoreKeyPath[0])+");");
}
else if (keyTypeName.equals("Integer"))
{
srcWriter.println("return ("+JsUtils.class.getCanonicalName()+".hasPropertyValue(object, "+EscapeUtils.quote(objectStoreKeyPath[0])+")?"+JsUtils.class.getCanonicalName()+".readIntPropertyValue(object, "+EscapeUtils.quote(objectStoreKeyPath[0])+"):null);");
}
else if (keyTypeName.equals("Double"))
{
srcWriter.println("return "+JsUtils.class.getCanonicalName()+".readDoublePropertyValue(object, "+EscapeUtils.quote(objectStoreKeyPath[0])+");");
}
else if (keyTypeName.equals(Date.class.getCanonicalName()))
{
srcWriter.println("return new "+Date.class.getCanonicalName()+"((long)"+JsUtils.class.getCanonicalName()+".readDoublePropertyValue(object, "+EscapeUtils.quote(objectStoreKeyPath[0])+"));");
}
else
{
srcWriter.println("return object.cast();");
}
srcWriter.println("}");
}
@Override
public String getProxyQualifiedName()
{
return cursorType.getPackage().getName()+"."+getProxySimpleName();
}
@Override
public String getProxySimpleName()
{
String typeName = cursorName.replaceAll("\\W", "_");
return typeName+"_SQL_Cursor";
}
@Override
protected SourcePrinter getSourcePrinter()
{
String packageName = cursorType.getPackage().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("WSQLCursor<"+getKeyTypeName()+","+getKeyTypeName(objectStoreKeyPath)+","+getTargetObjectClassName()+">");
return new SourceCodePrinter(composerFactory.createSourceWriter(context.getGeneratorContext(), printWriter), context.getLogger());
}
protected String[] getImports()
{
String[] imports = new String[] {
Array.class.getCanonicalName(),
WSQLAbstractDatabase.class.getCanonicalName(),
WSQLKeyRange.class.getCanonicalName(),
WSQLTransaction.class.getCanonicalName(),
WSQLCursor.class.getCanonicalName(),
CursorDirection.class.getCanonicalName(),
JSONObject.class.getCanonicalName(),
JsArrayMixed.class.getCanonicalName()
};
return imports;
}
}