public void addMatchingSetters() {
   check(implInterface || !dataTypeIn.isInterface());
   Set<String> usedFields = new HashSet<>();
   if (constructorParams != null) {
     usedFields.addAll(constructorParams);
   }
   if (factoryParams != null) {
     usedFields.addAll(factoryParams);
   }
   for (List<String> list : setters.values()) {
     usedFields.addAll(list);
   }
   for (String fieldName : fields.keySet()) {
     FieldGen fieldGen = fields.get(fieldName);
     Method getter = fieldGen.method;
     if (getter == null) continue;
     if (usedFields.contains(fieldName)) continue;
     String setterName =
         "set" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
     try {
       Method setter;
       if (implInterface) setter = dataTypeOut.getMethod(setterName, getter.getReturnType());
       else setter = dataTypeIn.getMethod(setterName, getter.getReturnType());
       if (!isPrivate(setter.getModifiers())) {
         addSetter(setter, asList(fieldName));
       }
     } catch (NoSuchMethodException e) {
       throw new RuntimeException(e);
     }
   }
 }
 public SerializerGenClass(Class<?> type, Class<?> typeImpl) {
   checkNotNull(type);
   checkNotNull(typeImpl);
   check(type.isInterface());
   check(type.isAssignableFrom(typeImpl));
   this.dataTypeIn = type;
   this.dataTypeOut = typeImpl;
   this.implInterface = true;
 }
 public void addSetter(Method method, List<String> fields) {
   check(implInterface || !dataTypeIn.isInterface());
   checkNotNull(method);
   checkNotNull(fields);
   check(!isPrivate(method.getModifiers()), "Setter cannot be private: %s", method);
   check(method.getGenericParameterTypes().length == fields.size());
   check(!setters.containsKey(method));
   setters.put(method, fields);
 }
 public void setConstructor(Constructor<?> constructor, List<String> fields) {
   check(implInterface || !dataTypeIn.isInterface());
   checkNotNull(constructor);
   checkNotNull(fields);
   check(this.constructor == null, "Constructor is already set: %s", this.constructor);
   check(!isPrivate(constructor.getModifiers()), "Constructor cannot be private: %s", constructor);
   check(constructor.getGenericParameterTypes().length == fields.size());
   this.constructor = constructor;
   this.constructorParams = fields;
 }
 public void setFactory(Method methodFactory, List<String> fields) {
   check(implInterface || !dataTypeIn.isInterface());
   checkNotNull(methodFactory);
   checkNotNull(fields);
   check(this.factory == null, "Factory is already set: %s", this.factory);
   check(!isPrivate(methodFactory.getModifiers()), "Factory cannot be private: %s", methodFactory);
   check(isStatic(methodFactory.getModifiers()), "Factory must be static: %s", methodFactory);
   check(methodFactory.getGenericParameterTypes().length == fields.size());
   this.factory = methodFactory;
   this.factoryParams = fields;
 }
 public void addField(Field field, SerializerGen serializer, int added, int removed) {
   check(implInterface || !dataTypeIn.isInterface());
   check(isPublic(field.getModifiers()));
   String fieldName = field.getName();
   check(!fields.containsKey(fieldName), "Duplicate field '%s'", field);
   FieldGen fieldGen = new FieldGen();
   fieldGen.field = field;
   fieldGen.serializer = serializer;
   fieldGen.versionAdded = added;
   fieldGen.versionDeleted = removed;
   fieldGen.offset = lastOffset;
   lastOffset += getType(field.getType()).getSize();
   fields.put(fieldName, fieldGen);
 }
 public SerializerGenClass(Class<?> type) {
   this.dataTypeIn = checkNotNull(type);
   if (!dataTypeIn.isInterface()) {
     this.dataTypeOut = dataTypeIn;
   }
 }
  @Override
  public void prepareDeserializeStaticMethods(
      int version,
      SerializerBuilder.StaticMethods staticMethods,
      CompatibilityLevel compatibilityLevel) {
    if (staticMethods.startDeserializeStaticMethod(this, version)) {
      return;
    }

    if (!implInterface && dataTypeIn.isInterface()) {
      Expression expression =
          deserializeInterface(this.getRawType(), version, staticMethods, compatibilityLevel);
      staticMethods.registerStaticDeserializeMethod(this, version, expression);
      return;
    }
    if (!implInterface && constructor == null && factory == null && setters.isEmpty()) {
      Expression expression = deserializeClassSimple(version, staticMethods, compatibilityLevel);
      staticMethods.registerStaticDeserializeMethod(this, version, expression);
      return;
    }

    List<Expression> list = new ArrayList<>();
    final Map<String, Expression> map = new HashMap<>();
    for (String fieldName : fields.keySet()) {
      FieldGen fieldGen = fields.get(fieldName);

      if (!fieldGen.hasVersion(version)) continue;

      fieldGen.serializer.prepareDeserializeStaticMethods(
          version, staticMethods, compatibilityLevel);
      Expression expression =
          let(
              fieldGen.serializer.deserialize(
                  fieldGen.getRawType(), version, staticMethods, compatibilityLevel));
      list.add(expression);
      map.put(fieldName, cast(expression, fieldGen.getRawType()));
    }

    Expression constructor;
    if (factory == null) {
      constructor = callConstructor(this.getRawType(), map, version);
    } else {
      constructor = callFactory(map, version);
    }

    Expression local = let(constructor);
    list.add(local);

    for (Method method : setters.keySet()) {
      boolean found = false;
      for (String fieldName : setters.get(method)) {
        FieldGen fieldGen = fields.get(fieldName);
        Preconditions.checkNotNull(fieldGen, "Field '%s' is not found in '%s'", fieldName, method);
        if (fieldGen.hasVersion(version)) {
          found = true;
          break;
        }
      }
      if (found) {
        Expression[] temp = new Expression[method.getParameterTypes().length];
        int i = 0;
        for (String fieldName : setters.get(method)) {
          FieldGen fieldGen = fields.get(fieldName);
          assert fieldGen != null;
          if (fieldGen.hasVersion(version)) {
            temp[i++] = map.get(fieldName);
          } else {
            temp[i++] = pushDefaultValue(fieldGen.getAsmType());
          }
        }
        list.add(call(local, method.getName(), temp));
      }
    }

    for (String fieldName : fields.keySet()) {
      FieldGen fieldGen = fields.get(fieldName);
      if (!fieldGen.hasVersion(version)) continue;
      if (fieldGen.field == null || isFinal(fieldGen.field.getModifiers())) continue;
      Variable field = field(local, fieldName);
      list.add(set(field, map.get(fieldName)));
    }

    list.add(local);
    staticMethods.registerStaticDeserializeMethod(this, version, sequence(list));
  }