Package com.balancedpayments.core

Source Code of com.balancedpayments.core.Resource

package com.balancedpayments.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.balancedpayments.Balanced;
import com.balancedpayments.errors.HTTPError;
import com.balancedpayments.errors.NotCreated;

public abstract class Resource {

    protected static final ThreadLocal<SimpleDateFormat> dateTimeFormat
            = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        }
    };

    @ResourceField()
    public Date created_at;

    @ResourceField()
    public String href;

    public Map<String, String> hyperlinks;

    @ResourceField()
    public String id;

    @ResourceField(mutable=true)
    public Map<String, Object> links;

    @ResourceField(mutable=true)
    public Map<String, String> meta;

    @ResourceField()
    public Date updated_at;


    public Resource() {
    }

    public Resource(Map<String, Object> payload) throws HTTPError {
        this.constructFromResponse(payload);
    }

    public Resource(String href) throws HTTPError {
        Map<String, Object> payload = Balanced.getInstance().getClient().get(href);
        this.deserialize(payload);
    }

    public void save() throws HTTPError {
        Map<String, Object> request = serialize();
        Map<String, Object> response = null;
        if (id == null) {
            if (href == null)
                throw new RuntimeException(this.getClass().getName());
            response = Balanced.getInstance().getClient().post(href, request);
        }
        else {
            response = Balanced.getInstance().getClient().put(href, request);
        }
        deserialize(response);
    }

    public void unstore() throws NotCreated, HTTPError {
        delete();
    }

    public void delete() throws NotCreated, HTTPError {
        if (id == null)
            throw new NotCreated(this.getClass());
        Balanced.getInstance().getClient().delete(href);
    }

    public void reload() throws HTTPError {
        deserialize(Balanced.getInstance().getClient().get(href));
    }

    @Deprecated
    public void refresh() throws HTTPError {
        reload();
    }

    public Map<String, Object> serialize() {
        Map<String, Object> payload = new HashMap<String, Object>();
        Field[] fields = this.getClass().getFields();
        for(Field f : fields){
            if (!f.isAnnotationPresent(ResourceField.class)) {
                continue;
            }
            ResourceField rf = f.getAnnotation(ResourceField.class);
            if (!rf.mutable()) {
                continue;
            }
            String name = rf.field().equals("") ? f.getName() : rf.field();
            Object value;
            try {
                value = f.get(this);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            payload.put(name, value);
         }
        return payload;
    }

    public void constructFromResponse(Map<String, Object>payload) throws HTTPError{
        Field[] fields = this.getClass().getFields();
        for (Field f : fields) {
            if (!f.isAnnotationPresent(ResourceField.class)) {
                continue;
            }

            Object value = null;

            ResourceField rf = f.getAnnotation(ResourceField.class);
            String key = rf.field().equals("") ? f.getName() : rf.field();

            if (f.getName() == "source") {
                String foo = "bar";
            }

            if (key.contains(".")) {
                value = this.hyperlinks != null ? this.hyperlinks.get(key) : null;
            }
            else if (!rf.required() && !payload.containsKey(key)) {
                value = null;
            }
            else {
                value = payload.get(key);
            }

            if (f.getType() == Date.class) {
                value = deserializeDate((String) value);
            }
            else if (f.getType() == String[].class) {
                value = (((ArrayList<String>) value).toArray(new String[0]));
            }
            else if (f.getType() == Integer.class) {
                try {
                    value = ((Double) value).intValue();
                } catch (Exception e) {
                    value = value;
                }
            }
            else if (Resource.class.isAssignableFrom(f.getType())) {
                if (value != null) {
                    if (value instanceof String) {
                        value = Balanced.getInstance().getClient().get((String)value);
                    }
                    value = deserializeResource((Map<String, Object>)value, f.getType());
                }
            }
            else if (ResourceCollection.class.isAssignableFrom(f.getType())) {
                if (value != null) {
                    value = deserializeResourceCollection((String) value, f.getType());
                }
            }

            try {
                f.set(this, value);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void hydrate(Map<String, String> links, Map<String, String> meta, Map<String, Object> entity) {
        for (Map.Entry<String, String> link : links.entrySet()) {
            String key = link.getKey();
            String value = link.getValue();
            String expandedValue = null;
            if (value != null) {
                Pattern logEntry = Pattern.compile("\\{(.*?)\\}");
                Matcher matcher = logEntry.matcher(value);
                if (matcher.find()) {
                    String token = matcher.group(1);
                    String[]linkKey = token.split("\\.");
                    String linkVal = (String)entity.get(linkKey[1]);

                    // hack for "self" in events.callbacks link
                    if (linkKey[1].equals("self")) {
                        linkKey[1] = "id";
                    }

                    if (linkVal != null) {
                        expandedValue = value.replaceAll("\\{" + token + "\\}", linkVal);
                    }
                    else {
                        linkVal = ((Map<String, String>)entity.get("links")).get(linkKey[1]);
                        if (linkVal != null) {
                            expandedValue = value.replaceAll("\\{" + token + "\\}", linkVal);
                        }
                    }
                }
                else {
                    expandedValue = value;
                }
            }

            link.setValue(expandedValue);
        }
        this.hyperlinks = links;
    }

    public void deserialize(Map<String, Object> payload) throws HTTPError{
        Map<String, String> links = (Map<String, String>)payload.remove("links");
        Map<String, String> meta = (Map<String, String>)payload.remove("meta");

        if (payload.size() > 1) {
            throw new RuntimeException("Not supported yet");
        }

        for (Object key : payload.keySet()) {
            Map<String, Object> entity = (Map<String, Object>)((ArrayList)payload.get(key)).get(0);
            hydrate(links, meta, entity);
            constructFromResponse(entity);
        }
    }

    protected Date deserializeDate(String raw) {
        // http://stackoverflow.com/a/2132605/1339571
        if (raw == null) return null;
        raw = raw.substring(0, 23) + raw.substring(26, raw.length());
        try {
            return dateTimeFormat.get().parse(raw);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    protected Object deserializeResourceCollection(String raw, Class clazz) {
        Object value;

        Constructor<?> ctor;
        try {
            ctor = clazz.getConstructor(String.class);
        } catch (SecurityException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        try {
            value = ctor.newInstance(new Object[] { raw });
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }

        return value;
    }

    protected Resource deserializeResource(Map<String, Object> raw, Class clazz) throws HTTPError {
        Resource value;

        Constructor<?> ctor;
        try {
            ctor = clazz.getConstructor();
        } catch (SecurityException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        try {
            value = (Resource) ctor.newInstance(new Object[] { });
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        value.deserialize(raw);

        return value;
    }
}
TOP

Related Classes of com.balancedpayments.core.Resource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.