1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.inputmethodservice.cts.db; 18 19 import android.database.Cursor; 20 import android.provider.BaseColumns; 21 22 import androidx.annotation.NonNull; 23 24 import java.util.ArrayList; 25 import java.util.HashMap; 26 import java.util.List; 27 import java.util.Map; 28 29 /** 30 * Abstraction of SQLite database row. 31 * @param <E> type of entities. 32 */ 33 public final class Entity<E> { 34 35 private final List<Field> mFields; 36 private final Map<String, Field> mFieldMap; 37 Entity(Builder<E> builder)38 private Entity(Builder<E> builder) { 39 mFields = builder.mFields; 40 mFieldMap = builder.mFieldMap; 41 } 42 43 /** 44 * Returns SQL statement to create this entity/row, such that 45 * "(_id INTEGER PRIMARY KEY AUTOINCREMENT, column2_name column2_type, ...)". 46 */ createEntitySql()47 String createEntitySql() { 48 final StringBuilder sb = new StringBuilder("("); 49 for (Field field : mFields) { 50 if (field.mPos > 0) sb.append(", "); 51 sb.append(field.mName).append(" ").append(field.mSqLiteType); 52 if (field.mName.equals(BaseColumns._ID)) { 53 sb.append(" PRIMARY KEY AUTOINCREMENT"); 54 } 55 } 56 return sb.append(")").toString(); 57 } 58 getField(String fieldName)59 Field getField(String fieldName) { 60 return mFieldMap.get(fieldName); 61 } 62 63 /** 64 * {@link Entity} builder. 65 * @param <E> type of entities. 66 */ 67 public static final class Builder<E> { 68 private final List<Field> mFields = new ArrayList<>(); 69 private final Map<String, Field> mFieldMap = new HashMap<>(); 70 private int mPos = 0; 71 72 /** 73 * Constructor or {@link Builder}. 74 */ Builder()75 public Builder() { 76 addFieldInternal(BaseColumns._ID, Cursor.FIELD_TYPE_INTEGER); 77 } 78 79 /** 80 * Add a new field with given name and type. 81 * 82 * @param name name of the field 83 * @param fieldType type enum of the field 84 * @return this builder, useful for chaining 85 */ addField(@onNull String name, int fieldType)86 public Builder<E> addField(@NonNull String name, int fieldType) { 87 addFieldInternal(name, fieldType); 88 return this; 89 } 90 91 /** 92 * Build {@link Entity}. 93 * 94 * @return a new instance of {@link Entity} built from this builder. 95 */ build()96 public Entity<E> build() { 97 return new Entity<>(this); 98 } 99 addFieldInternal(String name, int fieldType)100 private void addFieldInternal(String name, int fieldType) { 101 if (mFieldMap.containsKey(name)) { 102 throw new IllegalArgumentException("Field " + name + " already exists at " 103 + mFieldMap.get(name).mPos); 104 } 105 final Field field = Field.newInstance(mPos++, name, fieldType); 106 mFields.add(field); 107 mFieldMap.put(field.mName, field); 108 } 109 } 110 } 111