public static Database db() { assert U.must(db != null, "Database not initialized!"); return db; }
private void failIfReadonlyTx() { U.must(!data.insideTx.get() || !data.txReadonly.get(), "Cannot modify data inside read-only transaction!"); }
public static <T> T[] subarray(T[] arr, int from, int to) { int start = from >= 0 ? from : arr.length + from; int end = to >= 0 ? to : arr.length + to; if (start < 0) { start = 0; } if (end > arr.length - 1) { end = arr.length - 1; } U.must(start <= end, "Invalid range: expected form <= to!"); int size = end - start + 1; T[] part = Arrays.copyOf(arr, size); System.arraycopy(arr, start, part, 0, size); return part; }
protected long getSingleId() { U.must(ids.size() <= 1); return !ids.isEmpty() ? ids.iterator().next() : -1; }
/** * e.g. IF PersonService extends DAO<Person> THEN entity == Person */ private static Class<?> inferEntityType(Class<? extends DAO<?>> daoClass) { U.must(daoClass.getSuperclass() == DAO.class, "Expected DAO to be superclass of %s, but found: %s!", daoClass, daoClass.getSuperclass()); ParameterizedType genDao = Cls.generic(daoClass.getGenericSuperclass()); U.must(genDao != null && genDao.getActualTypeArguments().length > 0, "Cannot infer entity type for: %s", daoClass); Type arg = genDao.getActualTypeArguments()[0]; return Cls.clazz(arg); }
private static Rel rel(Method method) { Rel rel = Metadata.get(method.getAnnotations(), Rel.class); U.must(rel != null, "@Relation is required for method: %s", method); return rel; }
private void txRollback() { data.ids.set(data.txIdCounter.get()); for (Entry<Long, Rec> e : data.txChanges.entrySet()) { Long id = e.getKey(); Rec value = e.getValue(); U.must(value != null, "Cannot have null value!"); data.data.put(id, value); } for (Entry<Long, Object> e : data.txInsertions.entrySet()) { // rollback insert operation Long id = e.getKey(); Object value = e.getValue(); U.must(value == INSERTION, "Expected insertion mode!"); Rec inserted = data.data.remove(id); U.must(inserted != null, "Cannot have null insertion!"); } }
public DbColumn<?> column(Method method) { U.must(DbColumn.class.isAssignableFrom(method.getReturnType())); String name = method.getName(); DbColumn<?> res = columns.get(name); if (res == null) { Class<Object> colType = Cls.clazz(Cls.generic(method.getGenericReturnType()).getActualTypeArguments()[0]); DbColumn<Object> value = DB.column(values, method.getName(), colType); DbColumn<?> old = columns.putIfAbsent(name, value); return U.or(old, value); } return res; }
public Map<String, Object> loadMetadata(InputStream in) { globalLock(); try { BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line = reader.readLine(); U.must(line != null, "Missing meta-data at the first line in the database file!"); Map<String, Object> meta = U.map(); data.serializer.deserialize(line.getBytes(), meta); reader.close(); return meta; } catch (IOException e) { throw new RuntimeException("Cannot load meta-data from database!", e); } finally { globalUnlock(); } }
@Override public Object entity(String rql, Object... args) { String[] parts = rql.split(" "); String entityName = U.capitalized(parts[0]); Class<?> entityType = getEntityType(entityName); U.must(entityType != null, "Cannot find entity '%s'!", entityName); Map<String, Object> properties = U.map(); if (parts.length > 1) { String[] props = rql.substring(entityName.length() + 1).split("\\s*\\,\\s*"); int argIndex = 0; for (String prop : props) { String[] kv = prop.trim().split("\\s*=\\s*"); String key = kv[0]; Object value; if (kv.length > 1) { value = kv[1].equals("?") ? args[argIndex++] : kv[1]; } else { value = true; } properties.put(key, value); } } return entity(entityType, properties); }
U.must(data.aOrB.compareAndSet(isA, !isA), "DB persistence file switching error!");
private void resolveDoubleFileInconsistency() { String file1 = currentFile().getName(); String file2 = otherFile().getName(); Log.warn("The database was left in inconsistent state, both files exist!", "file1", file1, "file2", file2); long modif1, modif2; try { modif1 = (Long) loadMetadata(new FileInputStream(currentFile())).get(META_TIMESTAMP); modif2 = (Long) loadMetadata(new FileInputStream(otherFile())).get(META_TIMESTAMP); } catch (FileNotFoundException e) { throw new RuntimeException(e); } U.must(modif1 != modif2, "Cannot determine which database file to remove, please remove the incorrect file manually!"); // delete the most recent file, since it wasn't written completely File recent = modif1 > modif2 ? currentFile() : otherFile(); Log.warn("The more recent database file is assumed incomplete, so it will be deleted!", "file", recent); recent.delete(); }
public static void initRelations(Object target) { for (Prop prop : Beany.propertiesOf(target.getClass()).select(ANNOTATED_DB_REL_PROPS)) { Rel rel = prop.getAnnotation(Rel.class); U.must(!U.isEmpty(rel.value()), "Relation name must be specified!"); Object value = prop.getRaw(target); if (value == null && !prop.isReadOnly()) { Class<?> type = prop.getType(); if (DbList.class.equals(type)) { prop.setRaw(target, DB.list(target, rel.value())); } else if (DbSet.class.equals(type)) { prop.setRaw(target, DB.set(target, rel.value())); } else if (DbRef.class.equals(type)) { prop.setRaw(target, DB.ref(target, rel.value())); } } } }