What's included in the second sprint, and how is it graded?
This is the second set of deliverables in the personal Android project, due at the end of the second sprint. In general, deliverables are cumulative: They include elements delivered in earlier sprints, but these should be updated as necessary, and they won’t be weighted as heavily in the grading. Thus, the content for this milestone is expected to include project summary and design elements, as well as the data model documentation included in the first milestone—all updated as necessary—along with new elements for this milestone.
Note: If elements previously included in the first milestone do not correspond to the project in its current state—or if you have not addressed issues that were raised in the grading and feedback for the first milestone—you will not get full credit for those elements.
The nominal total value of this deliverable is 50 points; in addition, up to 10 points of extra credit can be earned for exemplary execution of any or all of the required elements.
See “Milestone 1: Project description” for this element’s requirements.
See “Milestone 1: Intended users and user stories” for this element’s requirements.
See “Milestone 1: Wireframe diagram” for this element’s requirements.
See “Milestone 1: UML class diagram” for this element’s requirements.
See “Milestone 1: Cloud- or device-based services or data” for this element’s requirements.
Your documentation must include a physical ERD, showing all entities, attributes, and relationships—with the exception of associative entities.
The ERD must be displayed as a single SVG, embedded in a page dedicated to this purpose, accessible (directly or indirectly) via a link from the main page of your GitHub pages site. This image must be a clickable link that opens a PDF version of the same image.
Each entity in the ERD must be named using lower_snake_case, and must include (at least) a primary key attribute, of the SQLite INTEGER type or the Java long type.
Each attribute must be displayed with:
Name, in lower_snake_case.
Data type, specified as a SQLite datatype or Java type. (Please be consistent!)
Any relevant primary key (PK), foreign key (FK), unique constraint (UQ or UK), and/or index (IX) indicators (the last 3 should be numbered—e.g., FK1, IX1, UQ1, etc.—even if there is only one of them in an entity).
Nullability indicator, if the attribute is allowed to have a null value. (Use either N, null, NULL, or Null.) Note that no indicator should be used to indicate non-nullability.
All relationship lines must include the appropriate crow’s foot symbol (including cardinality and modality) at each end.
For a conceptual many-to-many relationship, the associative entity that enables such a relationship may be omitted at this point, as noted above.
For every entity in the ERD, there must be a corresponding entity class in your implementation project. There must not be any entity class in the implementation project that does not correspond to an entity in the ERD.
All of the entity classes must be located either in the model or model.entity subpackage (within the base package of the project). Note that the choice to place an entity class in an entity subpackage must be made consistently: Please don’t put one entity class in the model.entity package, while putting another entity class from the same project directly in the model package.
Entity classes must be linked to from the GitHub Pages site. That is, entity classes must be listed in the GitHub Pages-based documentation, and each must be displayed as a link to the source code in GitHub for that class.
Each entity class must be annotated with @Entity.
The tableName attribute of the @Entity annotation must be used to specify a lower_snake_case name for the corresponding table; this name must match (exactly) the name of the corresponding entity in the ERD. For example, an entity class named MusicGenre, corresponding to an entity shown in the ERD as music_genre could be declared as follows:
@Entity(tableName = "music_genre")
public class MusicGenre {...}
Every attribute listed in the ERD must be present as a field in the associated entity class. Aside from these attribute-related fields, there must not be any other non-static, non-transient, non-@Ignore-annotated fields in the entity class.
All fields must be private, and named in lowerCamelCase.
All fields corresponding to entity attributes must have both accessors and mutators (i.e. getters and setters).
If the entity’s primary key is composed of a single attribute, then the corresponding field must be named id, with a type of long, and it must be annotated with @PrimaryKey(autoGenerate = true).
Such a field must also use the name element of the @ColumnInfo annotation to specify a column name consisting of the entity name, followed by “id”, expressed in lower_snake_case. For example, a field corresponding to the primary key attribute of an entity class named DevelopmentTeam would be declared as follows:
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "development_team_id")
private long id;
Field names must correspond to the attribute names. If a field’s lowerCamelCase name consists of multiple words, the name attribute of the @ColumnInfo annotation must be used to specify the column name in lower_snake_case; that column name must match the attribute name in the ERD. For example, a long field named managerId would be declared as follows:
@ColumnInfo(name = "manager_id")
private long managerId;
The field types must correspond to those given in the ERD (i.e., they must be the same as Java types in the ERD, or must be the Java equivalents of SQLite types in the ERD).
Any field in an entity class corresponding to a non-nullable attribute in the ERD must either be declared as a primitive type or be annotated with @NonNull to enforce that constraint.
Any field in an entity class corresponding to a nullable attribute in the ERD must be declared as an object (not primitive) type, and must not be annotated with @NonNull.
Entity classes must use the expected rational ordering of class members: all fields, then constructors (if any), then all methods (including accessors and mutators), and finally nested classes/interfaces/enums (if any).
Each entity class must include all appropriate class-level and field-level annotations to implement the primary keys, unique constraints, and other indices indicated in the ERD. Important: Don’t forget to create indices for foreign keys! (These are not automatically created by Room or SQLite, as they are in most other databases.)
If any field of the class is of an enumerated type, that enum must be declared as a top-level enum in the model.pojo or model.type subpackage; it must also include @TypeConverter-annotated public static methods to convert between the enumerated type and Integer.
For every entity in the data model, your project must include a corresponding data access object (DAO) interface, declaring the CRUD operations supported for that entity.
All DAO interfaces must be located in the model.dao subpackage, within the main package structure of the overall project.
DAO interfaces must be linked to from the GitHub Pages site in the same fashion as entity classes.
The name of each DAO interface must consist of the corresponding entity class name, followed by “Dao”, expressed in UpperCamelCase (of course). For example, the DAO interface declaring the CRUD operations supported for instances of a ProjectTask entity class would be named ProjectTaskDao.
Each DAO interface must be annotated with @Dao.
Each DAO interface must declare at least one (1) @Insert-annotated method (named in lowerCamelCase); any such method must take a single parameter of the entity type, the entity array (or varargs) type, or a Collection of the entity type. The return types must be the ReactiveX Single type, with the type parameter specified as Long (for inserting a single instance) or List<Long> (for inserting multiple instances).
Additional @Insert-annotated methods should be declared as appropriate, based on the anticipated requirements of the app.
Each DAO interface must declare at least one @Query-annotated method, for retrieving a single instance of the corresponding entity.
The return type of this method must be the LiveData generic type, using a type parameter of the entity type (or a POJO class extending the entity type).
The @Query annotation must include the SQL code for selecting a single record from the corresponding table, with a placeholder for a long parameter (since the primary key type is long); the referenced parameter must be included in the method declaration.
For example, if the entity type is Attempt, then the DAO would minimally include this method declaration:
@Query("SELECT * FROM attempt WHERE attempt_id = :attemptId")
LiveData<Attempt> select(long attemptId);
Additional @Query-annotated methods should be declared as appropriate, based on the anticipated requirements of the app. For example, if the wireframe diagram includes a screen intended to display a list of reminders, where each reminder is an instance of the Reminder entity class, and each reminder has a due date represented by the dueBy field in the class, and the due_by column in the table, we might declare the following method:
@Query("SELECT * FROM reminder ORDER BY due_by ASC")
LiveData<List<Reminder>> selectAll();
Note that the return type for a LiveData-based query that is intended to retrieve (at least potentially) multiple instances must be LiveData<List<EntityClassName>>, where EntityClassName must be replaced by the name of the corresponding entity class (or that of a POJO class that embeds or extends the entity class).
Each DAO interface should declare @Update- and @Delete-annotated methods as appropriate, based on the anticipated requirements of the app, and with the appropriate ReactiveX return types (typically Single<Integer> or Completable). Note that in the case of an entity whose instances are intended to be immutable in their persistent form, there will generally be no need for @Update-annotated methods in the DAO; similarly, an entity whose instances will not be deleted, or whose deletion will be controlled by cascading, there will generally be no need for @Delete-annotated methods.
Your project must include a public abstract class that extends RoomDatabase.
The database class must be located in the service subpackage, within the main package structure of the overall project.
The database class must be linked to from the GitHub Pages site.
The database class must include:
The @Database annotation, with an entities element that specifies all of the entity classes in the data model.
A public static method named getName, with a String return type, and no parameters. This method must return a String that specifies the name of the physical file that will hold the database contents.
public abstract methods that return instances of the DAO interfaces, with one such method per DAO. The name of each such method must consist of “get”, followed by the name of the DAO interface, e.g. getProjectTaskDao.
If any of the entity classes have Date, Instant, Duration or other fields not directly supported by Room and SQLite (other than enum classes you define in your own code), the database class must contain a nested public static class Converters with @TypeConverter-annotated public static methods that perform the necessary conversions.
If any @TypeConverter-annotated methods are declared, whether in an enum or in a nested Converters class, those classes must be specified in a @TypeConverters annotation on the database class itself.
Your documentation must include the up-to-date SQL data definition language (DDL) statements that could be used to construct the database.
Your repository must have a docs/sql/ddl.sql file, containing all of the SQL statements defining the tables, primary keys, foreign keys, unique constraints, and other indices declared in your entity classes. (Note that these statements are included in the database schema file optionally generated by Room at build time; however, the generated file is a JSON file, and the SQL statements included in it have placeholders for the table names and do not end in semicolons. Thus, you cannot simply use that file as-is to satisfy this requirement.)
The contents of docs/sql/ddl.sql must be formatted using the IntelliJ code formatting features. (Don’t forget to set the dialect of the file to SQLite, and use semicolons after each SQL statement; otherwise, the formatting will not work as expected.)
Additionally, your repository must contain a file published as a page in the GitHub Pages site, reachable by a link from the overview page, displaying the same content as the docs/sql/ddl.sql file, and linking to the latter file.