001package net.bramp.commons.lang3.math.gson;
002
003import com.google.errorprone.annotations.Immutable;
004import com.google.gson.TypeAdapter;
005import com.google.gson.stream.JsonReader;
006import com.google.gson.stream.JsonToken;
007import com.google.gson.stream.JsonWriter;
008import java.io.IOException;
009import org.apache.commons.lang3.math.Fraction;
010
011/**
012 * GSON TypeAdapter for Apache Commons Math Fraction Object
013 *
014 * @author bramp
015 */
016@Immutable
017public class FractionAdapter extends TypeAdapter<Fraction> {
018
019  /** If set, 0/0 returns this value, instead of throwing a ArithmeticException */
020  @SuppressWarnings(
021      "Immutable") // TODO Remove when https://github.com/google/error-prone/issues/512 is fixed
022  private final Fraction zeroByZero;
023
024  /** If set, N/0 returns this value, instead of throwing a ArithmeticException */
025  @SuppressWarnings(
026      "Immutable") // TODO Remove when https://github.com/google/error-prone/issues/512 is fixed
027  private final Fraction divideByZero;
028
029  public FractionAdapter() {
030    this(Fraction.ZERO, Fraction.ZERO);
031  }
032
033  private FractionAdapter(Fraction zeroByZero, Fraction divideByZero) {
034    this.zeroByZero = zeroByZero;
035    this.divideByZero = divideByZero;
036  }
037
038  @Override
039  public Fraction read(JsonReader reader) throws IOException {
040    JsonToken next = reader.peek();
041
042    if (next == JsonToken.NULL) {
043      reader.nextNull();
044      return null;
045    }
046
047    if (next == JsonToken.NUMBER) {
048      return Fraction.getFraction(reader.nextDouble());
049    }
050
051    String fraction = reader.nextString().trim();
052
053    // Ambiguous as to what 0/0 is, but FFmpeg seems to think it's zero
054    if (zeroByZero != null && "0/0".equals(fraction)) {
055      return zeroByZero;
056    }
057
058    // Another edge cases is invalid files sometimes output 1/0.
059    if (divideByZero != null && fraction.endsWith("/0")) {
060      return divideByZero;
061    }
062
063    return Fraction.getFraction(fraction);
064  }
065
066  @Override
067  public void write(JsonWriter writer, Fraction value) throws IOException {
068    if (value == null) {
069      writer.nullValue();
070      return;
071    }
072    writer.value(value.toProperString());
073  }
074}