Java tutorial
/* * 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; } }