Java tutorial
/* * Copyright (C) 2014 8tory, Inc. * * 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 com.parse.simple; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.Collection; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.lang.reflect.Field; import com.parse.ParseObject; import com.parse.ParseQuery; import com.parse.ParseUser; import com.parse.ParseGeoPoint; import com.parse.ParseClassName; import com.parse.GetCallback; import com.parse.FindCallback; import com.parse.CountCallback; import com.parse.ParseException; import org.json.JSONObject; import java.util.Date; import android.text.TextUtils; import android.os.Bundle; public class SimpleParse { private Class<?> mKlass; private Object mFrom; private ParseObject mTo; private ParseQuery mQuery; private String mObjectId; private SimpleParse() { } public SimpleParse(Class<?> klass) { mKlass = klass; } public SimpleParse(Object object) { mFrom = object; mKlass = object.getClass(); } public static SimpleParse from(Class<?> klass) { return new SimpleParse(klass); } public static SimpleParse from(Object object) { return new SimpleParse(object); } public void saveInBackground() { saveInBackground(mFrom, mTo); } public void saveInBackground(Object object) { if (mFrom == null) { mFrom = object; } else { mTo = (ParseObject) object; } saveInBackground(mFrom, mTo); } public SimpleParse to(ParseObject to) { mTo = to; return this; } public static ParseObject commit(ParseObject from) { return commit(from, from); } public synchronized static ParseObject commit(Object from, ParseObject to) { for (Map.Entry<SimpleField, SimpleParseColumn> fieldEntry : SimpleParseCache.get() .getColumnFields(from.getClass()).entrySet()) { final SimpleField field = fieldEntry.getKey(); final SimpleParseColumn column = fieldEntry.getValue(); final String columnName = SimpleParseCache.get().getColumnName(field, column); if (TextUtils.isEmpty(columnName)) continue; Bundle icicle = SimpleParseCache.get().columnDataCache.get(columnName); if (icicle == null) { icicle = new Bundle(); SimpleParseCache.get().columnDataCache.put(columnName, icicle); } Class<?> fieldType = field.getType(); try { Object value = field.get(from); Class<? extends Filter> filter = column.filter(); if (!Optional.class.equals(column.saver())) { value = ((Value) SimpleParseCache.get().getObject(column.saver())).value(); } else if (NullValue.class.equals(column.saver())) { continue; } else if (!OptionalFilter.class.equals(filter)) { value = SimpleParseCache.get().getFilter(filter).onSave(value, icicle, from, to); } if (column.self() && fieldType.isAssignableFrom(ParseObject.class)) { // do nothing } else if (value == null) { to.put(columnName, JSONObject.NULL); //to.remove(columnName); } else if (fieldType.equals(Byte.class) || fieldType.equals(byte.class)) { to.put(columnName, (Byte) value); } else if (fieldType.equals(Short.class) || fieldType.equals(short.class)) { to.put(columnName, (Short) value); } else if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) { to.put(columnName, (Integer) value); } else if (fieldType.equals(Long.class) || fieldType.equals(long.class)) { to.put(columnName, (Long) value); } else if (fieldType.equals(Float.class) || fieldType.equals(float.class)) { to.put(columnName, (Float) value); } else if (fieldType.equals(Double.class) || fieldType.equals(double.class)) { to.put(columnName, (Double) value); } else if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) { to.put(columnName, (Boolean) value); } else if (fieldType.equals(Character.class) || fieldType.equals(char.class)) { to.put(columnName, value.toString()); } else if (fieldType.equals(String.class)) { String valueString = value.toString(); String prefix = column.prefix(); String suffix = column.suffix(); Class<?> prefixClass = column.prefixClass(); if (!Optional.class.equals(prefixClass)) { prefix = (String) ((Value) SimpleParseCache.get().getObject(prefixClass)).value(); } Class<?> suffixClass = column.suffixClass(); if (!Optional.class.equals(suffixClass)) { suffix = (String) ((Value) SimpleParseCache.get().getObject(suffixClass)).value(); } if (!TextUtils.isEmpty(prefix) && valueString.startsWith(prefix)) { //valueString.replace(prefix, ""); valueString = valueString.substring(prefix.length(), valueString.length()); } if (!TextUtils.isEmpty(suffix) && valueString.endsWith(suffix)) { valueString = valueString.substring(0, valueString.length() - suffix.length()); } if (SimpleParseObject.OBJECT_ID.equals(columnName)) { to.setObjectId(valueString); } else { to.put(columnName, valueString); } } else if (fieldType.equals(Byte[].class) || fieldType.equals(byte[].class)) { to.put(columnName, (byte[]) value); } else if (fieldType.equals(JSONObject.class)) { to.put(columnName, (JSONObject) value); } else if (fieldType.equals(List.class)) { to.addAll(columnName, (List) value); } else if (fieldType.equals(Date.class)) { to.put(columnName, (Date) value); } else if (fieldType.equals(ParseUser.class)) { to.put(columnName, (ParseUser) value); } else if (fieldType.equals(ParseGeoPoint.class)) { to.put(columnName, (ParseGeoPoint) value); } else if (fieldType.equals(ParseObject.class)) { to.put(columnName, (ParseObject) value); } //else if (ReflectionUtils.isSubclassOf(fieldType, Enum.class)) { //to.put(columnName, ((Enum<?>) value).name()); //} } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } SimpleParseCache.get().columnDataCache.clear(); return to; } public static <T> T load(ParseObject to) { return (T) load(to, to); } public synchronized static <T> T load(Class<T> from, ParseObject to) { String id = to.getObjectId(); T object = null; if (SimpleParseCache.get().parseObjectsCache.containsKey(id)) { object = (T) SimpleParseCache.get().parseObjectsCache.get(id); return object; } try { object = from.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } object = load(object, to); SimpleParseCache.get().parseObjectsCache.put(id, object); return object; } public synchronized static <T> T load(T from, ParseObject to) { for (Map.Entry<SimpleField, SimpleParseColumn> fieldEntry : SimpleParseCache.get() .getColumnFields(from.getClass()).entrySet()) { final SimpleField field = fieldEntry.getKey(); final SimpleParseColumn column = fieldEntry.getValue(); final String columnName = SimpleParseCache.get().getColumnName(field, column); if (TextUtils.isEmpty(columnName)) continue; Bundle icicle = SimpleParseCache.get().columnDataCache.get(columnName); if (icicle == null) { icicle = new Bundle(); SimpleParseCache.get().columnDataCache.put(columnName, icicle); } Class<?> fieldType = field.getType(); field.setAccessible(true); try { Class<? extends Filter> filterClass = column.filter(); Filter filter = null; if (!OptionalFilter.class.equals(filterClass)) { filter = SimpleParseCache.get().getFilter(column.filter()); } boolean filtered = false; Object saveValue = null; if (!Optional.class.equals(column.loader())) { filtered = true; saveValue = ((Value) SimpleParseCache.get().getObject(column.loader())).value(); } else if (NullValue.class.equals(column.loader())) { continue; } else if (filter != null) { Class<?> saveType = filter.getSaveType(); if (!saveType.equals(fieldType)) { filtered = true; if (column.self() && saveType.isAssignableFrom(ParseObject.class)) { saveValue = (ParseObject) to; saveValue = (ParseObject) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Byte.class) || saveType.equals(byte.class)) { saveValue = (byte) to.getInt(columnName); saveValue = (byte) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Short.class) || saveType.equals(short.class)) { saveValue = (short) to.getInt(columnName); saveValue = (short) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Integer.class) || saveType.equals(int.class)) { saveValue = to.getInt(columnName); saveValue = (int) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Long.class) || saveType.equals(long.class)) { saveValue = to.getLong(columnName); saveValue = (long) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Float.class) || saveType.equals(float.class)) { saveValue = (float) to.getDouble(columnName); saveValue = (float) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Double.class) || saveType.equals(double.class)) { saveValue = to.getDouble(columnName); saveValue = (double) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Boolean.class) || saveType.equals(boolean.class)) { saveValue = to.getBoolean(columnName); saveValue = (boolean) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Character.class) || saveType.equals(char.class)) { saveValue = to.getString(columnName); saveValue = (String) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(String.class)) { if (SimpleParseObject.OBJECT_ID.equals(columnName)) { saveValue = to.getObjectId(); } else { saveValue = to.getString(columnName); } saveValue = (String) filter.onLoad(saveValue, icicle, from, to); String prefix = column.prefix(); Class<?> prefixClass = column.prefixClass(); if (!Optional.class.equals(prefixClass)) { prefix = (String) ((Value) SimpleParseCache.get().getObject(prefixClass)).value(); } String suffix = column.suffix(); Class<?> suffixClass = column.suffixClass(); if (!Optional.class.equals(suffixClass)) { suffix = (String) ((Value) SimpleParseCache.get().getObject(suffixClass)).value(); } saveValue = prefix + saveValue + suffix; } else if (saveType.equals(Byte[].class) || saveType.equals(byte[].class)) { saveValue = to.getString(columnName); saveValue = (String) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(JSONObject.class)) { saveValue = to.getJSONObject(columnName); saveValue = (JSONObject) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(List.class)) { saveValue = to.getList(columnName); saveValue = (List) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(Date.class)) { saveValue = to.getDate(columnName); saveValue = (Date) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(ParseUser.class)) { saveValue = to.getParseUser(columnName); saveValue = (ParseUser) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(ParseGeoPoint.class)) { saveValue = to.getParseGeoPoint(columnName); saveValue = (ParseGeoPoint) filter.onLoad(saveValue, icicle, from, to); } else if (saveType.equals(ParseObject.class)) { saveValue = to.getParseObject(columnName); saveValue = (ParseObject) filter.onLoad(saveValue, icicle, from, to); } } } if (column.self() && fieldType.isAssignableFrom(ParseObject.class)) { ParseObject value = (ParseObject) (filtered ? saveValue : to); field.set(from, value); } else if (fieldType.equals(Byte.class) || fieldType.equals(byte.class)) { byte value = (byte) (filtered ? saveValue : to.getInt(columnName)); field.setByte(from, value); } else if (fieldType.equals(Short.class) || fieldType.equals(short.class)) { short value = (short) (filtered ? saveValue : to.getInt(columnName)); field.setShort(from, value); } else if (fieldType.equals(Integer.class) || fieldType.equals(int.class)) { int value = (int) (filtered ? saveValue : to.getInt(columnName)); field.setInt(from, value); } else if (fieldType.equals(Long.class) || fieldType.equals(long.class)) { long value = (long) (filtered ? saveValue : to.getLong(columnName)); field.setLong(from, value); } else if (fieldType.equals(Float.class) || fieldType.equals(float.class)) { float value = (float) (filtered ? saveValue : to.getDouble(columnName)); field.setFloat(from, value); } else if (fieldType.equals(Double.class) || fieldType.equals(double.class)) { double value = (double) (filtered ? saveValue : to.getDouble(columnName)); field.setDouble(from, value); } else if (fieldType.equals(Boolean.class) || fieldType.equals(boolean.class)) { boolean value = (boolean) (filtered ? saveValue : to.getBoolean(columnName)); field.setBoolean(from, value); } else if (fieldType.equals(Character.class) || fieldType.equals(char.class)) { String value = (String) (filtered ? saveValue : to.getString(columnName)); field.set(from, value); } else if (fieldType.equals(String.class)) { String value = null; if (filtered) { value = (String) saveValue; } else { if (SimpleParseObject.OBJECT_ID.equals(columnName)) { value = to.getObjectId(); } else { value = to.getString(columnName); } String prefix = column.prefix(); Class<?> prefixClass = column.prefixClass(); if (!Optional.class.equals(prefixClass)) { prefix = (String) ((Value) SimpleParseCache.get().getObject(prefixClass)).value(); } String suffix = column.suffix(); Class<?> suffixClass = column.suffixClass(); if (!Optional.class.equals(suffixClass)) { suffix = (String) ((Value) SimpleParseCache.get().getObject(suffixClass)).value(); } value = prefix + value + suffix; } field.set(from, value); } else if (fieldType.equals(Byte[].class) || fieldType.equals(byte[].class)) { String value = (String) (filtered ? saveValue : to.getString(columnName)); field.set(from, value); } else if (fieldType.equals(JSONObject.class)) { JSONObject value = (JSONObject) (filtered ? saveValue : to.getJSONObject(columnName)); field.set(from, value); } else if (fieldType.equals(List.class)) { List value = (List) (filtered ? saveValue : to.getList(columnName)); field.set(from, value); } else if (fieldType.equals(Date.class)) { Date value = (Date) (filtered ? saveValue : to.getDate(columnName)); field.set(from, value); } else if (fieldType.equals(ParseUser.class)) { ParseUser value = (ParseUser) (filtered ? saveValue : to.getParseUser(columnName)); field.set(from, value); } else if (fieldType.equals(ParseGeoPoint.class)) { ParseGeoPoint value = (ParseGeoPoint) (filtered ? saveValue : to.getParseGeoPoint(columnName)); field.set(from, value); } else if (fieldType.equals(ParseObject.class)) { ParseObject value = (ParseObject) (filtered ? saveValue : to.getParseObject(columnName)); field.set(from, value); } //else if (ReflectionUtils.isSubclassOf(fieldType, Enum.class)) { //to.put(columnName, ((Enum<?>) value).name()); //} } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } SimpleParseCache.get().columnDataCache.clear(); return from; } public void saveInBackground(Object from, ParseObject to) { if (to == null) { to = new ParseObject(SimpleParseCache.get().getClassName(mKlass)); } commit(from, to); to.saveInBackground(); } /* String objectId = gameScore.getObjectId(); Date updatedAt = gameScore.getUpdatedAt(); Date createdAt = gameScore.getCreatedAt(); */ // pinInBackground() // createWithoutData // fetchFromLocalDatastoreInBackground() // unpinInBackground() /* * gameScore.increment("score"); * gameScore.saveInBackground(); */ /* gameScore.addAllUnique("skills", Arrays.asList("flying", "kungfu")); * gameScore.saveInBackground(); */ // saveEventuall() /* public static void registerSubclass(Class<?> klass) { getClassName(klass); getColumnFields(klass); ParseObject.registerSubclass(klass); } */ // SimpleParseQuery.from(Profile.class).is("xWMyZ4YEGZ").query(new GetCallback<ParseUser>() {}); private Boolean mIsObjectId; public SimpleParse is(String objectId) { mObjectId = objectId; mIsObjectId = true; return this; } public SimpleParse isNot(String objectId) { mObjectId = objectId; mIsObjectId = false; return this; } public SimpleParse is(String key, Object value) { getQuery().whereEqualTo(key, value); return this; } public SimpleParse isNot(String key, Object value) { getQuery().whereNotEqualTo(key, value); return this; } public SimpleParse up(String key, Object value) { getQuery().whereGreaterThanOrEqualTo(key, value); return this; } public SimpleParse upOf(String key, Object value) { getQuery().whereGreaterThan(key, value); return this; } public SimpleParse down(String key, Object value) { getQuery().whereLessThanOrEqualTo(key, value); return this; } public SimpleParse downOf(String key, Object value) { getQuery().whereLessThan(key, value); return this; } public SimpleParse in(String key, List<Object> values) { getQuery().whereContainedIn(key, values); return this; } public SimpleParse notIn(String key, List<Object> values) { getQuery().whereNotContainedIn(key, values); return this; } public SimpleParse has(String key) { getQuery().whereExists(key); return this; } public SimpleParse hasNot(String key) { getQuery().whereDoesNotExist(key); return this; } public SimpleParse in(String key, String value, ParseQuery<? extends ParseObject> query) { getQuery().whereMatchesKeyInQuery(key, value, query); return this; } public SimpleParse in(String key, String value, SimpleParse simpleParseObject) { in(key, value, simpleParseObject.getQuery()); return this; } public SimpleParse notIn(String key, String value, ParseQuery<? extends ParseObject> query) { getQuery().whereDoesNotMatchKeyInQuery(key, value, query); return this; } public SimpleParse notIn(String key, String value, SimpleParse simpleParseObject) { in(key, value, simpleParseObject.getQuery()); return this; } public SimpleParse keys(List<String> keys) { getQuery().selectKeys(keys); return this; } /* public SimpleParse keys(String... keys) { keys(keys); return this; } */ public SimpleParse hasAll(String key, List<Object> values) { getQuery().whereContainsAll(key, values); return this; } public SimpleParse starts(String key, String value) { getQuery().whereStartsWith(key, value); return this; } public SimpleParse matches(String key, ParseQuery<? extends ParseObject> query) { getQuery().whereMatchesQuery(key, query); return this; } public SimpleParse matches(String key, SimpleParse simpleParseObject) { matches(key, simpleParseObject.getQuery()); return this; } public SimpleParse notMatches(String key, ParseQuery<? extends ParseObject> query) { getQuery().whereDoesNotMatchQuery(key, query); return this; } public SimpleParse notMatches(String key, SimpleParse simpleParseObject) { notMatches(key, simpleParseObject.getQuery()); return this; } public SimpleParse descending(String key) { getQuery().orderByDescending(key); return this; } public SimpleParse ascending(String key) { getQuery().orderByAscending(key); return this; } public SimpleParse addDescending(String key) { getQuery().addDescendingOrder(key); return this; } public SimpleParse addAscending(String key) { getQuery().addAscendingOrder(key); return this; } public SimpleParse skip(int size) { getQuery().setSkip(size); return this; } public SimpleParse limit(int size) { getQuery().setLimit(size); return this; } public SimpleParse include(String key) { getQuery().include(key); return this; } public SimpleParse local() { getQuery().fromLocalDatastore(); return this; } // unpinAllInBackground // pinAllInBackground public SimpleParse cachePolicy(ParseQuery.CachePolicy policy) { // extends Enum<ParseQuery.CachePolicy> getQuery().setCachePolicy(policy); return this; } /* public boolean hasCachedResult() { return getQuery().hasCachedResult(); } public boolean clearCachedResult() { return getQuery().clearCachedResult(); } */ public <T extends ParseObject> ParseQuery<T> getQuery() { if (!(mKlass.isAssignableFrom(ParseObject.class))) { return null; } Class<? extends ParseObject> klass = (Class<? extends ParseObject>) mKlass; if (mQuery == null) { mQuery = ParseQuery.getQuery(klass); } return mQuery; } public static <T extends ParseObject> ParseQuery<T> getQuery(Class<T> klass) { return from(klass).getQuery(); } private void get(GetCallback<ParseObject> getCallback) { if (mIsObjectId != null) { getQuery().getInBackground(mObjectId, getCallback); } } private void findInBackground(FindCallback<ParseObject> findCallback) { find(findCallback); } private void find(FindCallback<ParseObject> findCallback) { getQuery().findInBackground(findCallback); } private void find() { try { getQuery().find(); } catch (ParseException e) { } } private void count(CountCallback countCallback) { getQuery().countInBackground(countCallback); } }