concept G22Variable extends ConceptWithChangeListeners is IPersistenceInfo { settableWithVar S name; volatile O value; settableWithVar bool persistent; // big = value is stored in separate file settableWithVar bool big; // field "value" is persisted iff field "persistent" is set public Map _persistenceInfo() { ret litmap(value := persistent && !big); } public simplyCached FieldVar varValue() { ret new FieldVar(this, "value", () -> value(), value -> value(value)); } void setValueIfNull(O defaultValue) { if (defaultValue != null && value == null) value(defaultValue); } O get aka value() { if (value != null) ret value; if (big) ret getBigValue(); ret value; } G22Utils g22utils() { ret main g22utils(_concepts()); } File bigFile() { ret newFile(assertNotNull(g22utils().projectDir()), id + "-" + sanitizeFileName(name) + ".structgz"); } O getBigValue() { File f = bigFile(); ret value = unstructureGZFile(f, g22utils().classFinder()); } void setBigValue(O value) { if (value == null) { if (hasBigValue()) { deleteBigValue(); change(); } } else { File f = bigFile(); saveGZStructureToFile(f, value); change(); } } void deleteBigValue() { deleteFile(bigFile()); } bool hasBigValue() { ret fileExists(bigFile()); } void makeBig { if (big) ret; setBigValue(value); big(true); persistent(true); } void makeSmall { if (!big) ret; get(); // will cache the value big(false); deleteBigValue(); } selfType value aka setValue(O o) { if (big) setBigValue(o); else if (!eq(value, o)) { value = o; change(); } this; } bool notNull() { ret big ? hasBigValue() : value != null; } void unload() { if (big) value = null; } }