/**
* 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.commoncrawl.rpc.compiler;
import java.io.IOException;
import java.util.Map;
/**
*/
public class JMap extends JCompType {
static private int level = 0;
static private String getLevel() {
return Integer.toString(level);
}
static private void incrLevel() {
level++;
}
static private void decrLevel() {
level--;
}
static private String getId(String id) {
return id + getLevel();
}
private JType keyType;
private JType valueType;
class JavaMap extends JavaCompType {
JType.JavaType key;
JType.JavaType value;
JavaMap(JType.JavaType key, JType.JavaType value) {
super("java.util.TreeMap<" + key.getWrapperType() + ","
+ value.getWrapperType() + ">", "Map", "java.util.TreeMap<"
+ key.getWrapperType() + "," + value.getWrapperType() + ">");
this.key = key;
this.value = value;
}
@Override
void genReadMethod(CodeBuffer cb, String fname, String tag, boolean decl) {
if (decl) {
cb.append(getType() + " " + fname + ";\n");
}
cb.append("{\n");
incrLevel();
cb.append("int "+getId("itemCount")+" = decoder.readInt(input);\n");
cb.append(fname + "=new " + getType() + "();\n");
cb.append("for (int "+getId("i") + "=0;"+getId("i")+"<"+getId("itemCount")+";++"+getId("i")+") {\n");
key.genReadMethod(cb, getId("k"), getId("k"), true);
value.genReadMethod(cb, getId("v"), getId("v"), true);
cb.append(fname + ".put(" + getId("k") + "," + getId("v") + ");\n");
cb.append("}\n");
decrLevel();
cb.append("}\n");
}
@Override
void genSkipMethod(CodeBuffer cb) {
cb.append("{\n");
incrLevel();
cb.append("int "+getId("itemCount")+" = decoder.readInt(input);\n");
cb.append("for (int "+getId("i") + "=0;"+getId("i")+"<"+getId("itemCount")+";++"+getId("i")+") {\n");
key.genSkipMethod(cb);
value.genSkipMethod(cb);
cb.append("}\n");
decrLevel();
cb.append("}\n");
};
@Override
void genJSON(CodeBuffer cb, String fname) throws IOException {
cb.append("writer.name(\""+fname+"\").beginObject();\n");
String entryType = "java.util.Map.Entry<" + key.getWrapperType()
+ "," + value.getWrapperType() + "> ";
cb.append("{\n");
incrLevel();
cb.append("for " + entryType + " " + getId("es") + " : " + fname + ".entrySet(){\n");
cb.append(" writer.name(" + getId("es") +".getKey()).value(" + getId("es") +".getValue());\n");
cb.append("}\n");
decrLevel();
cb.append("writer.endObject()\n");
}
@Override
boolean isIntrinsicType() {
return false;
}
@Override
void genWriteMethod(CodeBuffer cb, String fname, String tag) {
String setType = "java.util.Set<java.util.Map.Entry<"
+ key.getWrapperType() + "," + value.getWrapperType()
+ ">> ";
String entryType = "java.util.Map.Entry<" + key.getWrapperType()
+ "," + value.getWrapperType() + "> ";
String iterType = "java.util.Iterator<java.util.Map.Entry<"
+ key.getWrapperType() + "," + value.getWrapperType()
+ ">> ";
cb.append("{\n");
incrLevel();
cb.append(setType + getId("es") + " = " + fname + ".entrySet();\n");
// write out size of set ...
cb.append("// write out set size\n");
cb.append("encoder.writeInt(output," + getId("es") + ".size());\n");
// write out entries ...
cb.append("for(" + iterType + getId("midx") + " = " + getId("es")
+ ".iterator(); " + getId("midx") + ".hasNext();) {\n");
cb.append(entryType + getId("me") + " = " + getId("midx")
+ ".next();\n");
cb.append(key.getType() + " " + getId("k") + " = " + getId("me")
+ ".getKey();\n");
cb.append(value.getType() + " " + getId("v") + " = " + getId("me")
+ ".getValue();\n");
key.genWriteMethod(cb, getId("k"), getId("k"));
value.genWriteMethod(cb, getId("v"), getId("v"));
cb.append("}\n");
cb.append("}\n");
decrLevel();
}
@Override
void genClearMethod(CodeBuffer cb, String fname) {
cb.append(fname+".clear();\n");
}
@Override
void genClone(CodeBuffer cb,String type, String targetField, String sourceField) {
genMergeOrClone(true, cb, type, targetField, sourceField);
}
@Override
void genMerge(CodeBuffer cb, String type, String targetField,
String sourceField) {
genMergeOrClone(false,cb, type, targetField, sourceField);
}
private void genMergeOrClone(boolean isClone,CodeBuffer cb,String type, String targetField, String sourceField) {
cb.append("//Deep Copy Map\n");
if (isClone) {
cb.append(targetField+" = new "+"java.util.TreeMap<"
+ key.getWrapperType() + "," + value.getWrapperType() + ">();\n");
}
String setType = "java.util.Set<java.util.Map.Entry<"
+ key.getWrapperType() + "," + value.getWrapperType()
+ ">> ";
String entryType = "java.util.Map.Entry<" + key.getWrapperType()
+ "," + value.getWrapperType() + "> ";
String iterType = "java.util.Iterator<java.util.Map.Entry<"
+ key.getWrapperType() + "," + value.getWrapperType()
+ ">> ";
cb.append(setType + getId("es") + " = " + sourceField + ".entrySet();\n");
cb.append("for(" + iterType + getId("midx") + " = " + getId("es")+ ".iterator(); " + getId("midx") + ".hasNext();) {\n");
// get the next entry ...
cb.append(entryType + getId("me") + " = " + getId("midx") + ".next();\n");
// declare key and value locals
cb.append(key.getType()+" "+getId("k")+";\n");
cb.append(value.getType()+" "+getId("v")+";\n");
// and clone a new key ...
key.genClone(cb,key.getType(), getId("k"), getId("me")+ ".getKey()");
value.genClone(cb,value.getType(), getId("v"), getId("me")+ ".getValue()");
// and set it in the new map ...
cb.append(targetField + ".put("+getId("k")+","+getId("v")+");\n");
cb.append("}\n");
}
void genValidFieldCheck(CodeBuffer cb,String fieldName) {
cb.append("if ("+fieldName+".size() != 0)");
}
/** does this type have an idependent dirty state - ignores validFields bit**/
boolean hasDirtyState() {
return false;
}
void genDirtyCheck(CodeBuffer cb,String fieldName) {
cb.append("if (!isDirty){\n");
cb.append("isDirty="+fieldName+".size() !=0;\n");
cb.append("}\n");
}
}
/** Creates a new instance of JMap */
public JMap(JType t1, JType t2) {
setJavaType(new JavaMap(t1.getJavaType(), t2.getJavaType()));
setCppType(new CppCompType(" ::std::map<" + t1.getCppType().getType()
+ "," + t2.getCppType().getType() + ">"));
setCType(new CType());
keyType = t1;
valueType = t2;
}
String getSignature() {
return "{" + keyType.getSignature() + valueType.getSignature() + "}";
}
}