class CollectConstants extends SceneTransformer implements IJbcoTransform {

  private static final Logger logger = LoggerFactory.getLogger(FieldRenamer.class);

  public static final String name = "wjtp.jbco_cc";

  private final Map<Type, List<Constant>> typeToConstants = new HashMap<>();
  public static HashMap<Constant, SootField> constantsToFields = new HashMap<>();

  private int constants = 0;
  private int updatedConstants = 0;

  @Override
  public String getName() {
    return name;
  }

  @Override
  public String[] getDependencies() {
    return new String[] { name };
  }

  @Override
  public void outputSummary() {
    logger.info("Found {} constants, updated {} ones", constants, updatedConstants);
  }

  @Override
  protected void internalTransform(String phaseName, Map<String, String> options) {
    if (isVerbose()) {
      logger.info("Collecting Constant Data");
    }

    BodyBuilder.retrieveAllNames();

    final Chain<SootClass> applicationClasses = Scene.v().getApplicationClasses();

    for (SootClass applicationClass : applicationClasses) {
      for (SootMethod method : applicationClass.getMethods()) {
        if (!method.hasActiveBody() || method.getName().contains(SootMethod.staticInitializerName)) {
          continue;
        }

        for (ValueBox useBox : method.getActiveBody().getUseBoxes()) {
          final Value value = useBox.getValue();
          if (value instanceof Constant) {
            final Constant constant = (Constant) value;
            Type type = constant.getType();
            List<Constant> constants = typeToConstants.computeIfAbsent(type, t -> new ArrayList<>());

            if (!constants.contains(constant)) {
              this.constants++;
              constants.add(constant);
            }
          }
        }
      }
    }

    int count = 0;
    String name = "newConstantJbcoName";
    SootClass[] classes = applicationClasses.toArray(new SootClass[applicationClasses.size()]);
    for (Type type : typeToConstants.keySet()) {
      if (type instanceof NullType) {
        continue; // type = RefType.v("java.lang.Object");
      }
      for (Constant constant : typeToConstants.get(type)) {
        name += "_";
        SootClass randomClass;
        do {
          randomClass = classes[Rand.getInt(classes.length)];
        } while (!isSuitableClassToAddFieldConstant(randomClass, constant));

        final SootField newField
            = Scene.v().makeSootField(FieldRenamer.v().getOrAddNewName(name), type, Modifier.STATIC ^ Modifier.PUBLIC);
        randomClass.addField(newField);
        constantsToFields.put(constant, newField);
        addInitializingValue(randomClass, newField, constant);
        count++;
      }
    }

    updatedConstants += count;
  }

  private boolean isSuitableClassToAddFieldConstant(SootClass sc, Constant constant) {
    if (sc.isInterface()) {
      return false;
    }
    if (constant instanceof ClassConstant) {
      ClassConstant classConstant = (ClassConstant) constant;
      RefType type = (RefType) classConstant.toSootType();
      SootClass classFromConstant = type.getSootClass();
      Hierarchy hierarchy = Scene.v().getActiveHierarchy();
      return hierarchy.isVisible(sc, classFromConstant);
    }
    return true;
  }

  private void addInitializingValue(SootClass sc, SootField f, Constant constant) {<FILL_FUNCTION_BODY>}
}

    if (constant instanceof NullConstant) {
      return;
    } else if (constant instanceof IntConstant) {
      if (((IntConstant) constant).value == 0) {
        return;
      }
    } else if (constant instanceof LongConstant) {
      if (((LongConstant) constant).value == 0) {
        return;
      }
    } else if (constant instanceof StringConstant) {
      if (((StringConstant) constant).value == null) {
        return;
      }
    } else if (constant instanceof DoubleConstant) {
      if (((DoubleConstant) constant).value == 0) {
        return;
      }
    } else if (constant instanceof FloatConstant) {
      if (((FloatConstant) constant).value == 0) {
        return;
      }
    }

    Body b;
    boolean newInit = false;
    if (!sc.declaresMethodByName(SootMethod.staticInitializerName)) {
      SootMethod m = Scene.v().makeSootMethod(SootMethod.staticInitializerName, emptyList(), VoidType.v(), Modifier.STATIC);
      sc.addMethod(m);
      b = Jimple.v().newBody(m);
      m.setActiveBody(b);
      newInit = true;
    } else {
      SootMethod m = sc.getMethodByName(SootMethod.staticInitializerName);
      if (!m.hasActiveBody()) {
        b = Jimple.v().newBody(m);
        m.setActiveBody(b);
        newInit = true;
      } else {
        b = m.getActiveBody();
      }
    }

    PatchingChain<Unit> units = b.getUnits();

    units.addFirst(Jimple.v().newAssignStmt(Jimple.v().newStaticFieldRef(f.makeRef()), constant));
    if (newInit) {
      units.addLast(Jimple.v().newReturnVoidStmt());
    }
  
<methods>public non-sealed void <init>() ,public final void transform(java.lang.String, Map<java.lang.String,java.lang.String>) ,public final void transform(java.lang.String) ,public final void transform() <variables>