/* * @copyright 2013 Philip Warner * @license GNU General Public License * * This file is part of Book Catalogue. * * Book Catalogue is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Book Catalogue is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>. */ package com.eleybourn.bookcatalogue.datamanager; import java.io.Serializable; import android.os.Bundle; import com.eleybourn.bookcatalogue.utils.Utils; /** * Class to manage storage and retrieval of a piece of data from a bundle as well as * ancillary details such as visibility. * * @author pjw */ public class Datum { /** True if data should be visible */ private boolean mIsVisible = true; /** Validator for this Datum */ private DataValidator mValidator = null; /** Accessor for this Datum (eg. the datum might be a bit in a mask field, or a composite read-only value */ private DataAccessor mAccessor = null; /** Key of this datum */ private final String mKey; /** * Constructor * * @param key Key of this datum * @param validator Validator for this Datum * @param visible True if data should be visible */ public Datum(String key, DataValidator validator, boolean visible) { mKey = key; mValidator = validator; mIsVisible = visible; } /** Accessor */ public String getKey() { return mKey; } /** Accessor */ public boolean isVisible() { return mIsVisible; } /** Accessor */ public Datum setVisible(boolean isVisible) { mIsVisible = isVisible; return this; } /** Accessor */ public DataValidator getValidator() { return mValidator; } /** Accessor */ public boolean hasValidator() { return mValidator != null; } /** * Accessor. Protected against being set twice. */ public Datum setValidator(DataValidator validator) { if (mValidator != null && validator != mValidator) throw new RuntimeException("Datum '" + mKey + "' already has a validator"); mValidator = validator; return this; } /** Accessor */ public DataAccessor getAccessor() { return mAccessor; } /** * Accessor. Protected against being set twice. */ public Datum setAccessor(DataAccessor accessor) { if (mAccessor != null && accessor != mAccessor) throw new RuntimeException("Datum '" + mKey + "' already has an Accessor"); mAccessor = accessor; return this; } /** * Get the raw Object for this Datum * * @param data Parent DataManager * @param bundle Raw data bundle * * @return The object data */ public Object get(DataManager data, Bundle bundle) { if (mAccessor == null) { return bundle.get(mKey); } else { return mAccessor.get(data, this, bundle); } } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public boolean getBoolean(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.getBoolean(mKey); } else { o = mAccessor.get(data, this, bundle); } try { return (Boolean) o; } catch (ClassCastException e) { return Utils.objectToBoolean(o); } } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putBoolean(DataManager data, Bundle bundle, boolean value) { if (mAccessor == null) { bundle.putBoolean(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public int getInt(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.get(mKey); } else { o = mAccessor.get(data, this, bundle); } return (int) objectToLong(o); } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putInt(DataManager data, Bundle bundle, int value) { if (mAccessor == null) { bundle.putInt(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public long getLong(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.get(mKey); } else { o = mAccessor.get(data, this, bundle); } return objectToLong(o); } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putLong(DataManager data, Bundle bundle, long value) { if (mAccessor == null) { bundle.putLong(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public double getDouble(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.get(mKey); } else { o = mAccessor.get(data, this, bundle); } return objectToDouble(o); } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putDouble(DataManager data, Bundle bundle, double value) { if (mAccessor == null) { bundle.putDouble(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public float getFloat(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.get(mKey); } else { o = mAccessor.get(data, this, bundle); } return (float) objectToDouble(o); } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putFloat(DataManager data, Bundle bundle, float value) { if (mAccessor == null) { bundle.putFloat(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Retrieve the data from the DataManager, translating and using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return Value of the data */ public String getString(DataManager data, Bundle bundle) { Object o; if (mAccessor == null) { o = bundle.get(mKey); } else { o = mAccessor.get(data, this, bundle); } return objectToString(o); } /** * Store the data in the DataManager, using Accessor as necessary. * * @param data Parent collection * @param bundle Raw data * * @return This Datum, for chaining */ public Datum putString(DataManager data, Bundle bundle, String value) { if (mAccessor == null) { bundle.putString(mKey, value); } else { mAccessor.set(data, this, bundle, value); } return this; } /** * Get the serializable object from the collection. * We currently do not use a Datum for special access. * TODO: Consider how to use an accessor * * @param data Parent DataManager * @param bundle Raw data Bundle * * @return The data */ public Serializable getSerializable(DataManager data, Bundle bundle) { if (mAccessor == null) { return bundle.getSerializable(mKey); } else { throw new RuntimeException("Accessor not supported for serializable objects"); } } /** * Set the serializable object in the collection. * We currently do not use a Datum for special access. * TODO: Consider how to use an accessor * * @param data Parent DataManager * @param bundle Raw data Bundle * @param value The serializable object * * @return The data manager for chaining */ public Datum putSerializable(DataManager data, Bundle bundle, Serializable value) { if (mAccessor == null) { bundle.putSerializable(mKey, value); } else { throw new RuntimeException("Accessor not supported for serializable objects"); } return this; } /** * Translate the passed object to a String value * * @param o Object * * @return Resulting value */ public static String objectToString(Object o) { if (o == null) return ""; try { return (String) o; } catch (ClassCastException e) { return o.toString(); } } /** * Translate the passed object to a Long value * * @param o Object * * @return Resulting value */ public static long objectToLong(Object o) { if (o == null) return 0; try { return (Long) o; } catch (ClassCastException e) { final String s = o.toString(); if (s.equals("")) return 0; else try { return Long.parseLong(s); }catch (NumberFormatException e1) { if ( Utils.objectToBoolean(o) ) { return 1; } else { return 0; } } } } /** * Translate the passed object to a Double value * * @param o Object * * @return Resulting value */ public static double objectToDouble(Object o) { if (o == null) return 0; try { return (Double) o; } catch (ClassCastException e) { final String s = o.toString(); if (s.equals("")) return 0; else return Double.parseDouble(s); } } }