better support for sliver urns
[sfa.git] / sfa / util / xrn.py
index d5410ab..f2ab48b 100644 (file)
@@ -23,7 +23,7 @@
 \r
 import re\r
 \r
-from sfa.util.faults import *\r
+from sfa.util.faults import SfaAPIError\r
 \r
 # for convenience and smoother translation - we should get rid of these functions eventually \r
 def get_leaf(hrn): return Xrn(hrn).get_leaf()\r
@@ -79,7 +79,7 @@ class Xrn:
     # A better alternative than childHRN.startswith(parentHRN)\r
     # e.g. hrn_is_auth_for_hrn('a\.b', 'a\.b.c.d') -> True,\r
     # but hrn_is_auth_for_hrn('a', 'a\.b.c.d') -> False\r
-    # Also hrn_is_uauth_for_hrn('a\.b.c.d', 'a\.b.c.d') -> True\r
+    # Also hrn_is_auth_for_hrn('a\.b.c.d', 'a\.b.c.d') -> True\r
     @staticmethod\r
     def hrn_is_auth_for_hrn(parenthrn, hrn):\r
         if parenthrn == hrn:\r
@@ -89,16 +89,21 @@ class Xrn:
                 return True\r
         return False\r
 \r
+    ########## basic tools on URNs\r
     URN_PREFIX = "urn:publicid:IDN"\r
+    URN_PREFIX_lower = "urn:publicid:idn"\r
+\r
+    @staticmethod\r
+    def is_urn (text):\r
+        return text.lower().startswith(Xrn.URN_PREFIX_lower)\r
 \r
-    ########## basic tools on URNs\r
     @staticmethod\r
     def urn_full (urn):\r
-        if urn.startswith(Xrn.URN_PREFIX): return urn\r
-        else: return Xrn.URN_PREFIX+URN\r
+        if Xrn.is_urn(urn): return urn\r
+        else: return Xrn.URN_PREFIX+urn\r
     @staticmethod\r
     def urn_meaningful (urn):\r
-        if urn.startswith(Xrn.URN_PREFIX): return urn[len(Xrn.URN_PREFIX):]\r
+        if Xrn.is_urn(urn): return urn[len(Xrn.URN_PREFIX):]\r
         else: return urn\r
     @staticmethod\r
     def urn_split (urn):\r
@@ -111,22 +116,33 @@ class Xrn:
     # self.type\r
     # self.path\r
     # provide either urn, or (hrn + type)\r
-    def __init__ (self, xrn, type=None):\r
+    def __init__ (self, xrn, type=None, id=None):\r
         if not xrn: xrn = ""\r
         # user has specified xrn : guess if urn or hrn\r
-        if xrn.startswith(Xrn.URN_PREFIX):\r
+        self.id = id\r
+        if Xrn.is_urn(xrn):\r
             self.hrn=None\r
             self.urn=xrn\r
+            if id:\r
+                self.urn = "%s:%s" % (self.urn, str(id))\r
             self.urn_to_hrn()\r
         else:\r
             self.urn=None\r
             self.hrn=xrn\r
             self.type=type\r
             self.hrn_to_urn()\r
+        self._normalize()\r
 # happens all the time ..\r
 #        if not type:\r
 #            debug_logger.debug("type-less Xrn's are not safe")\r
 \r
+    def __repr__ (self):\r
+        result="<XRN u=%s h=%s"%(self.urn,self.hrn)\r
+        if hasattr(self,'leaf'): result += " leaf=%s"%self.leaf\r
+        if hasattr(self,'authority'): result += " auth=%s"%self.authority\r
+        result += ">"\r
+        return result\r
+\r
     def get_urn(self): return self.urn\r
     def get_hrn(self): return self.hrn\r
     def get_type(self): return self.type\r
@@ -144,21 +160,35 @@ class Xrn:
         self._normalize()\r
         return self.leaf\r
 \r
-    def get_authority_hrn(self): \r
+    def get_authority_hrn(self):\r
         self._normalize()\r
         return '.'.join( self.authority )\r
     \r
     def get_authority_urn(self): \r
         self._normalize()\r
         return ':'.join( [Xrn.unescape(x) for x in self.authority] )\r
-    \r
+\r
+    def set_authority(self, authority):\r
+        """\r
+        update the authority section of an existing urn\r
+        """\r
+        authority_hrn = self.get_authority_hrn()\r
+        if not authority_hrn.startswith(authority):\r
+            hrn = ".".join([authority,authority_hrn, self.get_leaf()])\r
+        else:\r
+            hrn = ".".join([authority_hrn, self.get_leaf()])\r
+            \r
+        self.hrn = hrn \r
+        self.hrn_to_urn()\r
+        self._normalize()\r
+        \r
     def urn_to_hrn(self):\r
         """\r
         compute tuple (hrn, type) from urn\r
         """\r
         \r
 #        if not self.urn or not self.urn.startswith(Xrn.URN_PREFIX):\r
-        if not self.urn.startswith(Xrn.URN_PREFIX):\r
+        if not Xrn.is_urn(self.urn):\r
             raise SfaAPIError, "Xrn.urn_to_hrn"\r
 \r
         parts = Xrn.urn_split(self.urn)\r
@@ -170,13 +200,22 @@ class Xrn:
             # or completely change how record types are generated/stored   \r
             if name != 'sa':\r
                 type = type + "+" + name\r
-\r
+            name =""\r
+        else:\r
+            name = parts.pop(len(parts)-1)\r
         # convert parts (list) into hrn (str) by doing the following\r
         # 1. remove blank parts\r
         # 2. escape dots inside parts\r
         # 3. replace ':' with '.' inside parts\r
-        # 3. join parts using '.' \r
-        hrn = '.'.join([Xrn.escape(part).replace(':','.') for part in parts if part]) \r
+        # 3. join parts using '.'\r
+        hrn = '.'.join([Xrn.escape(part).replace(':','.') for part in parts if part])\r
+        # dont replace ':' in the name section\r
+        if name:\r
+            parts = name.split(':')\r
+            if len(parts) > 1:\r
+                self.id = ":".join(parts[1:])\r
+                name = parts[0]    \r
+            hrn += '.%s' % Xrn.escape(name) \r
 \r
         self.hrn=str(hrn)\r
         self.type=str(type)\r
@@ -187,27 +226,34 @@ class Xrn:
         """\r
 \r
 #        if not self.hrn or self.hrn.startswith(Xrn.URN_PREFIX):\r
-        if self.hrn.startswith(Xrn.URN_PREFIX):\r
+        if Xrn.is_urn(self.hrn):\r
             raise SfaAPIError, "Xrn.hrn_to_urn, hrn=%s"%self.hrn\r
 \r
         if self.type and self.type.startswith('authority'):\r
-            self.authority = Xrn.hrn_split(self.hrn)\r
+            self.authority = Xrn.hrn_auth_list(self.hrn)\r
+            leaf = self.get_leaf()\r
+            #if not self.authority:\r
+            #    self.authority = [self.hrn]\r
             type_parts = self.type.split("+")\r
             self.type = type_parts[0]\r
             name = 'sa'\r
             if len(type_parts) > 1:\r
                 name = type_parts[1]\r
+            auth_parts = [part for part in [self.get_authority_urn(), leaf] if part]\r
+            authority_string = ":".join(auth_parts)\r
         else:\r
             self.authority = Xrn.hrn_auth_list(self.hrn)\r
             name = Xrn.hrn_leaf(self.hrn)\r
-\r
-        authority_string = self.get_authority_urn()\r
+            authority_string = self.get_authority_urn()\r
 \r
         if self.type == None:\r
             urn = "+".join(['',authority_string,Xrn.unescape(name)])\r
         else:\r
             urn = "+".join(['',authority_string,self.type,Xrn.unescape(name)])\r
-        \r
+\r
+        if self.id:\r
+            urn = "%s:%s" % (urn, self.id)        \r
+\r
         self.urn = Xrn.URN_PREFIX + urn\r
 \r
     def dump_string(self):\r