/* * 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.util.Date; import java.util.Set; import org.cruxframework.crux.core.client.collection.CollectionFactory; import org.cruxframework.crux.core.client.db.WSQLAbstractObjectStore.EncodeCallback; import org.cruxframework.crux.core.client.db.WSQLKeyRange; import org.cruxframework.crux.core.client.file.Blob; import org.cruxframework.crux.core.client.utils.EscapeUtils; import org.cruxframework.crux.core.client.utils.FileUtils; import org.cruxframework.crux.core.client.utils.JsUtils; 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.AbstractKeyValueProxyCreator; 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.JPrimitiveType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.json.client.JSONParser; /** * @author Thiago da Rosa de Bustamante * */ public abstract class SQLAbstractKeyValueProxyCreator extends AbstractKeyValueProxyCreator { private JClassType blobType; public SQLAbstractKeyValueProxyCreator(RebindContext context, JClassType targetObjectType, String objectStoreName, String[] keyPath) { super(context, targetObjectType, objectStoreName, keyPath); this.blobType = context.getGeneratorContext().getTypeOracle().findType(Blob.class.getCanonicalName()); } @Override protected void generateGetNativeKeyMethod(SourcePrinter srcWriter) { if (hasCompositeKey()) { super.generateGetNativeKeyMethod(srcWriter); } else { srcWriter.println("private "+JsArrayMixed.class.getCanonicalName()+" getNativeKey("+getKeyTypeName()+" key){"); srcWriter.println(JsArrayMixed.class.getCanonicalName()+ " result = "+JsArrayMixed.class.getCanonicalName()+".createArray().cast();"); srcWriter.println("getNativeKey(key, result);"); srcWriter.println("return result;"); srcWriter.println("}"); srcWriter.println(); srcWriter.println("private void getNativeKey("+getKeyTypeName()+" key, "+JsArrayMixed.class.getCanonicalName()+" result){"); srcWriter.println("if (key == null){"); srcWriter.println("result.push((String)null);"); srcWriter.println("return;"); srcWriter.println("}"); JType jType = getPropertyType(keyPath[0]); if (jType.equals(stringType)) { srcWriter.println("result.push((String)key);"); } else if (jType.equals(integerType) || (jType.equals(JPrimitiveType.INT))) { srcWriter.println("result.push((int)key);"); } else if (jType.equals(doubleType) || (jType.equals(JPrimitiveType.DOUBLE))) { srcWriter.println("result.push((double)key);"); } else if (jType.equals(dateType)) { srcWriter.println("result.push((double)(("+Date.class.getCanonicalName()+")key).getTime());"); } else { throw new CruxGeneratorException("Invalid key type for objectStore ["+targetObjectType.getParameterizedQualifiedSourceName()+"]"); } srcWriter.println("}"); } } protected JType getPropertyType(String property) { JType jType = JClassUtils.getTypeForProperty(property, targetObjectType); if (jType == null) { throw new CruxGeneratorException("Invalid property for objectStore ["+targetObjectType.getParameterizedQualifiedSourceName()+"]"); } return jType; } protected void generateGetKeyPathMethod(SourcePrinter srcWriter) { srcWriter.println("protected Array<String> getKeyPath(){"); srcWriter.println("Array<String> keyPath = "+CollectionFactory.class.getCanonicalName()+".createArray();"); for(String path: keyPath) { srcWriter.println("keyPath.add("+EscapeUtils.quote(path)+");"); } srcWriter.println("return keyPath;"); srcWriter.println("}"); srcWriter.println(); } protected void generateGetIndexedColumnNamesMethod(SourcePrinter srcWriter, Set<String> indexColumns) { srcWriter.println("protected Array<String> getIndexedColumnNames(){"); srcWriter.println("Array<String> indexColumnNames = "+CollectionFactory.class.getCanonicalName()+".createArray();"); for (String col : indexColumns) { for(String path: keyPath) { if (!path.equals(col)) { srcWriter.println("indexColumnNames.add("+EscapeUtils.quote(col)+");"); } } } srcWriter.println("return indexColumnNames;"); srcWriter.println("}"); srcWriter.println(); } protected void generateGetKeyRangeFactoryMethod(SourcePrinter srcWriter, String parentName) { srcWriter.println("public KeyRangeFactory<"+getKeyTypeName()+"> getKeyRangeFactory(){"); String keyRangeFatoryClassName = new SQLKeyRangeFactoryProxyCreator(context, targetObjectType, objectStoreName, keyPath, parentName).create(); srcWriter.println("return (KeyRangeFactory<"+getKeyTypeName()+">) new "+keyRangeFatoryClassName+"();"); srcWriter.println("}"); srcWriter.println(); } protected void generateDecodeObjectMethod(SourcePrinter srcWriter) { srcWriter.println("protected "+getTargetObjectClassName()+" decodeObject(String encodedObject){"); srcWriter.println("if ("+StringUtils.class.getCanonicalName()+".isEmpty(encodedObject)){"); srcWriter.println("return null;"); srcWriter.println("}"); if (targetObjectType.isAssignableTo(blobType)) { srcWriter.println("return "+FileUtils.class.getCanonicalName()+".fromDataURI(encodedObject).cast();"); } else { srcWriter.println("return "+serializerVariable+".decode("+JSONParser.class.getCanonicalName()+".parseStrict(encodedObject).isObject());"); } srcWriter.println("}"); srcWriter.println(); } protected void generateEncodeObjectMethod(SourcePrinter srcWriter) { srcWriter.println("protected void encodeObject("+getTargetObjectClassName()+" object, "+EncodeCallback.class.getCanonicalName()+" callback){"); srcWriter.println("if (object == null){"); srcWriter.println("throw new NullPointerException();"); srcWriter.println("}"); if (targetObjectType.isAssignableTo(blobType)) { throw new CruxGeneratorException("Blobs and files can not be inserted into object stores. Use FieStore instead."); } else if (isEmptyType()) { srcWriter.println("callback.onEncode("+JsUtils.class.getCanonicalName()+".toJSONValue(object));"); } else { srcWriter.println("callback.onEncode("+serializerVariable+".encode(object).isObject());"); } srcWriter.println("}"); srcWriter.println(); } protected void generateAddKeyRangeToQueryMethod(SourcePrinter srcWriter) { srcWriter.println("public void addKeyRangeToQuery(final KeyRange<"+getKeyTypeName()+"> range, "+ StringBuilder.class.getCanonicalName()+" sql, "+JsArrayMixed.class.getCanonicalName()+" args){"); srcWriter.println(JavaScriptObject.class.getCanonicalName()+" nativeKeyRange = "+WSQLKeyRange.class.getCanonicalName()+".getNativeKeyRange(range);"); srcWriter.println(JsArrayMixed.class.getCanonicalName()+" lower = "+JsArrayMixed.class.getCanonicalName()+".createArray().cast();"); srcWriter.println(JsArrayMixed.class.getCanonicalName()+" upper = "+JsArrayMixed.class.getCanonicalName()+".createArray().cast();"); srcWriter.println(JsUtils.class.getCanonicalName()+".readPropertyValue(nativeKeyRange, \"lower\", lower, false);"); srcWriter.println(JsUtils.class.getCanonicalName()+".readPropertyValue(nativeKeyRange, \"upper\", upper, false);"); srcWriter.println("boolean hasLower = false;"); srcWriter.println("if (lower.length() > 0){"); srcWriter.println("hasLower = true;"); if (keyPath.length == 1) { srcWriter.println("sql.append("+EscapeUtils.quote("\""+keyPath[0]+"\"")+" +(range.isLowerOpen()?\">\":\">=\")+\" ?\");"); srcWriter.println(JsUtils.class.getCanonicalName()+".copyValues(lower, args);"); } else { boolean first = true; for(int i = 0; i < keyPath.length; i++) { if (!first) { srcWriter.println("sql.append(\" AND \");"); } srcWriter.println("sql.append("+EscapeUtils.quote("\""+keyPath[i]+"\"")+" +(range.isLowerOpen()?\">\":\">=\")+\" ?\");"); first = false; } srcWriter.println(JsArrayMixed.class.getCanonicalName()+" lowerArrayColumn = lower.getObject(0).cast();"); srcWriter.println(JsUtils.class.getCanonicalName()+".copyValues(lowerArrayColumn, args);"); } srcWriter.println("}"); srcWriter.println("if (upper.length() > 0){"); if (keyPath.length == 1) { srcWriter.println("if (hasLower){"); srcWriter.println("sql.append(\" AND \");"); srcWriter.println("}"); srcWriter.println("sql.append("+EscapeUtils.quote("\""+keyPath[0]+"\"")+" +(range.isUpperOpen()?\"<\":\"<=\")+\" ?\");"); srcWriter.println(JsUtils.class.getCanonicalName()+".copyValues(upper, args);"); } else { boolean first = true; for(int i = 0; i < keyPath.length; i++) { if (!first) { srcWriter.println("sql.append(\" AND \");"); } else { srcWriter.println("if (hasLower){"); srcWriter.println("sql.append(\" AND \");"); srcWriter.println("}"); } srcWriter.println("sql.append("+EscapeUtils.quote("\""+keyPath[i]+"\"")+" +(range.isUpperOpen()?\"<\":\"<=\")+\" ?\");"); first = false; } srcWriter.println(JsArrayMixed.class.getCanonicalName()+" upperArrayColumn = upper.getObject(0).cast();"); srcWriter.println(JsUtils.class.getCanonicalName()+".copyValues(upperArrayColumn, args);"); } srcWriter.println("}"); srcWriter.println("}"); srcWriter.println(); } protected void generateAddKeyToQueryMethod(SourcePrinter srcWriter) { srcWriter.println("protected void addKeyToQuery(final "+getKeyTypeName()+" key, "+ StringBuilder.class.getCanonicalName()+" sql, "+JsArrayMixed.class.getCanonicalName()+" args){"); boolean first = true; for(String path: keyPath) { if (!first) { srcWriter.print("sql.append(\" AND \");"); } srcWriter.println("sql.append("+EscapeUtils.quote("\""+path+"\" = ?")+");"); first = false; } srcWriter.println("getNativeKey(key, args);"); srcWriter.println("}"); srcWriter.println(); } }