/**
* 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 org.commoncrawl.rpc.compiler.JCompType.CCompType;
import org.commoncrawl.rpc.compiler.JCompType.CppCompType;
/**
*/
public class JVector extends JCompType {
static private int level = 0;
static private String getId(String id) { return id+getLevel(); }
static private String getLevel() { return Integer.toString(level); }
static private void incrLevel() { level++; }
static private void decrLevel() { level--; }
private JType type;
class JavaVector extends JavaCompType {
private JType.JavaType element;
JavaVector(JType.JavaType t) {
super("java.util.ArrayList<"+t.getWrapperType()+">",
"Vector", "java.util.ArrayList<"+t.getWrapperType()+">");
element = t;
}
@Override
boolean isIntrinsicType() {
return false;
}
@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");
element.genReadMethod(cb, getId("e"), getId("e"), true);
cb.append(fname+".add("+getId("e")+");\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");
element.genSkipMethod(cb);
cb.append("}\n");
decrLevel();
cb.append("}\n");
}
@Override
void genWriteMethod(CodeBuffer cb, String fname, String tag) {
cb.append("{\n");
incrLevel();
cb.append("int "+getId("len")+" = "+fname+".size();\n");
cb.append("encoder.writeInt(output,"+getId("len")+");\n");
cb.append("for(int "+getId("vidx")+" = 0; "+getId("vidx")+"<"+getId("len")+"; "+getId("vidx")+"++) {\n");
cb.append(element.getType()+" "+getId("e")+" = "+fname+".get("+getId("vidx")+");\n");
element.genWriteMethod(cb, getId("e"), getId("e"));
cb.append("}\n");
cb.append("}\n");
decrLevel();
}
@Override
void genJSON(CodeBuffer cb, String fname) throws IOException {
cb.append("writer.name(\""+fname+"\").beginArray();\n");
cb.append("for(int "+getId("vidx")+" = 0; "+getId("vidx")+"<"+fname+".size();"+getId("vidx")+"++) {\n");
cb.append("writer.value(");
if (element.isIntrinsicType())
cb.append(fname+".get("+getId("vidx")+"));\n");
else
cb.append(fname+".get("+getId("vidx")+").toString());\n");
cb.append("}\n");
cb.append("writer.endArray();\n");
}
@Override
void genClearMethod(CodeBuffer cb, String fname) {
//TODO: IS THIS THE MOST EFFICIENT WAY TO CLEAR A STRING
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 final void genMergeOrClone(boolean isClone,CodeBuffer cb,String type, String targetField, String sourceField) {
cb.append("//Deep Copy Vector\n");
if (isClone) {
cb.append(targetField+" = new "+"java.util.ArrayList<"+ element.getWrapperType() + ">();\n");
}
cb.append("int "+getId("len")+" = "+sourceField+".size();\n");
cb.append("for(int "+getId("vidx")+" = 0; "+getId("vidx")+"<"+getId("len")+"; "+getId("vidx")+"++) {\n");
// get the next entry ...
cb.append(element.getType()+" "+getId("src")+" = "+sourceField+".get("+getId("vidx")+");\n");
// declare copied value
cb.append(element.getType()+" "+getId("tgt")+";\n");
// and clone the new element ...
element.genClone(cb,element.getType(), getId("tgt"), getId("src"));
// and add the new entry to new vector ...
cb.append(targetField + ".add("+getId("tgt")+");\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 true;
}
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 JVector */
public JVector(JType t) {
type = t;
setJavaType(new JavaVector(t.getJavaType()));
setCppType(new CppCompType(" ::std::vector<"+t.getCppType().getType()+">"));
setCType(new CCompType());
}
String getSignature() {
return "[" + type.getSignature() + "]";
}
}