Skip to content

Instantly share code, notes, and snippets.

@romainpiel
Last active January 3, 2017 17:03
Show Gist options
  • Save romainpiel/8999811 to your computer and use it in GitHub Desktop.
Save romainpiel/8999811 to your computer and use it in GitHub Desktop.
Square wire - handling default values
public static <T extends Message> T getDefault(Class<T> type) {
if (type == null) {
return null;
}
// Create Builder instance
Class builderType = null;
Message.Builder<T> msgBuilder = null;
try {
builderType = getBuilder(type);
msgBuilder = (Message.Builder<T>) builderType.getConstructor().newInstance();
} catch (ClassNotFoundException e) {
Log.e(TAG, e.getMessage(), e);
} catch (InvocationTargetException e) {
Log.e(TAG, e.getMessage(), e);
} catch (NoSuchMethodException e) {
Log.e(TAG, e.getMessage(), e);
} catch (InstantiationException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IllegalAccessException e) {
Log.e(TAG, e.getMessage(), e);
}
if (builderType == null || msgBuilder == null) {
return null;
}
// Browse Builder fields and assign everything to default values
Object resultingValue;
Field staticField;
for (Field field : builderType.getDeclaredFields()) {
try {
resultingValue = null;
// if instanceof Message, set the default values one step deeper
if (Message.class.isAssignableFrom(field.getType())) {
resultingValue = getDefault((Class<? extends Message>) field.getType());
} else if (!Modifier.isFinal(field.getModifiers())) {
staticField = type.getField("DEFAULT_" + field.getName().toUpperCase());
resultingValue = staticField.get(null);
}
if (resultingValue != null) {
field.set(msgBuilder, resultingValue);
}
} catch (IllegalAccessException e) {
Log.e(TAG, e.getMessage(), e);
} catch (NoSuchFieldException e) {
Log.e(TAG, e.getMessage(), e);
}
}
return msgBuilder.build();
}
public static <T extends Message> T merge(T msg, T defaultMsg) {
if (msg == null || defaultMsg == null) {
return null;
}
// Create Builder instances
Class<? extends Message> type = msg.getClass();
Message.Builder<T> msgBuilder = null;
Message.Builder<T> defaultMsgBuilder = null;
Class builderType = null;
try {
builderType = getBuilder(type);
msgBuilder = (Message.Builder<T>) builderType.getConstructor(type).newInstance(msg);
defaultMsgBuilder = (Message.Builder<T>) builderType.getConstructor(type).newInstance(defaultMsg);
} catch (InstantiationException e) {
Log.e(TAG, e.getMessage(), e);
} catch (IllegalAccessException e) {
Log.e(TAG, e.getMessage(), e);
} catch (InvocationTargetException e) {
Log.e(TAG, e.getMessage(), e);
} catch (NoSuchMethodException e) {
Log.e(TAG, e.getMessage(), e);
} catch (ClassNotFoundException e) {
Log.e(TAG, e.getMessage(), e);
}
if (builderType == null || msgBuilder == null || defaultMsgBuilder == null) {
return null;
}
// Browse Builder fields and merge defaultMsg values into msg if msg's val is null
Object messageFieldValue, defaultMessageFieldValue;
Object resultingValue;
for (Field field : builderType.getDeclaredFields()) {
try {
messageFieldValue = field.get(msgBuilder);
defaultMessageFieldValue = field.get(defaultMsgBuilder);
resultingValue = null;
// if message, we'll have to merge enclosing field values
if (Message.class.isAssignableFrom(field.getType())) {
resultingValue = merge((Message) messageFieldValue, (Message) defaultMessageFieldValue);
} else if (!Modifier.isFinal(field.getModifiers())) {
resultingValue = Wire.get(messageFieldValue, defaultMessageFieldValue);
}
if (resultingValue != null) {
field.set(msgBuilder, resultingValue);
}
} catch (IllegalAccessException e) {
Log.e(TAG, e.getMessage(), e);
}
}
return msgBuilder.build();
}
private static <T extends Message> Class getBuilder(Class<T> type) throws ClassNotFoundException {
if (type == null) {
return null;
}
return Class.forName(type.getName() + "$Builder");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment