Make generation of xml:id attribute configurable through an adapter
authorDenis Laxalde <denis.laxalde@logilab.fr>
Tue, 19 Jun 2018 15:42:06 +0200
changeset 2956 d945aaa3f821
parent 2953 97b06a36d104
child 2957 b468ae71bdd8
Make generation of xml:id attribute configurable through an adapter The idea is to have the generation of xml:id attribute configurable based on entity context. So we create an entity adapter IXmlId that default to the current implementation. This will be extended in cubicweb-saem_ref where we'd want to use the ARK identifier to produce this xml:id attribute. In profile_generation module, we rename eid2xmlid function as xmlid and make it accept an entity.
cubicweb_seda/entities/__init__.py
cubicweb_seda/entities/profile_generation.py
test/test_profile_generation.py
--- a/cubicweb_seda/entities/__init__.py	Tue Feb 20 16:28:20 2018 +0100
+++ b/cubicweb_seda/entities/__init__.py	Tue Jun 19 15:42:06 2018 +0200
@@ -20,6 +20,7 @@
 from logilab.common.registry import objectify_predicate
 
 from cubicweb.predicates import is_instance
+from cubicweb.view import EntityAdapter
 from cubicweb_compound.entities import IContainer, IContained, IClonableAdapter
 
 from .. import seda_profile_container_def
@@ -202,6 +203,17 @@
                 clones[data_object].cw_set(**{rtype: transfer})
 
 
+class XmlIdAdapter(EntityAdapter):
+    """Adapter for entity to be inserted in XML document and for which an
+    xml:id attribute needs to be generated.
+    """
+    __regid__ = 'IXmlId'
+    __select__ = is_instance('Any')
+
+    def id(self):
+        return u'id{}'.format(self.entity.eid)
+
+
 def registration_callback(vreg):
     vreg.register_all(globals().values(), __name__)
     vreg.register(IContainer.build_class('SEDAArchiveTransfer'))
--- a/cubicweb_seda/entities/profile_generation.py	Tue Feb 20 16:28:20 2018 +0100
+++ b/cubicweb_seda/entities/profile_generation.py	Tue Jun 19 15:42:06 2018 +0200
@@ -100,9 +100,9 @@
     return concept.label()
 
 
-def eid2xmlid(eid):
-    """Return a value usable as ID/IDREF for the given eid."""
-    return 'id' + text_type(eid)
+def xmlid(entity):
+    """Return a value usable as ID/IDREF for the given entity."""
+    return entity.cw_adapt_to('IXmlId').id()
 
 
 def serialize(value, build_url):
@@ -115,7 +115,7 @@
         if value.cw_etype == 'Concept':
             return _concept_value(value, 'seda-2')
         if _internal_reference(value):
-            return eid2xmlid(value.eid)
+            return xmlid(value)
         return None  # intermediary entity
     if isinstance(value, bool):
         return 'true' if value else 'false'
@@ -785,7 +785,7 @@
             cardinality=archive_unit.user_cardinality,
             documentation=archive_unit.user_annotation,
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
-            extra_attributes={'xml:id': eid2xmlid(archive_unit.eid)},
+            extra_attributes={'xml:id': xmlid(archive_unit)},
         )
         transfer = archive_unit.cw_adapt_to('ITreeBase').parent()
         self.xsd_archival_agreement(archive_node, transfer)
@@ -814,7 +814,7 @@
             cardinality=archive_unit.user_cardinality,
             documentation=archive_unit.user_annotation,
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
-            extra_attributes={'xml:id': eid2xmlid(archive_unit.eid)},
+            extra_attributes={'xml:id': xmlid(archive_unit)},
         )
         content_entity = self.archive_unit_content(archive_unit)
         self.element_schema(ao_node, 'Name', 'udt:TextType',
@@ -841,7 +841,7 @@
             cardinality=data_object.user_cardinality,
             documentation=data_object.user_annotation,
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
-            extra_attributes={'xml:id': eid2xmlid(data_object.eid)},
+            extra_attributes={'xml:id': xmlid(data_object)},
         )
 
         self.xsd_system_id(document_node, data_object)
@@ -1088,7 +1088,7 @@
                     xsd_attributes=[XAttr('when', 'udt:DateType',
                                           cardinality=when_card),
                                     XAttr('languageID', 'xsd:language')],
-                    extra_attributes={'xml:id': eid2xmlid(item.eid)},
+                    extra_attributes={'xml:id': xmlid(item)},
                 )
 
     def xsd_originating_agency(self, parent, content):
@@ -1117,7 +1117,7 @@
             cardinality=keyword.user_cardinality,
             documentation=keyword.user_annotation,
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
-            extra_attributes={'xml:id': eid2xmlid(keyword.eid)},
+            extra_attributes={'xml:id': xmlid(keyword)},
         )
         content = keyword.keyword_content
         url = None
@@ -1218,7 +1218,7 @@
             cardinality=archive_unit.user_cardinality,
             documentation=archive_unit.user_annotation,
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
-            extra_attributes={'xml:id': eid2xmlid(archive_unit.eid)},
+            extra_attributes={'xml:id': xmlid(archive_unit)},
         )
         transfer = archive_unit.cw_adapt_to('ITreeBase').parent()
         self.xsd_archival_agreement(archive_node, transfer)
@@ -1259,7 +1259,7 @@
             parent, 'Document',
             cardinality=data_object.user_cardinality,
             documentation=data_object.user_annotation,
-            extra_attributes={'xml:id': eid2xmlid(data_object.eid)},
+            extra_attributes={'xml:id': xmlid(data_object)},
             xsd_attributes=[XAttr('Id', 'xsd:ID')],
         )
         self.xsd_attachment(document_node, data_object)
@@ -1294,7 +1294,7 @@
                 cardinality=item.user_cardinality,
                 documentation=item.user_annotation,
                 xsd_attributes=[XAttr('languageID', 'xsd:language')],
-                extra_attributes={'xml:id': eid2xmlid(item.eid)},
+                extra_attributes={'xml:id': xmlid(item)},
             )
 
     def xsd_integrity(self, parent, data_object):
@@ -1306,7 +1306,7 @@
                                                   fixed_value=_concept_value(
                                                       algorithm, self.concepts_language))])
         self.element_schema(integrity, 'UnitIdentifier', 'qdt:ArchivesIDType',
-                            default_value=eid2xmlid(data_object.eid))
+                            default_value=xmlid(data_object))
 
     system_id_tag_name = 'Identification'
     # in SEDA 0.2, ArchiveObject tag name is 'Contains' (as for Archive)
@@ -1411,7 +1411,7 @@
 def _simple_path_target_values(entity, rtype, role, target_etype):
     if target_etype in BASE_TYPES:
         if rtype == 'id':
-            return [(None, eid2xmlid(entity.eid))]
+            return [(None, xmlid(entity))]
         return [(None, getattr(entity, rtype, None))]
     targets = entity.related(rtype, role, entities=True)
     rschema = entity._cw.vreg.schema.rschema
--- a/test/test_profile_generation.py	Tue Feb 20 16:28:20 2018 +0100
+++ b/test/test_profile_generation.py	Tue Jun 19 15:42:06 2018 +0200
@@ -673,6 +673,7 @@
             cnx.commit()
         self.transfer_eid = transfer.eid
         self.bdo_eid = bdo.eid
+        self.bdo_xmlid = bdo.cw_adapt_to('IXmlId').id()
         self.au_eid = unit.eid
 
     def test_profile1(self):
@@ -698,8 +699,7 @@
         for attrdef in self.xpath(root, '//xs:attribute[@xml:id]'):
             self.assertEqual(attrdef[0]['type'], 'ID')
         # ensure they are properly referenced using 'default' attribute
-        xmlid = pg.eid2xmlid(self.bdo_eid)
-        references = self.xpath(root, '//rng:element[@a:defaultValue="{}"]'.format(xmlid))
+        references = self.xpath(root, '//rng:element[@a:defaultValue="{}"]'.format(self.bdo_xmlid))
         self.assertEqual(len(references), 1)
         self.assertEqual(references[0].attrib['name'], 'DataObjectReferenceId')
         for reference_id in self.xpath(root, '//rng:element[@name="DataObjectReferenceId"]'):