
// // Copyright (c) 2008, John Sublett // Licensed under the Academic Free License version 3.0 // // History: // 23 Mar 08 John Sublett Creation // ** ** HavenNamespace manages the Namespace of a haven service. ** ** See `docLib::Haven`. ** const class HavenNamespace : Namespace { // TODO - no documentation new make() { } // TODO - no documentation new makeFor(Str havenName) { this.havenName = havenName } // TODO - no documentation HavenService findHaven() { return (HavenService)Thread.find(havenName) } ** ** Create the specified object in the namespace. For ** haven the uri must be null. ** override Uri create(Uri uri, Obj obj) { if (uri != null) throw ArgErr.make("Uri must be null for new haven objects.") haven := findHaven haven.open try { return haven.create(obj) } finally { haven.close } } ** ** Get the object identified by the specified uri. ** override Obj get(Uri objUri, Bool checked := true) { haven := findHaven haven.open try { relUri := objUri.relTo(uri) if (!relUri.isRel) throw UnresolvedErr.make("Uri not in namespace: $objUri") // at this point the uri is of the form 'pod/Type' or 'pod/Type/id' objType := typeFromUri(relUri) if (objType == null) { if (checked) throw UnresolvedErr.make("Not found: $objUri") else return null } if (!haven.typeTableExists(objType)) throw UnresolvedErr.make("Type table does not exist: $objType") if (relUri.path.size == 2) return ObjTable.make(haven, objType) objId := idFromUri(haven, objType, relUri) if (objId == null) { if (checked) throw HavenErr.make("Not found: $objUri") else return null } try { return haven.read(objType, objId) } catch(Err e) { if (checked) throw e else return null } } finally { haven.close } } ** ** Update the specified object mapped to the specified uri. ** override Void put(Uri uri, Obj obj) { haven := findHaven haven.open try { // get existing, if not found UnresolvedErr will be thrown existing := get(uri) // make sure keys are equal because keys cannot be modified table := haven.table(obj.type) keyCols := table.keyColumns keyCols.each |ColDef col| { if (col.field.get(existing) != col.field.get(obj)) throw HavenErr.make("Key columns cannot be updated on a put.") } haven.update(obj) } finally { haven.close } } ** ** Delete the object with the specified uri. ** override Void delete(Uri objUri) { haven := findHaven haven.open try { relUri := objUri.relTo(uri) if (!relUri.isRel) throw UnresolvedErr.make("Uri not in namespace: $objUri") objType := typeFromUri(relUri) if (objType == null) throw UnresolvedErr.make("Not found: $objUri") objId := idFromUri(haven, objType, relUri) if (objId == null) throw UnresolvedErr.make("Not found: $objUri") result := haven.deleteById(objType, objId) if (!result) throw UnresolvedErr.make("Not found: $objUri") } finally { haven.close } } ////////////////////////////////////////////////////////////////////////// // Uri mapping ////////////////////////////////////////////////////////////////////////// internal Type typeFromUri(Uri relUri) { if (relUri.path.size < 2) return null podName := relUri.path[0] typeName := relUri.path[1] return Pod.find(podName).findType(typeName) } internal Obj idFromUri(HavenService haven, Type objType, Uri relUri) { if (relUri.path.size < 3) return null idStr := relUri.path[2] tableDef := haven.table(objType) keyCol := tableDef.keyColumns[0] if (keyCol.field.of == Str.type) return idStr else { method := keyCol.field.of.method("fromStr") return method.call1(idStr) } } ** ** Get the uri for the specified object. ** Uri objToUri(Obj obj, HavenService haven := null) { if (haven == null) haven = findHaven id := haven.table(obj.type).keyValue(obj) if (uri == null) return (obj.type.pod.name + "/" + obj.type.name + "/" + id).toUri else return (uri.toStr + "/" + obj.type.pod.name + "/" + obj.type.name + "/" + id).toUri } ** ** Get the uri for the object with the specified type and id. ** Uri idToUri(Type objType, Obj id) { if (uri == null) return (objType.pod.name + "/" + objType.name + "/" + id).toUri else return (uri.toStr + "/" + objType.pod.name + "/" + objType.name + "/" + id).toUri } ////////////////////////////////////////////////////////////////////////// // Fields ////////////////////////////////////////////////////////////////////////// // TODO - no documentation const Str havenName := "haven" }