Source code

KittyORM constraint declaration examples
  1. Click to view NOT NULL constraint declaration example:
    1@KITTY_COLUMN(columnOrder = 0)
    2@PRIMARY_KEY
    3@NOT_NULL // NOT NULL constraint declaration
    4public Long id;

  2. Click to view DEFAULT constraint declaration examples:
     1@KITTY_COLUMN(columnOrder = 3)
     2@DEFAULT(signedInteger = 28) // You can choose for options for default declaration, if nothing set than 0 value would be used
     3@NOT_NULL
     4public Integer defaultNumber;
     5
     6@KITTY_COLUMN(columnOrder = 4)
     7@DEFAULT(
     8        predefinedLiteralValue = LiteralValues.CURRENT_DATE
     9)
    10@NOT_NULL
    11public String creationDate;

  3. Click to view UNIQUE constraint declaration examples:
    1@KITTY_COLUMN(columnOrder = 1)
    2@NOT_NULL
    3@UNIQUE
    4public Long rndId;
     1@KITTY_TABLE(tableName = "cai")
     2@FOREIGN_KEY_T(
     3        name = "CAI_FK",
     4        columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME},
     5        reference = @FOREIGN_KEY_REFERENCE(
     6                foreignTableName = "random",
     7                foreignTableColumns = {"id"},
     8                onUpdate = OnUpdateDeleteActions.CASCADE,
     9                onDelete = OnUpdateDeleteActions.CASCADE
    10        )
    11)
    12@INDEX(indexColumns = {"creation_date"}) 
    13@UNIQUE_T(columns = {"rnd_id, animal"}) // Declaring unique constraint on more than two columns
    14public class IndexesAndConstraintsModel extends KittyModel {
    15    ...
    16}

  4. Click to view CHECK constraint declaration example:
    1@KITTY_COLUMN(columnOrder = 2)
    2@CHECK(checkExpression = "animal IN (\"CAT\", \"TIGER\", \"LION\")") // only cats allowed to this party
    3public Animals animal;

  5. Click to view COLLATE constraint declaration example:
    1@KITTY_COLUMN(columnOrder = 2)
    2@COLLATE(collation = BuiltInCollations.NOCASE) // Collation example
    3@CHECK(checkExpression = "animal IN (\"CAT\", \"TIGER\", \"LION\")") 
    4public Animals animal;

  6. Click to view PRIMARY KEY constraint declaration examples:
    1@KITTY_COLUMN(
    2        columnOrder = 0, 
    3        isIPK = true
    4)
    5public Long id;
    1@KITTY_COLUMN(columnOrder = 0)
    2@PRIMARY_KEY
    3@NOT_NULL
    4public Long id;
     1@KITTY_TABLE(tableName = "cpk_test")
     2@PRIMARY_KEY_T(
     3    columns = {"user_name", "email"}
     4)
     5public class CPKModel extends KittyModel {
     6
     7    @KITTY_COLUMN(columnOrder = 0)
     8    public String userName;
     9
    10    @KITTY_COLUMN(columnOrder = 1)
    11    @UNIQUE
    12    public String email;
    13    
    14    ...
    15}

  7. Click to view FOREIGN KEY constraint declaration examples:
     1@KITTY_COLUMN(columnOrder = 1)
     2@NOT_NULL
     3@UNIQUE
     4@FOREIGN_KEY(
     5        reference = @FOREIGN_KEY_REFERENCE(
     6                foreignTableName = "random",
     7                foreignTableColumns = {"id"},
     8                onUpdate = OnUpdateDeleteActions.CASCADE,
     9                onDelete = OnUpdateDeleteActions.CASCADE
    10        )
    11)
    12public Long rndId;
     1@KITTY_TABLE(tableName = "cai")
     2@FOREIGN_KEY_T(
     3        name = "CAI_FK",
     4        columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME},
     5        reference = @FOREIGN_KEY_REFERENCE(
     6                foreignTableName = "random",
     7                foreignTableColumns = {"id"},
     8                onUpdate = OnUpdateDeleteActions.CASCADE,
     9                onDelete = OnUpdateDeleteActions.CASCADE
    10        )
    11)
    12@INDEX(indexColumns = {"creation_date"})
    13public class IndexesAndConstraintsModel extends KittyModel {
    14    ...
    15    
    16    @KITTY_COLUMN(columnOrder = 1)
    17    @NOT_NULL
    18    @UNIQUE
    19    public Long rndId;
    20
    21    ...
    22}

  8. Click to view index declaration examples:
     1@KITTY_TABLE(tableName = "cai")
     2@FOREIGN_KEY_T(
     3        name = "CAI_FK",
     4        columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME},
     5        reference = @FOREIGN_KEY_REFERENCE(
     6                foreignTableName = "random",
     7                foreignTableColumns = {"id"},
     8                onUpdate = OnUpdateDeleteActions.CASCADE,
     9                onDelete = OnUpdateDeleteActions.CASCADE
    10        )
    11)
    12@INDEX(indexColumns = {"creation_date"}) // index declaration
    13public class IndexesAndConstraintsModel extends KittyModel {
    14    ...
    15
    16    @KITTY_COLUMN(columnOrder = 4)
    17    @DEFAULT(
    18            predefinedLiteralValue = LiteralValues.CURRENT_DATE
    19    )
    20    @NOT_NULL
    21    public String creationDate; // indexed column
    22
    23    ...
    24}
     1@KITTY_TABLE(tableName = "cai")
     2...
     3public class IndexesAndConstraintsModel extends KittyModel {
     4    ...
     5
     6    @KITTY_COLUMN(columnOrder = 5)
     7    @DEFAULT(
     8            predefinedLiteralValue = LiteralValues.CURRENT_TIMESTAMP
     9    )
    10    // One column indexe declaration example
    11    @ONE_COLUMN_INDEX(unique = true, indexName = "IAC_unique_index_creation_timestamp") 
    12    @NOT_NULL
    13    public Timestamp creationTmstmp;
    14
    15    ...
    16}

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}

  5. Click to view IndexesAndConstraintsModel.class:
     1@KITTY_TABLE(tableName = "cai")
     2@FOREIGN_KEY_T(
     3        name = "CAI_FK",
     4        columns = {IndexesAndConstraintsModel.RANDOM_ID_CNAME},
     5        reference = @FOREIGN_KEY_REFERENCE(
     6                foreignTableName = "random",
     7                foreignTableColumns = {"id"},
     8                onUpdate = OnUpdateDeleteActions.CASCADE,
     9                onDelete = OnUpdateDeleteActions.CASCADE
    10        )
    11)
    12@INDEX(indexColumns = {"creation_date"})
    13public class IndexesAndConstraintsModel extends KittyModel {
    14    static final String RANDOM_ID_CNAME = "rnd_id";
    15
    16    @KITTY_COLUMN(columnOrder = 0)
    17    @PRIMARY_KEY
    18    @NOT_NULL
    19    public Long id;
    20
    21    @KITTY_COLUMN(columnOrder = 1)
    22    @NOT_NULL
    23    @UNIQUE
    24    public Long rndId;
    25
    26    @KITTY_COLUMN(columnOrder = 2)
    27    @CHECK(checkExpression = "animal IN (\"CAT\", \"TIGER\", \"LION\")") // only cats allowed to this party
    28    public Animals animal;
    29
    30    @KITTY_COLUMN(columnOrder = 3)
    31    @DEFAULT(signedInteger = 28) // You can choose for options for default declaration, if nothing set than 0 value would be used
    32    @NOT_NULL
    33    public Integer defaultNumber;
    34
    35    @KITTY_COLUMN(columnOrder = 4)
    36    @DEFAULT(
    37            predefinedLiteralValue = LiteralValues.CURRENT_DATE
    38    )
    39    @NOT_NULL
    40    public String creationDate;
    41
    42    @KITTY_COLUMN(columnOrder = 5)
    43    @DEFAULT(
    44            predefinedLiteralValue = LiteralValues.CURRENT_TIMESTAMP
    45    )
    46    @ONE_COLUMN_INDEX(unique = true, indexName = "IAC_unique_index_creation_timestamp")
    47    @NOT_NULL
    48    public Timestamp creationTmstmp;
    49
    50    @Override
    51    public String toString() {
    52        StringBuilder sb = new StringBuilder(64);
    53        sb.append("[ RowID = ").append(getRowID())
    54                .append(" ; id = ").append(id)
    55                .append(" ; rndId = ").append(rndId)
    56                .append(" ; animal = ").append(animal)
    57                .append(" ; defaultNumber = ").append(defaultNumber)
    58                .append(" ; creationDate = ").append(creationDate)
    59                .append(" ; creationTmstmp = ").append(creationTmstmp).append(" ]");
    60        return sb.toString();
    61    }
    62}

Fragment code used in this tutorial
  1. Click to view Lesson3Tab2Constraints.class:
      1public class Lesson3Tab2Constraints extends Lesson3BaseFragment {
      2
      3    private BasicDatabase database;
      4
      5    protected ArrayAdapter<String> animalAdapter;
      6    protected Spinner animalSpinner;
      7
      8    public Lesson3Tab2Constraints() {}
      9
     10    EditText rndIdFkET;
     11    EditText defaultIntET;
     12    EditText creationDateET;
     13    EditText creationTmstmpET;
     14
     15    Button saveNewModelButton;
     16    Button wipeAllButton;
     17
     18    @Override
     19    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     20        View rootView = inflater.inflate(R.layout.lesson3_tab2_constraints_and_indexes, container, false);
     21
     22        rndIdFkET = rootView.findViewById(R.id.l3_t2_et_fk);
     23        defaultIntET = rootView.findViewById(R.id.l3_t2_et_default_number);
     24        creationDateET = rootView.findViewById(R.id.l3_t2_et_creation_date);
     25        creationTmstmpET = rootView.findViewById(R.id.l3_t2_et_current_timestamp);
     26
     27        saveNewModelButton = rootView.findViewById(R.id._l3_t2_save_button);
     28        saveNewModelButton.setOnClickListener(new View.OnClickListener() {
     29            @Override
     30            public void onClick(View v) {
     31                IndexesAndConstraintsModel model = getModelFromInput();
     32                if(model==null) return;
     33                new InsertNewAsync().execute(model);
     34            }
     35        });
     36
     37        wipeAllButton = rootView.findViewById(R.id._l3_t2_wipe_button);
     38        wipeAllButton.setOnClickListener(new View.OnClickListener() {
     39            @Override
     40            public void onClick(View v) {
     41                new WipeAsync().execute(0l);
     42            }
     43        });
     44
     45
     46        setUpExpandedList(
     47                rootView,
     48                R.id._l3_t2_expanded_panel_lw,
     49                R.id._l3_t2_expanded_panel_text,
     50                R.string._l3_t2_expanded_text_pattern
     51        );
     52
     53        setAnimalSpinner(rootView, R.id.l3_t2_spinner, new AdapterView.OnItemSelectedListener() {
     54            @Override
     55            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
     56            }
     57
     58            @Override
     59            public void onNothingSelected(AdapterView<?> parent) {
     60            }
     61        });
     62
     63        reloadTableExpandedList();
     64        return rootView;
     65    }
     66
     67    private void reloadTableExpandedList() {
     68        new ReloadTableAsync().execute(0l);
     69    }
     70
     71    private IndexesAndConstraintsModel getModelFromInput() {
     72        IndexesAndConstraintsModel model = new IndexesAndConstraintsModel();
     73        String rndId = rndIdFkET.getText().toString();
     74        if(rndId == null) model.rndId = null;
     75        else if(rndId.trim().length() == 0) model.rndId = null;
     76        else {
     77            try {
     78                model.rndId = Long.parseLong(rndId);
     79            } catch (Exception e) {
     80                getLessonActivity().showWarningDialog(
     81                        R.string._warning_dialog_title,
     82                        R.string._l3_t2_rnd_id_cant_be_treated_as_null_or_long_only,
     83                        R.string._warning_dialog_ok_button_text);
     84                return null;
     85            }
     86        }
     87        String animalEnumStringValue = animalSpinner.getSelectedItem().toString();
     88        if(!animalEnumStringValue.equals(animalAdapter.getItem(animalAdapter.getCount()))) {
     89            model.animal = Animals.valueOf(animalEnumStringValue);
     90        }
     91        String defInteger = defaultIntET.getText().toString();
     92        if(defInteger == null) model.setFieldExclusion("defaultNumber");
     93        else if(defInteger.trim().length() == 0) model.setFieldExclusion("defaultNumber");
     94        else {
     95            try {
     96                model.defaultNumber = Integer.parseInt(defInteger);
     97            } catch (Exception e) {
     98                getLessonActivity().showWarningDialog(
     99                        R.string._warning_dialog_title,
    100                        R.string._l3_t2_default_number_can_be_treated_as_null_or_long_only,
    101                        R.string._warning_dialog_ok_button_text);
    102                return null;
    103            }
    104        }
    105        String creationDate = creationDateET.getText().toString();
    106        if(creationDate == null) model.setFieldExclusion("creationDate");
    107        else if(creationDate.trim().length() == 0) model.setFieldExclusion("creationDate");
    108        else model.creationDate = creationDate;
    109        String creationTimestamp = creationTmstmpET.getText().toString();
    110        if(creationTimestamp == null) model.setFieldExclusion("creationTmstmp");
    111        else if(creationTimestamp.trim().length() == 0) model.setFieldExclusion("creationTmstmp");
    112        else {
    113            Long creationTimestampLong = null;
    114            try {
    115                creationTimestampLong = Long.parseLong(creationTimestamp);
    116            } catch (Exception e) {
    117                getLessonActivity().showWarningDialog(
    118                        R.string._warning_dialog_title,
    119                        R.string._l3_t2_creation_timestamp_can_be_treated_as_null_or_long_only,
    120                        R.string._warning_dialog_ok_button_text);
    121                return null;
    122            }
    123            model.creationTmstmp = new Timestamp(creationTimestampLong);
    124        }
    125
    126        return model;
    127    }
    128
    129    private BasicDatabase getDatabase() {
    130        if(database != null) return database;
    131        database = new BasicDatabase(getContext());
    132        return database;
    133    }
    134
    135    @Override
    136    public void onVisible() {
    137        reloadTableExpandedList();
    138    }
    139
    140    @Override
    141    protected int snackbarMessageResource() {
    142        return R.string._l3_t2_snackbar_message;
    143    }
    144
    145    // Asyncs
    146
    147    class ReloadTableAsync extends AsyncTask<Long, Long, List<IndexesAndConstraintsModel>> {
    148
    149        @Override
    150        protected List<IndexesAndConstraintsModel> doInBackground(Long... params) {
    151            KittyMapper mapper = Lesson3Tab2Constraints.this.getDatabase().getMapper(IndexesAndConstraintsModel.class);
    152            List<IndexesAndConstraintsModel> out = mapper.findAll();
    153            mapper.close();
    154            return out;
    155        }
    156
    157        @Override
    158        protected void onPostExecute(List<IndexesAndConstraintsModel> result) {
    159            if(result != null) {
    160                events.setAdapter(new CAIModelAdapter(getContext(), result));
    161                expandedTitle.setText(format(expandeddTitlePattern, result.size()));
    162            } else {
    163                events.setAdapter(new CAIModelAdapter(getContext(), new LinkedList<IndexesAndConstraintsModel>()));
    164                expandedTitle.setText(format(expandeddTitlePattern, 0));
    165            }
    166        }
    167    }
    168
    169    private static final String ERR_STRING_WIPE = "Lesson3tab2WipeDataError, see exception details!";
    170
    171    class WipeAsync extends AsyncTask<Long, Long, Long> {
    172
    173        ProgressDialog dialog;
    174
    175        @Override
    176        protected void onPreExecute() {
    177            dialog = ProgressDialog.show(
    178                    Lesson3Tab2Constraints.this.getLessonActivity(),
    179                    Lesson3Tab2Constraints.this.getString(R.string._l3_t2_running_requested_operation_pg_title),
    180                    Lesson3Tab2Constraints.this.getString(R.string._l3_t2_running_requested_operation_pg_body)
    181            );
    182            dialog.setCancelable(false);
    183        }
    184
    185        @Override
    186        protected Long doInBackground(Long... params) {
    187            try {
    188                KittyMapper mapper = Lesson3Tab2Constraints.this.getDatabase().getMapper(IndexesAndConstraintsModel.class);
    189                long affected = mapper.deleteAll();
    190                mapper.close();
    191                return affected;
    192            } catch (Exception e) {
    193                Log.e(BasicDatabase.LOG_TAG, ERR_STRING_WIPE, e);
    194                if(e instanceof KittyRuntimeException) {
    195                    if(((KittyRuntimeException) e).getNestedException() != null) {
    196                        Log.e(BasicDatabase.LOG_TAG, ERR_STRING_WIPE, ((KittyRuntimeException) e).getNestedException());
    197                    }
    198                }
    199                return -1l;
    200            }
    201        }
    202
    203        @Override
    204        protected void onPostExecute(Long result) {
    205            dialog.cancel();
    206            if (result <= -1l) {
    207                getLessonActivity().showWarningDialog(
    208                        R.string._warning_dialog_title,
    209                        R.string._l3_t2_some_error_on_deleting,
    210                        R.string._warning_dialog_ok_button_text);
    211            } else {
    212                reloadTableExpandedList();
    213            }
    214        }
    215    }
    216
    217    static final String IA_EXPECTED_ONLY_ONE = "Lesson3Tab2Constraints$InsertNewAsync expects array with one element as parameter for doInBackground";
    218    static final String ERR_ON_INSERTION = "Lesson3Tab2Constraints$InsertNewAsync error on insertion, see exception details!";
    219
    220    class InsertNewAsync extends AsyncTask<IndexesAndConstraintsModel, Long, InsertNewAsyncResult> {
    221        @Override
    222        protected InsertNewAsyncResult doInBackground(IndexesAndConstraintsModel... params) {
    223            if(params.length > 1)
    224                throw new IllegalArgumentException(IA_EXPECTED_ONLY_ONE);
    225            try {
    226                KittyMapper mapper = getDatabase().getMapper(IndexesAndConstraintsModel.class);
    227                long insert = mapper.insert(params[0]);
    228                mapper.close();
    229                if(insert > -1l)
    230                    return new InsertNewAsyncResult(true, null, insert);
    231                else
    232                    return new InsertNewAsyncResult(false, null, insert);
    233            } catch (Exception e) {
    234                Log.e(BasicDatabase.LOG_TAG, ERR_ON_INSERTION, e);
    235                if(e instanceof KittyRuntimeException) {
    236                    if(((KittyRuntimeException) e).getNestedException() != null) {
    237                        Log.e(BasicDatabase.LOG_TAG, ERR_ON_INSERTION, ((KittyRuntimeException) e).getNestedException());
    238                    }
    239                }
    240                return new InsertNewAsyncResult(false, e, -1l);
    241            }
    242        }
    243
    244        protected void onPostExecute(InsertNewAsyncResult result) {
    245            if(result.success)
    246                reloadTableExpandedList();
    247            else {
    248                getLessonActivity().showWarningDialog(
    249                        R.string._warning_dialog_title,
    250                        R.string._l3_t2_some_error_on_insertion,
    251                        R.string._warning_dialog_ok_button_text);
    252            }
    253        }
    254    }
    255
    256    class InsertNewAsyncResult {
    257        boolean success;
    258        Exception exception;
    259        long insertId;
    260
    261        public InsertNewAsyncResult(boolean success, Exception exception, long insertId) {
    262            this.success = success;
    263            this.exception = exception;
    264            this.insertId = insertId;
    265        }
    266    }
    267
    268    // Animal spinner stuff
    269    protected ArrayAdapter<String> newAnimalAdapter() {
    270        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_dropdown_item) {
    271
    272            @Override
    273            public View getView(int position, View convertView, ViewGroup parent) {
    274
    275                View v = super.getView(position, convertView, parent);
    276                if (position == getCount()) {
    277                    ((TextView)v.findViewById(android.R.id.text1)).setText("");
    278                    ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed"
    279                }
    280
    281                return v;
    282            }
    283
    284            @Override
    285            public int getCount() {
    286                return super.getCount()-1;
    287            }
    288
    289        };
    290
    291        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    292        String[] adapterStrings = getContext().getResources().getStringArray(R.array.animal_enum);
    293        for(int i = 0; i < adapterStrings.length; i++) {
    294            adapter.add(adapterStrings[i]);
    295        }
    296        adapter.add(getContext().getString(R.string._l2_t1_random_animal_hint));
    297        return adapter;
    298    }
    299
    300    protected void setAnimalSpinner(View rootView, int spinnerId, AdapterView.OnItemSelectedListener onItemSelectedListener) {
    301        animalSpinner = (Spinner) rootView.findViewById(spinnerId);
    302        animalAdapter = newAnimalAdapter();
    303        animalSpinner.setAdapter(animalAdapter);
    304        animalSpinner.setSelection(animalAdapter.getCount()); //display hint
    305        animalSpinner.setOnItemSelectedListener(onItemSelectedListener);
    306    }
    307
    308    // expanded list
    309    CAIModelAdapter caiModelAdapter;
    310
    311    @Override
    312    protected void setUpExpandedList(View rootView, int eventsId, int eventsTitleId, int eventTitleStringPattern) {
    313        events = (ListView) rootView.findViewById(eventsId);
    314        expandedTitle = (TextView) rootView.findViewById(eventsTitleId);
    315        expandeddTitlePattern = getString(eventTitleStringPattern);
    316
    317        expandedTitle.setText(format(expandeddTitlePattern, 0));
    318
    319        if(expandedAdapter == null) {
    320            caiModelAdapter = new CAIModelAdapter(getContext(), new LinkedList<IndexesAndConstraintsModel>());
    321        }
    322
    323        events.setAdapter(caiModelAdapter);
    324        events.setOnTouchListener(new View.OnTouchListener() {
    325
    326            // Setting on Touch Listener for handling the touch inside ScrollView
    327            @Override
    328            public boolean onTouch(View v, MotionEvent event) {
    329                // Disallow the touch request for parent scroll on touch of child view
    330                v.getParent().requestDisallowInterceptTouchEvent(true);
    331                return false;
    332            }
    333        });
    334    }
    335
    336    // Fab menu section
    337
    338    @Override
    339    public View.OnClickListener helpFabMenuAction() {
    340        return new View.OnClickListener() {
    341            @Override
    342            public void onClick(View v) {
    343                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T2_TUTORIAL);
    344            }
    345        };
    346    }
    347
    348    @Override
    349    public View.OnClickListener sourceFabMenuAction() {
    350        return new View.OnClickListener() {
    351            @Override
    352            public void onClick(View v) {
    353                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T2_SOURCE);
    354            }
    355        };
    356    }
    357
    358    @Override
    359    public View.OnClickListener schemaFabMenuAction() {
    360        return new View.OnClickListener() {
    361            @Override
    362            public void onClick(View v) {
    363                ((KittyTutorialActivity)getActivity()).showWebViewDialog(LessonsUriConstants.L3_T2_SCHEMA);
    364            }
    365        };
    366    }
    367}