All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ning.billing.recurly.model.RecurlyObject Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2010-2014 Ning, Inc.
 * Copyright 2014-2015 The Billing Project, LLC
 *
 * The Billing Project licenses this file to you under the Apache License, version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */

package com.ning.billing.recurly.model;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.xml.bind.annotation.XmlTransient;

import com.fasterxml.jackson.annotation.JsonInclude;
import org.joda.time.DateTime;

import com.ning.billing.recurly.RecurlyClient;
import com.ning.billing.recurly.model.jackson.RecurlyObjectsSerializer;
import com.ning.billing.recurly.model.jackson.RecurlyXmlSerializerProvider;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;

@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class RecurlyObject {

    @XmlTransient
    private RecurlyClient recurlyClient;

    @XmlTransient
    protected String href;

    public static final String NIL_STR = "nil";
    public static final List NIL_VAL = Arrays.asList("nil", "true");

    // See https://github.com/killbilling/recurly-java-library/issues/4 for why
    // @JsonIgnore is required here and @XmlTransient is not enough
    @JsonIgnore
    public String getHref() {
        return href;
    }

    public void setHref(final Object href) {
        this.href = stringOrNull(href);
    }

    public static XmlMapper newXmlMapper() {
        final XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.setSerializerProvider(new RecurlyXmlSerializerProvider());
        final AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
        final AnnotationIntrospector secondary = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
        final AnnotationIntrospector pair = new AnnotationIntrospectorPair(primary, secondary);
        xmlMapper.setAnnotationIntrospector(pair);
        xmlMapper.registerModule(new JodaModule());
        xmlMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

        final SimpleModule m = new SimpleModule("module", new Version(1, 0, 0, null, null, null));
        m.addSerializer(Accounts.class, new RecurlyObjectsSerializer(Accounts.class, "account"));
        m.addSerializer(AddOns.class, new RecurlyObjectsSerializer(AddOns.class, "add_on"));
        m.addSerializer(Adjustments.class, new RecurlyObjectsSerializer(Adjustments.class, "adjustment"));
        m.addSerializer(Coupons.class, new RecurlyObjectsSerializer(Coupons.class, "coupon"));
        m.addSerializer(Invoices.class, new RecurlyObjectsSerializer(Invoices.class, "invoice"));
        m.addSerializer(Plans.class, new RecurlyObjectsSerializer(Plans.class, "plan"));
        m.addSerializer(RecurlyErrors.class, new RecurlyObjectsSerializer(RecurlyErrors.class, "error"));
        m.addSerializer(SubscriptionAddOns.class, new RecurlyObjectsSerializer(SubscriptionAddOns.class, "subscription_add_on"));
        m.addSerializer(Subscriptions.class, new RecurlyObjectsSerializer(Subscriptions.class, "subscription"));
        m.addSerializer(Transactions.class, new RecurlyObjectsSerializer(Transactions.class, "transaction"));
        xmlMapper.registerModule(m);

        return xmlMapper;
    }

    public static Boolean booleanOrNull(@Nullable final Object object) {
        if (isNull(object)) {
            return null;
        }

        // Booleans are represented as objects (e.g. false), which Jackson
        // will interpret as an Object (Map), not Booleans.
        if (object instanceof Map) {
            final Map map = (Map) object;
            if (map.keySet().size() == 2 && "boolean".equals(map.get("type"))) {
                return Boolean.valueOf((String) map.get(""));
            }
        }

        return Boolean.valueOf(object.toString());
    }

    public static String stringOrNull(@Nullable final Object object) {
        if (isNull(object)) {
            return null;
        }

        return object.toString().trim();
    }

    public static Integer integerOrNull(@Nullable final Object object) {
        if (isNull(object)) {
            return null;
        }

        // Integers are represented as objects (e.g. 2015), which Jackson
        // will interpret as an Object (Map), not Integers.
        if (object instanceof Map) {
            final Map map = (Map) object;
            if (map.keySet().size() == 2 && "integer".equals(map.get("type"))) {
                return Integer.valueOf((String) map.get(""));
            }
        }

        return Integer.valueOf(object.toString());
    }

    public static DateTime dateTimeOrNull(@Nullable final Object object) {
        if (isNull(object)) {
            return null;
        }

        // DateTimes are represented as objects (e.g. 2011-04-19T07:00:00Z), which Jackson
        // will interpret as an Object (Map), not DateTimes.
        if (object instanceof Map) {
            final Map map = (Map) object;
            if (map.keySet().size() == 2 && "datetime".equals(map.get("type"))) {
                return new DateTime(map.get(""));
            }
        }

        return new DateTime(object.toString());
    }

    public static boolean isNull(@Nullable final Object object) {
        if (object == null) {
            return true;
        }

        // Hack to work around Recurly output for nil values: the response will contain
        // an element with a nil attribute (e.g.  or ) which Jackson will
        // interpret as an Object (Map), not a String.
        if (object instanceof Map) {
            final Map map = (Map) object;
            if (map.keySet().size() >= 1 && map.get(NIL_STR) != null && NIL_VAL.contains(map.get(NIL_STR).toString())) {
                return true;
            }
        }

        return false;
    }

     T fetch(final T object, final Class clazz) {
        if (object.getHref() == null || recurlyClient == null) {
            return object;
        }
        return recurlyClient.doGETWithFullURL(clazz, object.getHref());
    }

    public void setRecurlyClient(final RecurlyClient recurlyClient) {
        this.recurlyClient = recurlyClient;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        return this.hashCode() == o.hashCode();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy