001package org.gbif.api.jackson;
002
003import org.gbif.api.vocabulary.Rank;
004
005import java.io.IOException;
006import java.util.Map;
007
008import com.google.common.collect.Maps;
009import org.codehaus.jackson.JsonGenerator;
010import org.codehaus.jackson.JsonParser;
011import org.codehaus.jackson.JsonToken;
012import org.codehaus.jackson.map.DeserializationContext;
013import org.codehaus.jackson.map.JsonDeserializer;
014import org.codehaus.jackson.map.JsonSerializer;
015import org.codehaus.jackson.map.SerializerProvider;
016
017/**
018 * Jackson {@link JsonSerializer} and Jackson {@link JsonDeserializer} classes for {@link Rank} that uses the common rank markers instead of enum names.
019 */
020public class RankSerde {
021
022  /**
023   * Jackson {@link JsonSerializer} for {@link Rank}.
024   */
025  public static class RankJsonSerializer extends JsonSerializer<Rank> {
026
027    @Override
028    public void serialize(Rank value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
029      if (value == null) {
030        jgen.writeNull();
031        return;
032      }
033      if (value.getMarker() == null) {
034        jgen.writeString(value.name().toLowerCase().replaceAll("_", " "));
035      } else {
036        jgen.writeString(value.getMarker());
037      }
038    }
039  }
040
041  /**
042   * Jackson {@link JsonDeserializer} for {@link Rank}.
043   */
044  public static class RankJsonDeserializer extends JsonDeserializer<Rank> {
045    private static final Map<String, Rank> RANKS = Maps.newHashMap();
046    static {
047      for (Rank r : Rank.values()) {
048        if (r.getMarker() != null) {
049          RANKS.put(r.getMarker(), r);
050        }
051      }
052    }
053
054    @Override
055    public Rank deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
056      if (jp.getCurrentToken() == JsonToken.VALUE_STRING) {
057        if (RANKS.containsKey(jp.getText())) {
058          return RANKS.get(jp.getText());
059
060        } else {
061          // try enum name as last resort
062          try {
063            return Rank.valueOf(jp.getText().toUpperCase().replaceAll(" ", "_"));
064          } catch (IllegalArgumentException e) {
065            // swallow
066          }
067        }
068        return null;
069      }
070      throw ctxt.mappingException("Expected String");
071    }
072  }
073}