me.henrytao.observableorm.orm.ObservableModel.java Source code

Java tutorial

Introduction

Here is the source code for me.henrytao.observableorm.orm.ObservableModel.java

Source

/*
 * Copyright 2015 "Henry Tao <hi@henrytao.me>"
 *
 * Licensed 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 me.henrytao.observableorm.orm;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import me.henrytao.observableorm.util.JsonUtils;
import rx.Observable;

/**
 * Created by henrytao on 3/31/15.
 */
public abstract class ObservableModel<T extends ObservableModel> {

    protected abstract void setObservableAdapter(List<Class> adapter);

    public static enum ACTION {
        ADD, SAVE, SAVE_OR_ADD, REMOVE, CHANGE
    }

    public static Observable<Object> observe(Class observableModel, ACTION action) {
        // todo: trigger a subscription
        return null;
    }

    protected static final Map<Class, Deserializer> deserializerMap;

    protected static final Map<Class, Serializer> serializerMap;

    static {
        deserializerMap = new HashMap<>();
        deserializerMap.put(Date.class, new DateAdapter());

        serializerMap = new HashMap<>();
        serializerMap.put(Date.class, new DateAdapter());
    }

    public interface Fields {

        final String ID = "id";
    }

    @Column(name = Fields.ID)
    protected String mId;

    private List<Class> mListAdapterClass = new ArrayList<>();

    private List<ObservableAdapter> mListAdapter = new ArrayList<>();

    public ObservableModel() {
        setObservableAdapter(mListAdapterClass);
        for (Class adapterClass : mListAdapterClass) {
            // todo: need to think about handling exception
            try {
                mListAdapter.add((ObservableAdapter) adapterClass.newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    protected Field[] getDeclaredFields() {
        List<Field> fields = new ArrayList<Field>();
        fields.addAll(Arrays.asList(getClass().getDeclaredFields()));
        fields.addAll(Arrays.asList(getClass().getSuperclass().getDeclaredFields()));
        return fields.toArray(new Field[fields.size()]);
    }

    public Map<String, Object> serialize() throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = getDeclaredFields();
        for (Field f : fields) {
            if (!f.isAnnotationPresent(Column.class)) {
                continue;
            }
            Column column = f.getAnnotation(Column.class);
            if (!column.serialize()) {
                continue;
            }
            f.setAccessible(true);
            String name = column.name();
            Object value = f.get(this);
            Class type = f.getType();
            Serializer serializer = serializerMap.get(type);
            if (value == null) {
                continue;
            } else if (serializer != null) {
                map.put(name, serializer.serialize(value));
            } else if (ObservableModel.class.isAssignableFrom(type)) {
                // todo: need to test
                map.put(name, ((ObservableModel) value).serialize());
            } else {
                map.put(name, value);
            }
        }
        return map;
    }

    public T deserialize(Map<String, Object> map) throws IllegalAccessException {
        Field[] fields = getDeclaredFields();
        for (Field f : fields) {
            if (!f.isAnnotationPresent(Column.class)) {
                continue;
            }
            Column column = f.getAnnotation(Column.class);
            if (!column.deserialize()) {
                continue;
            }
            f.setAccessible(true);
            String name = column.name();
            Object value = map.get(name);
            Class type = f.getType();
            Deserializer deserializer = deserializerMap.get(type);
            if (deserializer != null) {
                f.set(this, deserializer.deserialize(value));
            } else if (boolean.class.isAssignableFrom(type)) {
                f.setBoolean(this, value == null ? false : (Boolean) value);
            } else if (double.class.isAssignableFrom(type)) {
                f.setDouble(this, value == null ? 0.0 : (Double) value);
            } else if (float.class.isAssignableFrom(type)) {
                f.setFloat(this, value == null ? 0f : (Float) value);
            } else if (int.class.isAssignableFrom(type)) {
                f.setInt(this, value == null ? 0 : (int) value);
            } else if (short.class.isAssignableFrom(type)) {
                f.setShort(this, value == null ? 0 : (short) value);
            } else if (byte.class.isAssignableFrom(type)) {
                f.setByte(this, value == null ? 0 : (byte) value);
            } else if (String.class.isAssignableFrom(type)) {
                f.set(this, value);
            } else if (JSONObject.class.isAssignableFrom(type)) {
                // todo: nested object should be another model
            }
        }
        return (T) this;
    }

    public T deserialize(String json) throws IllegalAccessException, JSONException {
        return deserialize(JsonUtils.decode(json));
    }

    public void add() throws IllegalAccessException {
        // todo: need to return observable list
        for (int i = 0; i < mListAdapter.size(); i++) {
            // todo: need to make sure mListAdapterClass & mListAdapter have the same size
            mListAdapter.get(i).add(mListAdapterClass.get(i), serialize());
        }
    }

    public void save() throws IllegalAccessException {
        // todo: need to return observable list
        for (int i = 0; i < mListAdapter.size(); i++) {
            // todo: need to make sure mListAdapterClass & mListAdapter have the same size
            mListAdapter.get(i).save(mListAdapterClass.get(i), serialize());
        }
    }

    public void saveOrAdd() throws IllegalAccessException {
        // todo: need to return observable list
        for (int i = 0; i < mListAdapter.size(); i++) {
            // todo: need to make sure mListAdapterClass & mListAdapter have the same size
            mListAdapter.get(i).saveOrAdd(mListAdapterClass.get(i), serialize());
        }
    }

    // todo: this is a demo for handling single apdater action
    protected void remove(Class observableAdapterClass) throws IllegalAccessException {
        // todo: need to make sure mListAdapterClass & mListAdapter have the same size
        int index = mListAdapterClass.indexOf(observableAdapterClass);
        if (index >= 0) {
            mListAdapter.get(index).remove(observableAdapterClass, serialize());
        }
    }

    public void remove() throws IllegalAccessException {
        // todo: need to return observable list
        for (Class observableAdapterClass : mListAdapterClass) {
            remove(observableAdapterClass);
        }
    }

    public String getId() {
        return mId;
    }

}