Sources
Package example.db
Package example.pl
Package example
example.db.BigIntegerType
public final class BigIntegerType extends SimpleType<BigInteger> {
// The prefix of the type descriptor. Note that the prefix must start with
// an uppercase charcter.
private static final String TD_PREFIX = "BigInteger";
@TypeFromDesc
public static final BigIntegerType createType(String typeDesc) throws
CreationException {
final TypeDesc td = new TypeDesc(typeDesc);
if (!td.prefix.equals(TD_PREFIX) || td.scheme != Scheme.INROW ||
!td.variable) {
throw new CreationException("Illegal type descriptor");
}
return new BigIntegerType(td.limit, Nulls.get(td.nullable));
}
BigIntegerType(int limit, Nulls nulls) throws IllegalArgumentException {
super(BigInteger.class, Scheme.INROW, nulls.value(), limit, true);
}
@Override
protected final String typeDescPrefix() {
return TD_PREFIX;
}
@Override
protected final byte[] toBytes(BigInteger val) throws NullPointerException {
return val.toByteArray();
}
@Override
public final BigInteger fromBytes(byte[] bytes, int offset, int len) throws
IndexOutOfBoundsException {
return new BigInteger(Arrays.copyOfRange(bytes, offset, offset + len));
}
}
example.db.CipherFactory
final class CipherFactory implements ICipherFactory {
private final IvParameterSpec iv = new IvParameterSpec(new byte[] {
114, -8, 22, -67, -71, 30, 118, -103,
51, -45, -110, -65, 16, -127, -73, 103 });
private final Key key = new SecretKeySpec(new byte[] { 114, -8, 23, -67,
-71, 30, 118, -103, 51, -45, -110, -65,
16, -127, -73, 103 }, "AES");
@Override
public final Cipher createCipher() throws NoSuchAlgorithmException,
NoSuchPaddingException {
// Example with padding: AES/CBC/PKCS5Padding
return Cipher.getInstance("AES/CTR/NoPadding");
}
@Override
public final void initCipher(Cipher cipher, boolean encrypt) throws
InvalidKeyException, InvalidAlgorithmParameterException {
cipher.init(encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, key, iv);
}
}
example.db.ContactTable
@SetupTable({ "PhoneNumber", "Email", "Street", "City", "State", "PostalCode",
"Country" })
public final class ContactTable extends CustomTable {
@SetupColumn("PhoneNumber")
public static final Column<String> PHONE_NUMBER = CL.ofString(
StandardCharsets.US_ASCII, NULLABLE, 12);
@SetupColumn("Email")
public static final Column<String> EMAIL = CL.ofString(NO_NULL, SMALL);
@SetupColumn("Street")
public static final Column<String> STREET = CL.ofString(NO_NULL, SMALL);
@SetupColumn("City")
public static final Column<String> CITY = CL.ofString(NO_NULL, SMALL);
@SetupColumn("State")
public static final Column<String> STATE = CL.ofString(NO_NULL, SMALL);
@SetupColumn("PostalCode")
public static final Column<Integer> POSTAL_CODE = CL.ofInteger(NO_NULL);
@SetupColumn("Country")
public static final Column<String> COUNTRY = CL.ofString(NULLABLE, SMALL);
public ContactTable() {
initialize(PHONE_NUMBER, EMAIL, STREET, CITY, STATE, POSTAL_CODE,COUNTRY);
}
}
example.db.CourseTable
@SetupTable({ "ID", "Name", "Teacher" })
public final class CourseTable extends IdTable {
@SetupColumn("ID")
public static final Column<String> ID = CL.ofString(NO_NULL, SMALL);
@SetupColumn("Name")
public static final Column<String> NAME = CL.ofString(NO_NULL, SMALL);
@SetupColumn(value = "Teacher", refdTable = "Teacher")
public static final Column<Ref> TEACHER = CL.ofRef();
public CourseTable() {
initialize(ID, NAME, TEACHER);
}
}
example.db.EduDB
@SetupDatabase(
name = "Edu",
tables = { "Course", "Student", "Teacher", "Contact" }
)
public final class EduDB extends CustomDatabase {
@SetupTableDeclaration("Course")
public static final CourseTable COURSE_TABLE = new CourseTable();
@SetupTableDeclaration("Student")
public static final StudentTable STUDENT_TABLE = new StudentTable();
@SetupTableDeclaration("Teacher")
public static final TeacherTable TEACHER_TABLE = new TeacherTable();
@SetupTableDeclaration("Contact")
public static final ContactTable CONTACT_TABLE = new ContactTable();
public EduDB(Path mainFile, int opMode, boolean writeProtect,
int consistencyNumber) {
final CustomTable[] tables = { COURSE_TABLE, STUDENT_TABLE,
TEACHER_TABLE, CONTACT_TABLE };
open(mainFile, opMode, writeProtect, null, consistencyNumber, tables);
// Create indexes.
for (CustomTable table : tables) {
if (table instanceof IdTable) {
((IdTable) table).initIndex();
}
}
}
}
example.db.IdTable
abstract class IdTable extends CustomTable {
private Column<?> idCol;
private Map<Object, Ref> index;
@Override
protected final void initialize(Column<?>... cols) {
super.initialize(cols);
idCol = cols[0];
}
final void initIndex() {
index = new HashMap<> ((int) (numberOfRows() * 4 / 3) + 1);
final Iterator<Row> it = iterator(idCol);
while (it.hasNext()) {
final Row row = it.next();
index.put(row.get(idCol), row.getRef());
}
}
public final Ref indexGet(Object id) {
return index.get(id);
}
private final Ref indexInsert(Object id, Ref ref) {
if (index.put(id, ref) != null) {
throw new IllegalArgumentException();
}
return ref;
}
private final void indexDelete(Object id) {
if (index.remove(id) == null) {
throw new IllegalArgumentException();
}
}
@Override
public final Ref insert(Object... vals) {
return indexInsert(vals[0], super.insert(vals));
}
@Override
public final void delete(Ref ref) {
throw new UnsupportedOperationException();
}
public final void delete(Object id) {
super.delete(indexGet(id));
indexDelete(id);
}
}
example.db.RoomTable
public final class RoomTable extends IdTable {
public static final Column<String> NUMBER = CL.ofString(NO_NULL, SMALL);
public static final Column<Ref[]> COURSES = CL.ofArrayOfRef(20);
public RoomTable() {
initialize(NUMBER, COURSES);
}
}
example.db.StudentTable
@SetupTable({ "Student Number", "Name", "Contact", "Courses" })
public final class StudentTable extends IdTable {
@SetupColumn("Student Number")
public static final Column<Integer> STUDENT_NUMBER = CL.ofInteger(NO_NULL);
@SetupColumn("Name")
public static final Column<String> NAME = CL.ofString(NO_NULL, SMALL);
@SetupColumn(value = "Contact", refdTable = "Contact")
public static final Column<Ref> CONTACT = CL.ofRef();
@SetupColumn(value = "Courses", refdTable = "Course")
public static final Column<Ref[]> COURSES = CL.ofArrayOfRef(30);
public StudentTable() {
initialize(STUDENT_NUMBER, NAME, CONTACT, COURSES);
}
}
example.db.TeacherTable
@SetupTable({ "Name", "Salary", "Contact", "Courses" })
public final class TeacherTable extends IdTable {
@SetupColumn("Name")
public static final Column<String> NAME = CL.ofString(NO_NULL, SMALL);
@SetupColumn("Salary")
public static final Column<BigInteger> SALARY = CL.create(
new BigIntegerType(20, NULLABLE));
@SetupColumn(value = "Contact", refdTable = "Contact")
public static final Column<Ref> CONTACT = CL.ofRef();
@SetupColumn(value = "Courses", refdTable = "Course")
public static final Column<Ref[]> COURSES = CL.ofArrayOfRef(45);
public TeacherTable() {
initialize(NAME, SALARY, CONTACT, COURSES);
}
}
example.pl.Contact
public final class Contact {
private String phoneNumber;
private String email;
private String street;
private String city;
private String state;
private int postalCode;
private String country;
private final String checkEmail(String value) {
if (value == null || value.indexOf('@') < 0) {
throw new IllegalArgumentException();
}
return value;
}
public Contact(String phoneNumber, String email, String street, String city,
String state, int postalCode, String country) {
this.phoneNumber = phoneNumber;
this.email = checkEmail(email);
this.street = street;
this.city = city;
this.state = state;
this.postalCode = postalCode;
this.country = country;
}
public final String getPhoneNumber() {
return phoneNumber;
}
public final void setPhoneNumber(String value) {
phoneNumber = value;
}
public final String getEmail() {
return email;
}
public final void setEmail(String value) {
email = checkEmail(value);
}
public final String getStreet() {
return street;
}
public final void setStreet(String value) {
street = value;
}
public final String getCity() {
return city;
}
public final void setCity(String value) {
city = value;
}
public final String getState() {
return state;
}
public final void setState(String value) {
state = value;
}
public final int getPostalCode() {
return postalCode;
}
public final void setPostalCode(int value) {
postalCode = value;
}
public final String getCountry() {
return country;
}
public final void setCountry(String value) {
country = value;
}
}
example.pl.Course
public final class Course {
private final String id;
private final String name;
private final Ref teacherRef;
Course(String id, String name, Ref teacherRef) {
this.id = id;
this.name = name;
this.teacherRef = teacherRef;
}
public final String getId() {
return id;
}
public final String getName() {
return name;
}
public final String getTeacher() {
return EduDB.TEACHER_TABLE.getValue(teacherRef, TeacherTable.NAME);
}
}
example.pl.EduPL
public final class EduPL implements AutoCloseable {
private final EduDB db;
public EduPL(Path mainFile, int opMode, boolean writeProtect,
int consistencyNumber) {
db = new EduDB(mainFile, opMode, writeProtect, consistencyNumber);
}
public final void persistCourse(String id, String name) {
final Ref ref = COURSE_TABLE.indexGet(id);
if (ref == null)
COURSE_TABLE.insert(id, name, null);
else {
COURSE_TABLE.update(ref, CourseTable.NAME.value(name));
}
}
private final Ref insertContact(Contact contact) {
return CONTACT_TABLE.insert(contact.getPhoneNumber(), contact.getEmail(),
contact.getStreet(), contact.getCity(), contact.getState(),
contact.getPostalCode(), contact.getCountry());
}
private final void updateContact(Ref ref, Contact contact) {
final Row stored = CONTACT_TABLE.get(ref);
final List<ColVal<?>> colVals = new ArrayList<>();
if (!Objects.equals(contact.getPhoneNumber(), stored.get(PHONE_NUMBER))) {
colVals.add(PHONE_NUMBER.value(contact.getPhoneNumber()));
}
if (!contact.getEmail().equals(stored.get(EMAIL))) {
colVals.add(EMAIL.value(contact.getEmail()));
}
if (!contact.getStreet().equals(stored.get(STREET))) {
colVals.add(STREET.value(contact.getStreet()));
}
if (!contact.getCity().equals(stored.get(CITY))) {
colVals.add(CITY.value(contact.getCity()));
}
if (!contact.getState().equals(stored.get(STATE))) {
colVals.add(STATE.value(contact.getState()));
}
if (Integer.compare(contact.getPostalCode(),
stored.get(POSTAL_CODE)) != 0) {
colVals.add(POSTAL_CODE.value(contact.getPostalCode()));
}
if (!Objects.equals(contact.getCountry(), stored.get(COUNTRY))) {
colVals.add(COUNTRY.value(contact.getCountry()));
}
CONTACT_TABLE.update(ref, colVals.toArray(new ColVal<?>[colVals.size()]));
}
public final void persistStudent(int studentNumber, String name,
Contact contact, List<String> courses) {
// Get row references of courses.
final Ref[] courseRefs = new Ref[courses.size()];
for (int i = 0; i < courseRefs.length; i++) {
courseRefs[i] = COURSE_TABLE.get(COURSE_TABLE.indexGet(
courses.get(i))).getRef();
}
final Ref ref = STUDENT_TABLE.indexGet(studentNumber);
if (ref == null)
STUDENT_TABLE.insert(studentNumber, name, insertContact(contact),
courseRefs);
else {
updateContact(STUDENT_TABLE.getValue(ref, StudentTable.CONTACT),
contact);
STUDENT_TABLE.update(ref, StudentTable.NAME.value(name),
StudentTable.COURSES.value(courseRefs));
}
}
public final void persistTeacher(String name, BigInteger salary,
Contact contact, List<String> courses) {
// Get row references of courses.
final Ref[] courseRefs = new Ref[courses.size()];
for (int i = 0; i < courseRefs.length; i++) {
courseRefs[i] = COURSE_TABLE.get(COURSE_TABLE.indexGet(
courses.get(i))).getRef();
}
Ref ref = TEACHER_TABLE.indexGet(name);
if (ref == null)
ref = TEACHER_TABLE.insert(name, salary, insertContact(contact),
courseRefs);
else {
updateContact(TEACHER_TABLE.getValue(ref, TeacherTable.CONTACT),
contact);
TEACHER_TABLE.update(ref, TeacherTable.SALARY.value(salary),
TeacherTable.COURSES.value(courseRefs));
}
// ref != null
// Update the link from course to teacher.
for (Ref courseRef : courseRefs) {
COURSE_TABLE.update(courseRef, CourseTable.TEACHER.value(ref));
}
}
public final void deleteCourse(String id) {
COURSE_TABLE.delete(id);
}
public final void deleteStudent(int studentNumber) {
final Ref contactRef = STUDENT_TABLE.getValue(
STUDENT_TABLE.indexGet(studentNumber),
StudentTable.CONTACT);
STUDENT_TABLE.delete(studentNumber);
CONTACT_TABLE.delete(contactRef);
}
public final void deleteTeacher(String name) {
final Row row = TEACHER_TABLE.get(TEACHER_TABLE.indexGet(name),
TeacherTable.CONTACT, TeacherTable.COURSES);
// Release link from course to teacher.
for (Ref courseRef : row.get(TeacherTable.COURSES)) {
COURSE_TABLE.update(courseRef, CourseTable.TEACHER.value(null));
}
TEACHER_TABLE.delete(name);
CONTACT_TABLE.delete(row.get(TeacherTable.CONTACT));
}
public final Course getCourse(String id) {
final Row row = COURSE_TABLE.get(COURSE_TABLE.indexGet(id));
return new Course(row.get(CourseTable.ID),
row.get(CourseTable.NAME),
row.get(CourseTable.TEACHER));
}
public final Student getStudent(int studentNumber) {
final Row row = STUDENT_TABLE.get(STUDENT_TABLE.indexGet(studentNumber));
return new Student(row.get(StudentTable.STUDENT_NUMBER),
row.get(StudentTable.NAME),
row.get(StudentTable.CONTACT),
row.get(StudentTable.COURSES));
}
public final Teacher getTeacher(String name) {
final Row row = TEACHER_TABLE.get(TEACHER_TABLE.indexGet(name));
return new Teacher(row.get(TeacherTable.NAME),
row.get(TeacherTable.SALARY),
row.get(TeacherTable.CONTACT),
row.get(TeacherTable.COURSES));
}
public final Unit openUnit() {
return db.openUnit();
}
public final ReadZone openReadZone() {
return db.openReadZone();
}
@Override
public void close() {
db.close();
}
}
example.pl.Person
public abstract class Person {
private final String name;
private final Ref contactRef;
private final Ref[] courseRefs;
Person(String name, Ref contactRef, Ref[] courseRefs) {
this.name = name;
this.contactRef = contactRef;
this.courseRefs = courseRefs;
}
public final String getName() {
return name;
}
public final Contact getContact() {
final Row row = CONTACT_TABLE.get(contactRef);
return new Contact(row.get(PHONE_NUMBER), row.get(EMAIL), row.get(STREET),
row.get(CITY), row.get(STATE), row.get(POSTAL_CODE),
row.get(COUNTRY));
}
public final List<String> getCourses() {
final int n = courseRefs.length;
final List<String> courses = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
courses.add(COURSE_TABLE.getValue(courseRefs[i], CourseTable.ID));
}
return courses;
}
}
example.pl.Student
public final class Student extends Person {
private final int studentNumber;
Student(int studentNumber, String name, Ref contactRef, Ref[] courseRefs) {
super(name, contactRef, courseRefs);
this.studentNumber = studentNumber;
}
public final int getStudentNumber() {
return studentNumber;
}
}
example.pl.Teacher
public final class Teacher extends Person {
private final BigInteger salary;
Teacher(String name, BigInteger salary, Ref contactRef, Ref[] courseRefs) {
super(name, contactRef, courseRefs);
this.salary = salary;
}
public final BigInteger getSalary() {
return salary;
}
}
example.Populator
public final class Populator {
public static final void run(Path layoutFile) {
try (EduPL pl = new EduPL(layoutFile, -1, false, 0)) {
pl.persistCourse("CSM", "Certified ScrumMaster");
pl.persistCourse("BOSS", "Chef Essentials");
pl.persistCourse("SCF", "Selenium and Cucumber Foundation");
pl.persistCourse("CFR", "Cybersec First Responder");
pl.persistCourse("CDPC", "Configuring and Deploying a Private Cloud");
pl.persistCourse("LSSGBP", "Lean Six Sigma Green Belt Practitioner");
pl.persistCourse("PE", "Puppet Essentials");
pl.persistCourse("RHOSA", "Red Hat OpenStack Administration II");
pl.persistCourse("HDJ", "HDP Developer: Java");
pl.persistCourse("LBSP", "Linux BASH Shell Programming");
pl.persistCourse("MBS", "Mastering BASH Scripts");
pl.persistCourse("P3P", "Python 3 Programming");
pl.persistCourse("ROR", "Ruby on Rails");
pl.persistCourse("CEH", "Certified Ethical Hacker v9");
pl.persistCourse("CSHARP", "The C# Programming Language");
pl.persistCourse("TA", "Tomcat Administration");
pl.persistCourse("CBC", "CCNA Bootcamp");
pl.persistCourse("PMBB", "Pestle, Most and Boston Box");
pl.persistStudent(1928, "James Smith", new Contact("234-911-5678",
"jsmith@example.com", "812 Main", "Barnsby", "NY",
48253, "USA"), Arrays.asList("P3P", "TA"));
pl.persistStudent(362, "Maria Garcia", new Contact("123-234-5678",
"m.garcia@example.com", "45 Elm", "Summercity", "CA",
15435, null), Arrays.asList("BOSS"));
pl.persistStudent(834, "David Jones", new Contact("845-611-7244",
"david.jones@example.com", "9 Washington",
"Springcity", "WK", 86342, "USA"),
Arrays.asList("LBSP", "CSHARP", "CSM"));
pl.persistStudent(1583, "Sarah Williams", new Contact("123-847-7541",
"s.williams@example.com", "63 Pine", "Autumncity",
"ZH", 25317, "Canada"),
Arrays.asList("CBC", "CSHARP", "LSSGBP", "TA"));
pl.persistStudent(74, "Nigel Lee", new Contact(null,
"nigel@example.com", "13 Howard", "Wintercity", "RO",
74682, "Mexico"), Arrays.asList("RHOSA", "TA"));
pl.persistStudent(348, "Jessica Hernandez", new Contact("184-584-9354",
"jh@example.com", "428 Market","Orangecity", "OA",
24381, "USA"), Arrays.asList("PE"));
pl.persistTeacher("Jane Smith", new BigInteger("76343"), new Contact(
"487-211-6824", "jane@example.com", "45 Pine",
"Autumncity", "ZH", 25317, "Canada"),
Arrays.asList("RHOSA", "P3P", "TA"));
pl.persistTeacher("Bill Johnson", new BigInteger("23546"), new Contact(
"184-754-2546", "johnsonbill@example.com", "32 Pine",
"Applecity", "IS", 84672, "USA"),
Arrays.asList("ROR"));
pl.persistTeacher("Amy Turner", new BigInteger("48623"), new Contact(
null, "amy.turner@example.com", "561 Hazle",
"Cherrycity", "DK", 56214, null),
Arrays.asList("LSSGBP", "SCF"));
pl.persistTeacher("Marc Vernes", new BigInteger("47732"), new Contact(
"148-532-4256", "marcV@example.com", "47 Eleven",
"Cherrycity", "DK", 56214, "USA"),
Arrays.asList("CEH", "PMBB"));
}
}
}