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")); } } }