I am using the following method to print all bundle contents in any possible case. The problem is that PMD is reporting both NcssCount
and CyclomaticComplexity
. I would like to improve the code so as to get rid of the warnings and not just supress them.
private static String bundleToString(Bundle bundle) {
StringBuilder out = new StringBuilder("Bundle[");
if (bundle == null) {
out.append("null");
} else {
boolean first = true;
for (String key : bundle.keySet()) {
if (!first) {
out.append(", ");
}
out.append(key).append('=');
Object value = bundle.get(key);
if (value instanceof int[]) {
out.append(Arrays.toString((int[]) value));
} else if (value instanceof byte[]) {
out.append(Arrays.toString((byte[]) value));
} else if (value instanceof boolean[]) {
out.append(Arrays.toString((boolean[]) value));
} else if (value instanceof short[]) {
out.append(Arrays.toString((short[]) value));
} else if (value instanceof long[]) {
out.append(Arrays.toString((long[]) value));
} else if (value instanceof float[]) {
out.append(Arrays.toString((float[]) value));
} else if (value instanceof double[]) {
out.append(Arrays.toString((double[]) value));
} else if (value instanceof String[]) {
out.append(Arrays.toString((String[]) value));
} else if (value instanceof CharSequence[]) {
out.append(Arrays.toString((CharSequence[]) value));
} else if (value instanceof Parcelable[]) {
out.append(Arrays.toString((Parcelable[]) value));
} else if (value instanceof Bundle) {
out.append(bundleToString((Bundle) value));
} else {
out.append(value);
}
first = false;
}
}
out.append(']');
return out.toString();
}
I've tried to split the code in two parts with the following logic but the NcssCount
and CyclomaticComplexity
just moved to the new method that does all the array casting.
if (value != null && value.getClass().isArray()) {
// the new method to call all the array casts
newMethodThatSuffersFromTheSameProblem(out, value);
} else if (value instanceof Bundle) {
out.append(bundleToString((Bundle) value));
} else {
out.append(value);
}
Can I somehow do a dynamic cast to each array type?
if (value != null && value.getClass().isArray()) {
out.append(Arrays.toString((<cast-to-class-array-[]>) value));
}
I've also tried out.append(Arrays.toString(value.getClass().cast(value)));
but gets a compilation error Cannot resolve method 'toString(capture<? extends java.lang.Object>)'
} else if (value instanceof String[]) {
out.append(Arrays.toString((String[]) value));
} else if (value instanceof CharSequence[]) {
out.append(Arrays.toString((CharSequence[]) value));
} else if (value instanceof Parcelable[]) {
out.append(Arrays.toString((Parcelable[]) value));
These 3 if
s could be replaced with one
} else if (value != null && value.getClass().isArray())
out.append(Arrays.toString((Object[]) value));
For the rest you can have static Map<Class, Function<Object, String>> convertors
and pre-fill it as
convertors.put(int[].class, value -> Arrays.toString((int [])value));
...
and then use
Function<Object, String> convertor = convertors.get(value.getClass());
if (convertor != null) {
out.append(convertor.apply(value));
} else ...
FOR OLDER ANDROID WHERE LAMBDAS ARE NOT AVAILABLE
interface ToString { String convert(Object object); }
...
static Map<Class, ToString> convertors = new HashMap();
convertors.put(int[].class, new ToString() { public String convert(Object value) { return Arrays.toString((int [])value); }});
...
and then use
ToString convertor = convertors.get(value.getClass());
if (convertor != null) {
out.append(convertor.convert(value));
} else ...