Source code

KittyORM custom mapping implementation example
  1. Click to view model field annotation example:
     1// Saving to text
     2@KITTY_COLUMN(
     3        columnOrder = 18,
     4        columnAffinity = TypeAffinities.TEXT
     5)
     6@KITTY_COLUMN_SERIALIZATION
     7public AnimalSounds stringSDF;
     8
     9// Saving to blob
    10@KITTY_COLUMN(
    11        columnOrder = 20,
    12        columnAffinity = TypeAffinities.BLOB
    13)
    14@KITTY_COLUMN_SERIALIZATION
    15public Bitmap byteArraySDF;

  2. Click to serialization\deserialization methods implementation examples:
     1String stringSDFSerialize() {
     2    if(stringSDF == null) return null;
     3    return new GsonBuilder().create().toJson(stringSDF);
     4}
     5
     6AnimalSounds stringSDFDeserialize(String cvData) {
     7    if(cvData == null) return null;
     8    if(cvData.length() == 0) return null;
     9    return new GsonBuilder().create().fromJson(cvData, AnimalSounds.class);
    10}
    11
    12public byte[] byteArraySDFSerialize() {//byteArraySDFSerialize
    13    if(byteArraySDF == null) return null;
    14    ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
    15    byteArraySDF.compress(Bitmap.CompressFormat.PNG, 100, bmpStream);
    16    return bmpStream.toByteArray();
    17}
    18
    19public Bitmap byteArraySDFDeserialize(byte[] cursorData) {
    20    if(cursorData == null) return null;
    21    if(cursorData.length == 0) return null;
    22    return BitmapFactory.decodeByteArray(cursorData, 0, cursorData.length);
    23}

KittyORM basic_datase implementation sources
  1. Click to view BasicDatabase.class:
     1@KITTY_DATABASE(
     2        databaseName = "basic_database",
     3        domainPackageNames = {"net.akaish.kittyormdemo.sqlite.basicdb"},
     4        logTag = LOG_TAG,
     5        isLoggingOn = true,
     6        isProductionOn = true,
     7        isPragmaOn = true
     8)
     9@KITTY_DATABASE_REGISTRY(
    10        domainPairs = {
    11                @KITTY_REGISTRY_PAIR(model = ComplexRandomModel.class, mapper = ComplexRandomMapper.class),
    12                @KITTY_REGISTRY_PAIR(model = IndexesAndConstraintsModel.class),
    13                @KITTY_REGISTRY_PAIR(model = RandomModel.class, mapper = RandomMapper.class)
    14        }
    15)
    16public class BasicDatabase extends KittyDatabase {
    17
    18    public static final String LOG_TAG = "BASIC DB DEMO";
    19
    20    /**
    21     * KittyORM main database class that represents bootstrap and holder for all related with database
    22     * components.
    23     * <br> See {@link KittyDatabase#KittyDatabase(Context, String)} for more info.
    24     *
    25     * @param ctx
    26     */
    27    public BasicDatabase(Context ctx) {
    28        super(ctx);
    29    }
    30
    31}

  2. Click to view AbstractRandomModel.class:
     1public abstract class AbstractRandomModel extends KittyModel {
     2
     3    public static final String RND_INTEGER_CNAME = "rnd_int_custom_column_name";
     4    public static final String RND_ANIMAL_CNAME = "rndanimal";
     5
     6    @KITTY_COLUMN(
     7            isIPK = true,
     8            columnOrder = 0
     9    )
    10    public Long id;
    11
    12    @KITTY_COLUMN(
    13            columnOrder = 1
    14    )
    15    public int randomInt;
    16
    17    @KITTY_COLUMN(
    18            columnOrder = 2,
    19            columnName = RND_INTEGER_CNAME
    20    )
    21    public Integer randomInteger;
    22
    23    @KITTY_COLUMN(
    24            columnOrder = 3,
    25            columnName = RND_ANIMAL_CNAME
    26    )
    27    public Animals randomAnimal;
    28
    29    @KITTY_COLUMN(
    30            columnOrder = 4,
    31            columnAffinity = TypeAffinities.TEXT
    32    )
    33    public String randomAnimalName;
    34}

  3. Click to view ComplexRandomModel.class:
      1@KITTY_TABLE
      2@KITTY_EXTENDED_CRUD(extendedCrudController = ComplexRandomMapper.class)
      3public class ComplexRandomModel extends AbstractRandomModel {
      4
      5    public ComplexRandomModel() {
      6        super();
      7    }
      8
      9
     10    // Primitives
     11    // (boolean, int, byte, double, long, short, float)
     12    @KITTY_COLUMN(columnOrder = 5)
     13    public boolean boolF;
     14
     15
     16    @KITTY_COLUMN(columnOrder = 6)
     17    public byte byteF;
     18
     19    @KITTY_COLUMN(columnOrder = 7)
     20    public double doubleF;
     21
     22    @KITTY_COLUMN(columnOrder = 8)
     23    public long longF;
     24
     25    @KITTY_COLUMN(columnOrder = 9)
     26    public short shortF;
     27
     28    @KITTY_COLUMN(columnOrder = 10)
     29    public float floatF;
     30
     31    // Byte array
     32    @KITTY_COLUMN(columnOrder = 11)
     33    public byte[] byteArray;
     34
     35    // String (TEXT) (String, BigDecimal, BigInteger, Enum)
     36    @KITTY_COLUMN(columnOrder = 12)
     37    public String stringF;
     38
     39    @KITTY_COLUMN(columnOrder = 13)
     40    public BigDecimal bigDecimalF;
     41
     42    @KITTY_COLUMN(columnOrder = 14)
     43    public BigInteger bigIntegerF;
     44
     45    @KITTY_COLUMN(columnOrder = 15)
     46    public Uri uriF;
     47
     48    @KITTY_COLUMN(columnOrder = 16)
     49    public File fileF;
     50
     51    @KITTY_COLUMN(columnOrder = 17)
     52    public Currency currencyF;
     53
     54    // SD
     55    @KITTY_COLUMN(
     56            columnOrder = 18,
     57            columnAffinity = TypeAffinities.TEXT
     58    )
     59    @KITTY_COLUMN_SERIALIZATION
     60    public AnimalSounds stringSDF;
     61
     62    @KITTY_COLUMN(columnOrder = 19)
     63    public SomeColours bitmapColour;
     64
     65    @KITTY_COLUMN(
     66            columnOrder = 20,
     67            columnAffinity = TypeAffinities.BLOB
     68    )
     69    @KITTY_COLUMN_SERIALIZATION
     70    public Bitmap byteArraySDF;
     71
     72    String stringSDFSerialize() {
     73        if(stringSDF == null) return null;
     74        return new GsonBuilder().create().toJson(stringSDF);
     75    }
     76
     77    AnimalSounds stringSDFDeserialize(String cvData) {
     78        if(cvData == null) return null;
     79        if(cvData.length() == 0) return null;
     80        return new GsonBuilder().create().fromJson(cvData, AnimalSounds.class);
     81    }
     82
     83    public byte[] byteArraySDFSerialize() {//byteArraySDFSerialize
     84        if(byteArraySDF == null) return null;
     85        ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
     86        byteArraySDF.compress(Bitmap.CompressFormat.PNG, 100, bmpStream);
     87        return bmpStream.toByteArray();
     88    }
     89
     90    public Bitmap byteArraySDFDeserialize(byte[] cursorData) {
     91        if(cursorData == null) return null;
     92        if(cursorData.length == 0) return null;
     93        return BitmapFactory.decodeByteArray(cursorData, 0, cursorData.length);
     94    }
     95
     96    // Primitive wrappers Boolean, Integer, Byte, Double, Short or Float
     97    @KITTY_COLUMN(columnOrder = 21)
     98    public Boolean boolFF;
     99
    100
    101    @KITTY_COLUMN(columnOrder = 22)
    102    public Byte byteFF;
    103
    104    @KITTY_COLUMN(columnOrder = 23)
    105    public Double doubleFF;
    106
    107    @KITTY_COLUMN(columnOrder = 24)
    108    public Short shortFF;
    109
    110    @KITTY_COLUMN(columnOrder = 25)
    111    public Float floatFF;
    112
    113
    114    // Long represented types Long, Date, Calendar, Timestamp
    115    @KITTY_COLUMN(columnOrder = 26)
    116    public Long longFF;
    117
    118    @KITTY_COLUMN(columnOrder = 27)
    119    public Date dateF;
    120
    121    @KITTY_COLUMN(columnOrder = 28)
    122    public Calendar calendarF;
    123
    124    @KITTY_COLUMN(columnOrder = 29)
    125    public Timestamp timestampF;
    126
    127    @Override
    128    public String toString() {
    129        StringBuffer out = new StringBuffer(256);
    130        out.append("Long id : "+id+"\r\n");
    131        out.append("int randomInt : "+randomInt+"\r\n");
    132        out.append("String stringF : "+stringF+"\r\n");
    133        out.append("BigInteger bigIntegerF : "+bigIntegerF+"\r\n");
    134        out.append("SomeColours bitmapColour : "+bitmapColour+"\r\n");
    135        out.append("Short shortFF : "+shortFF+"\r\n");
    136        out.append("Timestamp timestampF (HReadable) : "+timestampF+"\r\n");
    137        out.append("AnimalSounds stringSDF (HReadable) : "+stringSDFSerialize()+"\r\n");
    138        out.append("Uri uriF : " + uriF+"\r\n");
    139        out.append("Currency currencyF : " + currencyF.getSymbol()+"\r\n");
    140        out.append("... \r\n");
    141        return out.toString();
    142    }
    143
    144    public String toShortString() {
    145        StringBuffer out = new StringBuffer(256);
    146        out.append("[ Long id : "+id+"; ");
    147        out.append("int randomInt : "+randomInt+"; ");
    148        out.append("String stringF : "+stringF+"; ");
    149        out.append("BigInteger bigIntegerF : "+bigIntegerF+"; ");
    150        out.append("SomeColours bitmapColour : "+bitmapColour+"; ");
    151        out.append("Short shortFF : "+shortFF+"; ");
    152        out.append("Timestamp timestampF (HReadable) : "+timestampF+"; ... ]");
    153        return out.toString();
    154    }
    155
    156    @Deprecated
    157    public String toHTMLString() {
    158        StringBuffer out = new StringBuffer(2048);
    159        out.append("<br>Long id : "+id.toString()+"\r\n");
    160        out.append("<br><b>PRIMITIVES</b>"+"\r\n");
    161        out.append("<br>boolean boolF : "+Boolean.toString(boolF)+"\r\n");
    162        out.append("<br>int randomInt : "+Integer.toString(randomInt)+"\r\n");
    163        out.append("<br>byte byteF : "+Byte.toString(byteF)+"\r\n");
    164        out.append("<br>double doubleF : "+Double.toString(doubleF)+"\r\n");
    165        out.append("<br>long longF : "+Long.toString(longF)+"\r\n");
    166        out.append("<br>short shortF : "+Short.toString(shortF)+"\r\n");
    167        out.append("<br>float floatF : "+Float.toString(floatF)+"\r\n");
    168        out.append("<br>byte[] byteArray : "+byteArrayToString(byteArray)+"\r\n");
    169        out.append("<br><b>STRING AFFINITIES</b>"+"\r\n");
    170        out.append("<br>String randomAnimalName : "+randomAnimalName+"\r\n");
    171        out.append("<br>String stringF : "+stringF+"\r\n");
    172        out.append("<br>BigDecimal bigDecimalF : "+bigDecimalF.toEngineeringString()+"\r\n");
    173        out.append("<br>BigInteger bigIntegerF : "+bigIntegerF.toString()+"\r\n");
    174        out.append("<br>Animals randomAnimal : "+randomAnimal.toString()+"\r\n");
    175        out.append("<br><b>SERIALIZATION AND DESERIALIZATION</b>"+"\r\n");
    176        out.append("<br>AnimalSounds stringSDF : "+stringSDFSerialize()+"\r\n");
    177        out.append("<br>SomeColours bitmapColour : "+bitmapColour.toString()+"\r\n");
    178        out.append("<br><b>PRIMITIVE WRAPPERS</b>"+"\r\n");
    179        out.append("<br>Boolean boolFF : "+boolFF.toString()+"\r\n");
    180        out.append("<br>Integer randomInteger : "+randomInteger.toString()+"\r\n");
    181        out.append("<br>Byte byteFF : "+byteFF.toString()+"\r\n");
    182        out.append("<br>Double doubleFF : "+doubleFF.toString()+"\r\n");
    183        out.append("<br>Short shortFF : "+shortFF.toString()+"\r\n");
    184        out.append("<br>Float floatFF :"+floatFF.toString()+"\r\n");
    185        out.append("<br><b>LONG REPRESENTED TYPES</b>"+"\r\n");
    186        out.append("<br>Long longFF : "+longFF.toString()+"\r\n");
    187        out.append("<br>Date dateF : "+Long.toString(dateF.getTime())+"\r\n");
    188        out.append("<br>Calendar calendarF : "+Long.toString(calendarF.getTimeInMillis())+"\r\n");
    189        out.append("<br>Timestamp timestampF : "+Long.toString(timestampF.getTime())+"\r\n");
    190        out.append("<br>Date dateF (HReadable) : "+dateF.toString()+"\r\n");
    191        out.append("<br>Calendar calendarF (HReadable) : "+calendarF.getTime().toString()+"\r\n");
    192        out.append("<br>Timestamp timestampF (HReadable) : "+timestampF.toString()+"\r\n");
    193        return out.toString();
    194    }
    195
    196    public String byteArrayToString(byte[] toString) {
    197        String[] strings = new String[toString.length];
    198        for(int i = 0; i < toString.length; i++) {
    199            strings[i] = Byte.toString(toString[i]);
    200        }
    201        return KittyUtils.implodeWithCommaInBKT(strings);
    202    }
    203}

  4. Click to view ComplexRandomMapper.class:
    1public class ComplexRandomMapper extends KittyMapper {
    2
    3    public <M extends KittyModel> ComplexRandomMapper(KittyTableConfiguration tableConfiguration, M blankModelInstance, String databasePassword) {
    4        super(tableConfiguration, blankModelInstance, databasePassword);
    5    }
    6
    7}

Fragment and utility code used in this tutorial
  1. Click to view RNDComplexRandomModelFactory.class:
     1public class RNDComplexRandomModelFactory {
     2
     3    private final Random randomizer;
     4
     5    private final SparseArray<String> randomAnimalSays = new SparseArray<>();
     6    private final SparseArray<String> randomAnimalLocalizedName = new SparseArray<>();
     7
     8    private final Context context;
     9
    10    private final static String[] ISO4217_EXAMPLE_CODES = {"USD", "GBP", "EUR", "CNY", "JPY", "MYR", "AUD", "HKD", "PHP"}; // "KOR" currency code not present at 4.4
    11    private final static String[] URI_EXAMPLES = {"http://example.com", "file:///usr/somefile", "http://example.org"};
    12    private final static String[] FILE_EXAPLES = {"/file/one", "/file/two/some.txt", "/file/three/sys.iso"};
    13
    14    public RNDComplexRandomModelFactory(Context context) {
    15        super();
    16        this.context = context;
    17
    18        this.randomizer = new Random();
    19
    20        // Lol, getContext().getString() method is fucking slow, calling for each new random model this method twice causes 55% of all execution time of generating new random model (!)
    21        // Right now getting those string causes only 14% of execution time
    22        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.BEAR), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.BEAR)));
    23        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.CAT), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.CAT)));
    24        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.DOG), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.DOG)));
    25        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.GOAT), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.GOAT)));
    26        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.LION), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.LION)));
    27        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.SHEEP), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.SHEEP)));
    28        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.TIGER), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.TIGER)));
    29        randomAnimalSays.append(Animals.getLocalizedAnimalSaysResource(Animals.WOLF), context.getString(Animals.getLocalizedAnimalSaysResource(Animals.WOLF)));
    30
    31
    32        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.BEAR), context.getString(Animals.getLocalizedAnimalNameResource(Animals.BEAR)));
    33        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.CAT), context.getString(Animals.getLocalizedAnimalNameResource(Animals.CAT)));
    34        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.DOG), context.getString(Animals.getLocalizedAnimalNameResource(Animals.DOG)));
    35        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.GOAT), context.getString(Animals.getLocalizedAnimalNameResource(Animals.GOAT)));
    36        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.LION), context.getString(Animals.getLocalizedAnimalNameResource(Animals.LION)));
    37        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.SHEEP), context.getString(Animals.getLocalizedAnimalNameResource(Animals.SHEEP)));
    38        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.TIGER), context.getString(Animals.getLocalizedAnimalNameResource(Animals.TIGER)));
    39        randomAnimalLocalizedName.append(Animals.getLocalizedAnimalNameResource(Animals.WOLF), context.getString(Animals.getLocalizedAnimalNameResource(Animals.WOLF)));
    40    }
    41
    42    public ComplexRandomModel newComplexRandomModel() {
    43        ComplexRandomModel model = new ComplexRandomModel();
    44
    45        model.boolF = randomizer.nextBoolean();
    46        model.randomInt = randomizer.nextInt();
    47        model.byteF = (byte) randomizer.nextInt(128);
    48        model.doubleF = randomizer.nextDouble();
    49        model.longF = randomizer.nextLong();
    50        model.shortF = (short) randomizer.nextInt(1000);
    51        model.floatF = randomizer.nextFloat();
    52        model.byteArray = new byte[8];
    53        randomizer.nextBytes(model.byteArray);
    54
    55        StringBuffer rndStrBuffer = new StringBuffer(8);
    56        for(int i = 0; i < model.byteArray.length; i++) {
    57            rndStrBuffer.append((char) model.byteArray[i]);
    58        }
    59        model.stringF = rndStrBuffer.toString();
    60        model.bigDecimalF = new BigDecimal(randomizer.nextDouble());
    61        model.bigIntegerF = BigInteger.valueOf(randomizer.nextLong());
    62        model.randomAnimal = Animals.rndAnimal(randomizer);
    63        model.uriF = Uri.parse(URI_EXAMPLES[randomizer.nextInt(URI_EXAMPLES.length)]);
    64        model.fileF = new File(FILE_EXAPLES[randomizer.nextInt(FILE_EXAPLES.length)]);
    65        model.currencyF = Currency.getInstance(ISO4217_EXAMPLE_CODES[randomizer.nextInt(ISO4217_EXAMPLE_CODES.length)]);
    66
    67        AnimalSounds animalSounds = new AnimalSounds();
    68        animalSounds.animalName = randomAnimalLocalizedName.get(Animals.getLocalizedAnimalNameResource(model.randomAnimal));
    69        animalSounds.animalSounds = randomAnimalSays.get(Animals.getLocalizedAnimalSaysResource(model.randomAnimal));
    70        model.stringSDF = animalSounds;
    71
    72        model.bitmapColour = SomeColours.rndColour(randomizer);
    73        model.byteArraySDF = SomeColours.getSomeColourBitmpap(
    74                SomeColours.getSomeColoursBitmapResource(model.bitmapColour), context
    75        );
    76
    77        model.boolFF = Boolean.valueOf(randomizer.nextBoolean());
    78        model.randomInteger = Integer.valueOf(randomizer.nextInt());
    79        model.randomAnimalName = context.getString(Animals.getLocalizedAnimalNameResource(model.randomAnimal));
    80        model.byteFF = Byte.valueOf((byte) randomizer.nextInt(128));
    81        model.doubleFF = Double.valueOf(randomizer.nextDouble());
    82        model.shortFF = new Short((short) randomizer.nextInt(10000));
    83        model.floatFF = Float.valueOf(randomizer.nextFloat());
    84
    85        model.longFF = currentTimeMillis();
    86        model.dateF = new Date(model.longFF);
    87        model.calendarF = Calendar.getInstance();
    88        model.calendarF.setTimeInMillis(model.longFF);
    89        model.timestampF = new Timestamp(model.longFF);
    90
    91        return model;
    92    }
    93}

  2. Click to view Lesson3Tab1DatatypesAffinities.class:
      1public class Lesson3Tab1DatatypesAffinities extends Lesson3BaseFragment {
      2
      3    private BasicDatabase database;
      4
      5    public Lesson3Tab1DatatypesAffinities() {}
      6
      7    private Button insertRandomButton;
      8    private Button clearTableButton;
      9    private ListView eventsListView;
     10
     11    @Override
     12    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     13        View rootView = inflater.inflate(R.layout.lesson3_tab1_datatype_affinities, container, false);
     14
     15        insertRandomButton = rootView.findViewById(R.id.l3_t1_go_button);
     16        clearTableButton = rootView.findViewById(R.id.l3_t1_clear_button);
     17
     18        eventsListView = rootView.findViewById(R.id.l3_t1_actions);
     19
     20        insertRandomButton.setOnClickListener(new View.OnClickListener() {
     21            @Override
     22            public void onClick(View v) {
     23                insert25RND();
     24            }
     25        });
     26
     27        clearTableButton.setOnClickListener(new View.OnClickListener() {
     28            @Override
     29            public void onClick(View v) {
     30                clearTable();
     31            }
     32        });
     33
     34        setUpExpandedList(
     35                rootView,
     36                R.id._l3_t1_expanded_panel_list,
     37                R.id._l3_t1_expanded_panel_text,
     38                R.string._l3_t1_expanded_text_pattern
     39        );
     40
     41        reloadTableExpandedList();
     42        return rootView;
     43    }
     44
     45    private BasicDatabase getDatabase() {
     46        if(database != null) return database;
     47        database = new BasicDatabase(getContext());
     48        return database;
     49    }
     50
     51    ComplexRandomModelDTAAdapter complexExpandedAdapter;
     52
     53    @Override
     54    protected void setUpExpandedList(View rootView, int eventsId, int eventsTitleId, int eventTitleStringPattern) {
     55        events = (ListView) rootView.findViewById(eventsId);
     56        expandedTitle = (TextView) rootView.findViewById(eventsTitleId);
     57        expandeddTitlePattern = getString(eventTitleStringPattern);
     58
     59        expandedTitle.setText(format(expandeddTitlePattern, 0));
     60
     61        if(expandedAdapter == null) {
     62            complexExpandedAdapter = new ComplexRandomModelDTAAdapter(getContext(), new LinkedList<ComplexRandomModel>());
     63        }
     64
     65        events.setAdapter(complexExpandedAdapter);
     66        events.setOnTouchListener(new View.OnTouchListener() {
     67
     68            // Setting on Touch Listener for handling the touch inside ScrollView
     69            @Override
     70            public boolean onTouch(View v, MotionEvent event) {
     71                // Disallow the touch request for parent scroll on touch of child view
     72                v.getParent().requestDisallowInterceptTouchEvent(true);
     73                return false;
     74            }
     75        });
     76    }
     77
     78    @Override
     79    public void onVisible() {
     80        reloadTableExpandedList();
     81    }
     82
     83    private void insert25RND() {
     84        new InsertRandomAsync().execute(0l);
     85    }
     86
     87    private void clearTable() {
     88        new WipeAsync().execute(0l);
     89    }
     90
     91    private void reloadTableExpandedList() {
     92        new ReloadTableAsync().execute(0l);
     93    }
     94
     95    @Override
     96    protected int snackbarMessageResource() {
     97        return R.string._l3_t1_snackbar_message;
     98    }
     99
    100
    101    // Asyncs
    102
    103    class ReloadTableAsync extends AsyncTask<Long, Long, List<ComplexRandomModel>> {
    104
    105        @Override
    106        protected List<ComplexRandomModel> doInBackground(Long... params) {
    107            ComplexRandomMapper mapper = (ComplexRandomMapper) Lesson3Tab1DatatypesAffinities.this.getDatabase().getMapper(ComplexRandomModel.class);
    108            List<ComplexRandomModel> out = mapper.findAll();
    109            mapper.close();
    110            return out;
    111        }
    112
    113        @Override
    114        protected void onPostExecute(List<ComplexRandomModel> result) {
    115            if(result != null) {
    116                events.setAdapter(new ComplexRandomModelDTAAdapter(getContext(), (ArrayList<ComplexRandomModel>) result));
    117                expandedTitle.setText(format(expandeddTitlePattern, result.size()));
    118            } else {
    119                events.setAdapter(new ComplexRandomModelDTAAdapter(getContext(), new LinkedList<ComplexRandomModel>()));
    120                expandedTitle.setText(format(expandeddTitlePattern, 0));
    121            }
    122        }
    123    }
    124
    125    private static final String ERR_STRING_WIPE = "Lesson3tab1WipeDataError, see exception details!";
    126
    127    class WipeAsync extends AsyncTask<Long, Long, WipeAsyncResult> {
    128
    129        ProgressDialog dialog;
    130
    131        @Override
    132        protected void onPreExecute() {
    133            dialog = ProgressDialog.show(
    134                    Lesson3Tab1DatatypesAffinities.this.getLessonActivity(),
    135                    Lesson3Tab1DatatypesAffinities.this.getString(R.string._l3_t1_running_requested_operation_pg_title),
    136                    Lesson3Tab1DatatypesAffinities.this.getString(R.string._l3_t1_running_requested_operation_pg_body)
    137            );
    138            dialog.setCancelable(false);
    139        }
    140
    141        @Override
    142        protected WipeAsyncResult doInBackground(Long... params) {
    143            try {
    144                final ComplexRandomMapper mapper = (ComplexRandomMapper) Lesson3Tab1DatatypesAffinities.this.getDatabase().getMapper(ComplexRandomModel.class);
    145                long recordsCount = mapper.countAll();
    146                long affected = mapper.deleteAll();
    147                mapper.close();
    148                return new WipeAsyncResult(affected, recordsCount);
    149            } catch (Exception e) {
    150                Log.e(BasicDatabase.LOG_TAG, ERR_STRING_WIPE, e);
    151                if(e instanceof KittyRuntimeException) {
    152                    if(((KittyRuntimeException) e).getNestedException() != null) {
    153                        Log.e(BasicDatabase.LOG_TAG, ERR_STRING_WIPE, ((KittyRuntimeException) e).getNestedException());
    154                    }
    155                }
    156                return new WipeAsyncResult(-1l, -1l);
    157            }
    158        }
    159
    160        @Override
    161        protected void onPostExecute(WipeAsyncResult result) {
    162            dialog.cancel();
    163
    164            if (eventsListView != null) {
    165                eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>()));
    166                eventsListView.setOnTouchListener(new View.OnTouchListener() {
    167
    168                    // Setting on Touch Listener for handling the touch inside ScrollView
    169                    @Override
    170                    public boolean onTouch(View v, MotionEvent event) {
    171                        // Disallow the touch request for parent scroll on touch of child view
    172                        v.getParent().requestDisallowInterceptTouchEvent(true);
    173                        return false;
    174                    }
    175                });
    176                if (result.recordsCount > -1 && result.affectedRows > -1) {
    177                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_count_to_events), result.recordsCount));
    178                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_deleted_to_events), result.affectedRows));
    179                } else {
    180                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l3_t1_error_event));
    181                }
    182                ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged();
    183                reloadTableExpandedList();
    184            }
    185        }
    186    }
    187
    188    class WipeAsyncResult {
    189        Long affectedRows;
    190        Long recordsCount;
    191
    192        public WipeAsyncResult(Long affectedRows, Long recordsCount) {
    193            this.affectedRows = affectedRows;
    194            this.recordsCount = recordsCount;
    195        }
    196    }
    197
    198    static final int INSERT_AMOUNT = 25;
    199
    200    static final String ERR_INSERT_RND = "Lesson3tab1InsertRNDDataError, see exception details!";
    201
    202    class InsertRandomAsync extends AsyncTask<Long, Long, InsertRandomResults> {
    203        ProgressDialog dialog;
    204
    205        @Override
    206        protected void onPreExecute() {
    207            dialog = ProgressDialog.show(
    208                    Lesson3Tab1DatatypesAffinities.this.getLessonActivity(),
    209                    Lesson3Tab1DatatypesAffinities.this.getString(R.string._l3_t1_running_requested_operation_pg_title),
    210                    Lesson3Tab1DatatypesAffinities.this.getString(R.string._l3_t1_running_requested_operation_pg_body)
    211            );
    212            dialog.setCancelable(false);
    213        }
    214
    215        @Override
    216        protected InsertRandomResults doInBackground(Long... strings) {
    217            try {
    218                ComplexRandomMapper mapper = (ComplexRandomMapper) Lesson3Tab1DatatypesAffinities.this.getDatabase().getMapper(ComplexRandomModel.class);
    219                long recordsCount = mapper.countAll();
    220                long affected = mapper.deleteAll();
    221                LinkedList<ComplexRandomModel> modelsToInsert = new LinkedList<>();
    222                RNDComplexRandomModelFactory factory = new RNDComplexRandomModelFactory(getContext());
    223                for(int i = 0; i < INSERT_AMOUNT; i++) {
    224                    ComplexRandomModel m = factory.newComplexRandomModel();
    225                    modelsToInsert.addLast(m);
    226                }
    227                mapper.insertInTransaction(modelsToInsert);
    228                List<ComplexRandomModel> models = mapper.findAll();
    229                long recordsCountAfter = mapper.countAll();
    230                mapper.close();
    231                return new InsertRandomResults(models, affected, recordsCount, recordsCountAfter, true);
    232            } catch (Exception e) {
    233                Log.e(BasicDatabase.LOG_TAG, ERR_INSERT_RND, e);
    234                if(e instanceof KittyRuntimeException) {
    235                    if(((KittyRuntimeException) e).getNestedException() != null) {
    236                        Log.e(BasicDatabase.LOG_TAG, ERR_INSERT_RND, ((KittyRuntimeException) e).getNestedException());
    237                    }
    238                }
    239                return new InsertRandomResults(null, -1l, -1l, -1l, false);
    240            }
    241        }
    242
    243        @Override
    244        protected void onPostExecute(InsertRandomResults result) {
    245            dialog.cancel();
    246
    247            if (eventsListView != null) {
    248                eventsListView.setAdapter(new BasicArrayAdapter(getContext(), new LinkedList<String>()));
    249                eventsListView.setOnTouchListener(new View.OnTouchListener() {
    250
    251                    // Setting on Touch Listener for handling the touch inside ScrollView
    252                    @Override
    253                    public boolean onTouch(View v, MotionEvent event) {
    254                        // Disallow the touch request for parent scroll on touch of child view
    255                        v.getParent().requestDisallowInterceptTouchEvent(true);
    256                        return false;
    257                    }
    258                });
    259                if (result.operationSuccess) {
    260                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_count_to_events), result.modelsCountBefore));
    261                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_deleted_to_events), result.deletedModelsAffectedRows));
    262                    for(ComplexRandomModel m : result.modelInsertions) {
    263                        ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_inserted_to_events), m.toShortString()));
    264                    }
    265                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(format(getString(R.string._l3_t1_count_to_events), result.modelsCountAfter));
    266                } else {
    267                    ((BasicArrayAdapter) eventsListView.getAdapter()).addItemLast(getString(R.string._l3_t1_error_event));
    268                }
    269                ((BasicArrayAdapter) eventsListView.getAdapter()).notifyDataSetChanged();
    270            }
    271            reloadTableExpandedList();
    272        }
    273
    274
    275    }
    276
    277    class InsertRandomResults {
    278        List<ComplexRandomModel> modelInsertions;
    279        long deletedModelsAffectedRows;
    280        long modelsCountBefore;
    281        long modelsCountAfter;
    282        boolean operationSuccess;
    283
    284        public InsertRandomResults(List<ComplexRandomModel> modelInsertions, long deletedModelsAffectedRows, long modelsCountBefore, long modelsCountAfter, boolean opSuccess) {
    285            this.modelInsertions = modelInsertions;
    286            this.deletedModelsAffectedRows = deletedModelsAffectedRows;
    287            this.modelsCountBefore = modelsCountBefore;
    288            this.modelsCountAfter = modelsCountAfter;
    289            this.operationSuccess = opSuccess;
    290        }
    291    }
    292
    293    // Fab menu section
    294
    295    @Override
    296    public View.OnClickListener helpFabMenuAction() {
    297        return new View.OnClickListener() {
    298            @Override
    299            public void onClick(View v) {
    300                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T1_TUTORIAL);
    301            }
    302        };
    303    }
    304
    305    @Override
    306    public View.OnClickListener sourceFabMenuAction() {
    307        return new View.OnClickListener() {
    308            @Override
    309            public void onClick(View v) {
    310                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T1_SOURCE);
    311            }
    312        };
    313    }
    314
    315    @Override
    316    public View.OnClickListener schemaFabMenuAction() {
    317        return new View.OnClickListener() {
    318            @Override
    319            public void onClick(View v) {
    320                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T1_SCHEMA);
    321            }
    322        };
    323    }
    324}