Commit 08354416 authored by Sylvain Thénault's avatar Sylvain Thénault
Browse files

Stop using unique identifier on archive unit and data objects

They have been introduced at a first glance to handle references during profile
generation as well as display of 'first class' element in the UI. The main problem is
that they clash when using the 'import archive unit' feature, since one may not
import the same unit twice without changing the id first. Another problem is
that their purpose is not clear to end-user.

This changeset remove the attribute, use eid instead during profile generation
and fix tests. UI and proper migration will be handled in later csets.

Related #16070476
parent b6a2ad4c7683
......@@ -115,13 +115,13 @@ class SEDARelationshipCodeListVersion(SEDAAnyEntity):
class SEDABinaryDataObject(SEDAAnyEntity):
__regid__ = 'SEDABinaryDataObject'
fetch_attrs, cw_fetch_order = fetch_config(['id', 'filename', 'user_cardinality', 'user_annotation'])
value_attr = 'id'
fetch_attrs, cw_fetch_order = fetch_config(['filename', 'user_cardinality', 'user_annotation'])
value_attr = None
class SEDAPhysicalDataObject(SEDAAnyEntity):
__regid__ = 'SEDAPhysicalDataObject'
fetch_attrs, cw_fetch_order = fetch_config(['id', 'user_cardinality', 'user_annotation'])
value_attr = 'id'
fetch_attrs, cw_fetch_order = fetch_config(['user_cardinality', 'user_annotation'])
value_attr = None
class SEDARelationship(SEDAAnyEntity):
__regid__ = 'SEDARelationship'
......@@ -145,8 +145,8 @@ class SEDACompressed(SEDAAnyEntity):
class SEDAArchiveUnit(SEDAAnyEntity):
__regid__ = 'SEDAArchiveUnit'
fetch_attrs, cw_fetch_order = fetch_config(['id', 'user_cardinality', 'user_annotation'])
value_attr = 'id'
fetch_attrs, cw_fetch_order = fetch_config(['user_cardinality', 'user_annotation'])
value_attr = None
class SEDAServiceLevel(SEDAAnyEntity):
__regid__ = 'SEDAServiceLevel'
......
......@@ -109,7 +109,7 @@ class ITreeBaseSimplifiedArchiveUnitAdapter(ITreeBaseArchiveUnitAdapter):
seq = self.entity.first_level_choice.content_sequence
assert seq is not None, self.entity # can't be None in simplified profile
for do in self._cw.execute(
'Any DO, DOID ORDERBY DOID WHERE DO id DOID, '
'Any DO, DOUA ORDERBY DOUA WHERE DO user_annotation DOUA, '
'REF seda_data_object_reference_id DO, '
'REF seda_data_object_reference SEQ, SEQ eid %(x)s',
{'x': seq.eid}).entities():
......
......@@ -72,6 +72,12 @@ def content_types(content_type):
return content_types
def _internal_reference(value):
"""Return True if the given value is a reference to an entity within the profile."""
return getattr(value, 'cw_etype', None) in ('SEDAArchiveUnit',
'SEDABinaryDataObject', 'SEDAPhysicalDataObject')
def _concept_value(concept, language):
"""Return string value to be inserted in a SEDA export for the given concept.
......@@ -92,6 +98,11 @@ def _concept_value(concept, language):
% (concept.eid, language))
def eid2xmlid(eid):
"""Return a value usable as ID/IDREF for the given eid."""
return 'id' + text_type(eid)
def serialize(value):
"""Return typed `value` as an XSD string."""
if value is None:
......@@ -101,9 +112,8 @@ def serialize(value):
return value.absolute_url()
if value.cw_etype == 'Concept':
return _concept_value(value, 'seda-2')
if hasattr(value, 'id'):
# value is something in the profile which has a id (e.g. archive unit, data object)
return value.id
if _internal_reference(value):
return eid2xmlid(value.eid)
return None # intermediary entity
if isinstance(value, bool):
return 'true' if value else 'false'
......@@ -508,7 +518,7 @@ class SEDA2XSDExport(SEDA2ExportAdapter):
self.element('xsd:attribute', attributes=attrs, parent=extension_element)
fixed_value = serialize(value)
if fixed_value is not None:
attr = 'default' if hasattr(value, 'id') else 'fixed'
attr = 'default' if _internal_reference(value) else 'fixed'
target_element.attrib[attr] = fixed_value
def concept_scheme_attribute(self, xselement, type_element, scheme):
......@@ -692,7 +702,7 @@ class SEDA2RelaxNGExport(RNGMixin, SEDA2ExportAdapter):
self._rng_attribute(occ.target, parent_element)
fixed_value = serialize(value)
if fixed_value is not None:
if hasattr(value, 'id'):
if _internal_reference(value):
profile_element.attrib[self.qname('a:defaultValue')] = fixed_value
self.element('rng:data', profile_element, {'type': 'NCName'})
else:
......@@ -1510,6 +1520,8 @@ def _path_target_values(entity, path):
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, getattr(entity, rtype, None))]
targets = entity.related(rtype, role, entities=True)
rschema = entity._cw.vreg.schema.rschema
......
......@@ -100,11 +100,6 @@ msgid ""
"considered."
msgstr ""
msgid ""
"Default identifier that will be used to handle references. This is not "
"necessarily the identifier that will appear in the final sheet."
msgstr ""
msgid "Entity"
msgstr ""
......@@ -4610,24 +4605,6 @@ msgctxt "SEDAFormatLitteral"
msgid "format_litteral"
msgstr ""
msgid "id"
msgstr ""
msgctxt "SEDAArchiveUnit"
msgid "id"
msgstr ""
msgctxt "SEDABinaryDataObject"
msgid "id"
msgstr ""
msgctxt "SEDAPhysicalDataObject"
msgid "id"
msgstr ""
msgid "identifier must be unique within a profile"
msgstr ""
msgid "import menu"
msgstr "import"
......
......@@ -104,14 +104,6 @@ msgstr ""
"L'historique de conservation est du texte en SEDA 0.2, un seul élément est "
"autorisé."
msgid ""
"Default identifier that will be used to handle references. This is not "
"necessarily the identifier that will appear in the final sheet."
msgstr ""
"Identifiant qui sera utilisé pour gérer les références à la génération du "
"profil - ce n'est pas nécessairement l'identifiant qui sera utilisé dans les "
"bordereaux de transfert"
msgid "Entity"
msgstr "Entité"
......@@ -4632,24 +4624,6 @@ msgctxt "SEDAFormatLitteral"
msgid "format_litteral"
msgstr ""
msgid "id"
msgstr "identifiant"
msgctxt "SEDAArchiveUnit"
msgid "id"
msgstr ""
msgctxt "SEDABinaryDataObject"
msgid "id"
msgstr ""
msgctxt "SEDAPhysicalDataObject"
msgid "id"
msgstr ""
msgid "identifier must be unique within a profile"
msgstr "un identifiant doit être unique au sein d'un profil"
msgid "import menu"
msgstr "importer"
......
......@@ -10,3 +10,6 @@ for concept in scheme.reverse_in_scheme:
commit()
sync_schema_props_perms(('SEDAArchiveTransfer', 'title', 'String'))
for etype in ('SEDAArchiveUnit', 'SEDABinaryDataObject', 'SEDAPhysicalDataObject'):
drop_attribute(etype, 'id')
......@@ -424,7 +424,6 @@ class relationship_code_list_version_relationship_code_list_version_to(RelationD
class SEDABinaryDataObject(EntityType):
u""""""
filename = String(fulltextindexed=True)
id = String(required=True, description=_('Default identifier that will be used to handle references. This is not necessarily the identifier that will appear in the final sheet.'), constraints=[RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, NOT S identity X)', msg=_('identifier must be unique within a profile'))])
class archive_transfer_binary_data_object(RelationDefinition):
......@@ -440,7 +439,6 @@ class archive_transfer_binary_data_object(RelationDefinition):
annotable=True)
class SEDAPhysicalDataObject(EntityType):
u""""""
id = String(required=True, description=_('Default identifier that will be used to handle references. This is not necessarily the identifier that will appear in the final sheet.'), constraints=[RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, NOT S identity X)', msg=_('identifier must be unique within a profile'))])
class archive_transfer_physical_data_object(RelationDefinition):
......@@ -535,7 +533,6 @@ class physical_data_object_relationship(RelationDefinition):
annotable=True)
class SEDAArchiveUnit(EntityType):
u""""""
id = String(required=True, description=_('Default identifier that will be used to handle references. This is not necessarily the identifier that will appear in the final sheet.'), constraints=[RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, NOT S identity X)', msg=_('identifier must be unique within a profile'))])
class archive_transfer_archive_unit(RelationDefinition):
......
......@@ -127,7 +127,7 @@ class CompatAnalyzerTC(CubicWebTC):
with self.admin_access.repo_cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'diagnosis testing')
unit, unit_alt, unit_alt_seq = create_archive_unit(transfer)
create_archive_unit(unit_alt_seq, archive_unit_reference=True, id=u'auref')
create_archive_unit(unit_alt_seq, archive_unit_reference=True)
doctor = transfer.cw_adapt_to('ISEDACompatAnalyzer')
cnx.commit()
......
......@@ -84,11 +84,10 @@ class ContainerTC(CubicWebTC):
self.assertEqual(bdo.container[0].eid, unit.eid)
# test clone without reparenting
cloned = cnx.create_entity(unit.cw_etype, id=u'hop', user_annotation=u'clone',
cloned = cnx.create_entity(unit.cw_etype, user_annotation=u'clone',
clone_of=unit)
cnx.commit()
cloned.cw_clear_all_caches()
self.assertEqual(cloned.id, 'hop')
self.assertEqual(cloned.user_annotation, 'clone')
cloned_unit_alt_seq = cloned.first_level_choice.content_sequence
self.assertEqual(cloned_unit_alt_seq.container[0].eid, cloned.eid)
......@@ -98,7 +97,7 @@ class ContainerTC(CubicWebTC):
# test clone with reparenting
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
cloned = cnx.create_entity(unit.cw_etype, id=u'hop',
cloned = cnx.create_entity(unit.cw_etype,
clone_of=unit,
seda_archive_unit=transfer)
cnx.commit()
......
......@@ -98,7 +98,7 @@ class ArchiveUnitContentTC(CubicWebTC):
cnx.create_entity('SEDATitle', seda_title=content)
cnx.commit()
# Check that everything goes fine when the hook is called
cnx.execute('DELETE SEDAArchiveUnit X WHERE X id "au1"')
au.cw_delete()
cnx.commit()
......
......@@ -90,8 +90,8 @@ class SEDAHTMLExportFuncTC(SEDAExportFuncTCMixIn, XmlTestMixin, CubicWebTC):
AttrDef(label='algorithm', card='mandatory', value=None),
AttrDef(label='filename', card='optional', value=None),
AttrDef(label='href', card='optional', value=None),
AttrDef(label='id', card='mandatory', value='au1'),
AttrDef(label='id', card='mandatory', value='bdo1'),
AttrDef(label='id', card='mandatory', value='id{}'.format(self.au_eid)),
AttrDef(label='id', card='mandatory', value='id{}'.format(self.bdo_eid)),
AttrDef(label='id', card='optional', value=None),
AttrDef(label='when', card='optional', value=None),
AttrDef(label='uri', card='optional', value=None),
......
......@@ -34,7 +34,7 @@ from logilab.common.decorators import cached
from cubicweb.devtools.testlib import CubicWebTC
from cubes.seda.xsd2yams import XSDMMapping
from cubes.seda.entities.profile_generation import _path_target_values
from cubes.seda.entities.profile_generation import _path_target_values, eid2xmlid
import testutils
......@@ -362,7 +362,7 @@ class SEDA2ExportTCMixIn(object):
def test_skipped_mandatory_complex(self):
with self.admin_access.client_cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
testutils.create_data_object(transfer, id=u"bdo1", filename=u'fixed.txt')
testutils.create_data_object(transfer, filename=u'fixed.txt')
profile = self.profile_etree(transfer)
fname = self.get_element(profile, 'Filename')
self.assertElementDefinition(fname, {'name': 'Filename',
......@@ -381,7 +381,7 @@ class SEDA2ExportTCMixIn(object):
def test_fileinfo_card(self):
with self.admin_access.client_cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
bdo = cnx.create_entity('SEDABinaryDataObject', id=u"bdo1",
bdo = cnx.create_entity('SEDABinaryDataObject',
seda_binary_data_object=transfer)
appname = cnx.create_entity('SEDACreatingApplicationName',
seda_creating_application_name=bdo)
......@@ -404,7 +404,7 @@ class SEDA2ExportTCMixIn(object):
def test_data_object_package_card(self):
with self.admin_access.client_cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'test profile')
bdo = cnx.create_entity('SEDABinaryDataObject', id=u"bdo1",
bdo = cnx.create_entity('SEDABinaryDataObject',
seda_binary_data_object=transfer)
profile = self.profile_etree(transfer)
......@@ -535,7 +535,7 @@ class SEDA2ExportTCMixIn(object):
some_concept = scheme.add_concept(label=u'md5 algorithm', language_code=u'en')
transfer = create('SEDAArchiveTransfer', title=u'test profile',
seda_message_digest_algorithm_code_list_version=scheme)
create('SEDABinaryDataObject', id=u"bdo1", user_cardinality=u'0..n',
create('SEDABinaryDataObject', user_cardinality=u'0..n',
seda_binary_data_object=transfer,
seda_algorithm=some_concept)
......@@ -615,7 +615,7 @@ class SEDAExportFuncTCMixIn(object):
reverse_seda_seq_access_rule_rule=access_rule)
create('SEDAStartDate', user_cardinality=u'0..1', seda_start_date=access_rule_seq)
# binary data object
bdo = testutils.create_data_object(transfer, id=u"bdo1", user_cardinality=u'0..n',
bdo = testutils.create_data_object(transfer, user_cardinality=u'0..n',
seda_algorithm=some_concept)
create('SEDAFormatLitteral', seda_format_litteral=bdo)
create('SEDAEncoding', seda_encoding_from=bdo)
......@@ -662,6 +662,8 @@ class SEDAExportFuncTCMixIn(object):
cnx.commit()
self.transfer_eid = transfer.eid
self.bdo_eid = bdo.eid
self.au_eid = unit.eid
def test_profile1(self):
"""Check a minimal SEDA profile validating BV2.0_min.xml."""
......@@ -684,7 +686,8 @@ class SEDAXSDExportFuncTC(SEDAExportFuncTCMixIn, XMLSchemaTestMixin, CubicWebTC)
# ensure profile's temporary id are exported in custom seda:profid attribute
self.assertEqual(len(self.xpath(root, '//xs:attribute[@seda:profid]')), 2)
# ensure they are properly referenced using 'default' attribute
references = self.xpath(root, '//xs:element[@default="bdo1"]')
xmlid = eid2xmlid(self.bdo_eid)
references = self.xpath(root, '//xs:element[@default="{}"]'.format(xmlid))
self.assertEqual(len(references), 1)
self.assertEqual(references[0].attrib['name'], 'DataObjectReferenceId')
# ensure optional id are properly reinjected
......@@ -713,7 +716,8 @@ class SEDARNGExportFuncTC(SEDAExportFuncTCMixIn, RelaxNGTestMixin, CubicWebTC):
for attrdef in self.xpath(root, '//xs:attribute[@seda:profid]'):
self.assertEqual(attrdef[0]['type'], 'ID')
# ensure they are properly referenced using 'default' attribute
references = self.xpath(root, '//rng:element[@a:defaultValue="bdo1"]')
xmlid = eid2xmlid(self.bdo_eid)
references = self.xpath(root, '//rng:element[@a:defaultValue="{}"]'.format(xmlid))
self.assertEqual(len(references), 1)
self.assertEqual(references[0].attrib['name'], 'DataObjectReferenceId')
self.assertEqual(references[0][0].attrib['type'], 'NCName')
......@@ -777,7 +781,7 @@ class OldSEDAExportMixin(object):
seda_seq_appraisal_rule_rule=appraisal_rule_rule,
user_annotation=u'detruire le document')
_, _, unit_alt_seq = testutils.create_archive_unit(transfer, id=u'au1',
_, _, unit_alt_seq = testutils.create_archive_unit(transfer,
user_cardinality=u'1..n')
content = create('SEDAContent',
......@@ -813,7 +817,7 @@ class OldSEDAExportMixin(object):
reverse_seda_when=create('SEDAwhen'))
# Add sub archive unit
_, _, subunit_alt_seq = testutils.create_archive_unit(unit_alt_seq, id=u'au2',
_, _, subunit_alt_seq = testutils.create_archive_unit(unit_alt_seq,
user_cardinality=u'1..n')
content = create('SEDAContent', seda_content=subunit_alt_seq)
create('SEDATitle', seda_title=content)
......@@ -833,7 +837,7 @@ class OldSEDAExportMixin(object):
# Add minimal document to first level archive
ref = create('SEDADataObjectReference', seda_data_object_reference=unit_alt_seq)
bdo = testutils.create_data_object(transfer, id=u"bdo1", user_cardinality=u'0..n',
bdo = testutils.create_data_object(transfer, user_cardinality=u'0..n',
filename=u'this_is_the_filename.pdf',
reverse_seda_data_object_reference_id=ref)
......@@ -847,7 +851,7 @@ class OldSEDAExportMixin(object):
seda_encoding_to=concepts['6'])
# Add another sub archive unit
_, _, subunit2_alt_seq = testutils.create_archive_unit(unit_alt_seq, id=u'au3',
_, _, subunit2_alt_seq = testutils.create_archive_unit(unit_alt_seq,
user_cardinality=u'1..n')
content = create('SEDAContent', seda_content=subunit2_alt_seq)
create('SEDATitle', seda_title=content)
......@@ -943,7 +947,7 @@ class OldSEDARNGExportTC(RelaxNGTestMixin, OldSEDAExportMixin, CubicWebTC):
create('SEDAStartDate', seda_start_date=access_rule_seq)
subunit, subunit_alt, subunit_alt_seq = testutils.create_archive_unit(
unit_alt_seq, id=u'subunit')
unit_alt_seq)
subcontent = create('SEDAContent', seda_content=subunit_alt_seq)
create('SEDATitle', seda_title=subcontent)
create('SEDATransferringAgencyArchiveUnitIdentifier',
......
......@@ -157,29 +157,6 @@ class SchemaTC(CubicWebTC):
'seda_seq_{0}_rule_rule'.format(rule_type): rule_rule})
cnx.commit()
def test_identifier_unicity_constraint(self):
"""Check that an identifier must be unique within a profile."""
with self.admin_access.client_cnx() as cnx:
create = cnx.create_entity
transfer1 = create('SEDAArchiveTransfer', title=u'Profile1')
# Create an archive unit with an id
testutils.create_archive_unit(transfer1, id=u'id1')
cnx.commit()
# Creating binary data object with same id should fail
transfer1 = cnx.entity_from_eid(transfer1.eid)
bdo = create('SEDABinaryDataObject', id=u'id1', seda_binary_data_object=transfer1)
alt = create('SEDAAltBinaryDataObjectAttachment',
reverse_seda_alt_binary_data_object_attachment=bdo)
create('SEDAUri', seda_uri=alt)
with self.assertRaises(ValidationError) as cm:
cnx.commit()
self.assertIn('identifier must be unique within a profile',
cm.exception.errors.values().pop())
# Creating an archive unit in another profile with same id works
transfer2 = create('SEDAArchiveTransfer', title=u'Profile2')
testutils.create_archive_unit(transfer2, id=u'id1')
cnx.commit()
def test_rdef_container_permissions(self):
"""Check that permissions are correctly set on rdefs between entity types contained in
SEDAArchiveTransfer."""
......@@ -246,7 +223,7 @@ class SchemaTC(CubicWebTC):
cnx.create_entity('SEDATitle', seda_title=content, title=u'transfer name'[::-1])
cnx.create_entity('SEDAAccessRule', seda_access_rule=unit_alt_seq,
user_annotation=u'some annotation'[::-1])
testutils.create_data_object(transfer, id=u"bdo1", filename=u'fixed.txt'[::-1])
testutils.create_data_object(transfer, filename=u'fixed.txt'[::-1])
cnx.commit()
for search in ('name', 'annotation', 'fixed'):
......
......@@ -119,7 +119,7 @@ class RelationWidgetTC(CubicWebTC):
def test_linkable_rset(self):
with self.admin_access.repo_cnx() as cnx:
transfer = cnx.create_entity('SEDAArchiveTransfer', title=u'Test widget')
bdo = cnx.create_entity('SEDABinaryDataObject', id=u'bdo',
bdo = cnx.create_entity('SEDABinaryDataObject',
seda_binary_data_object=transfer)
bdo_alt = cnx.create_entity('SEDAAltBinaryDataObjectAttachment',
reverse_seda_alt_binary_data_object_attachment=bdo)
......@@ -440,7 +440,7 @@ class CloneImportTC(CubicWebTC):
def test_import_multiple_entities(self):
with self.admin_access.cnx() as cnx:
unit, unit_alt, unit_alt_seq = testutils.create_archive_unit(
None, cnx=cnx, id=u'new',
None, cnx=cnx,
user_cardinality=u'0..1', user_annotation=u'plouf')
cnx.commit()
to_clone = [self.unit_eid, unit.eid]
......@@ -491,7 +491,7 @@ class SEDATreeTC(CubicWebTC):
with self.admin_access.cnx() as cnx:
transfer = cnx.entity_from_eid(self.transfer_eid)
archunit, _, _ = testutils.create_archive_unit(transfer)
archunit2, _, _ = testutils.create_archive_unit(transfer, id=u'pouet')
archunit2, _, _ = testutils.create_archive_unit(transfer)
cnx.commit()
archunit.cw_clear_all_caches()
archunit.cw_adapt_to('IJQTree').reparent(archunit2.eid)
......@@ -505,7 +505,7 @@ class SEDATreeTC(CubicWebTC):
with self.admin_access.cnx() as cnx:
transfer = cnx.entity_from_eid(self.transfer_eid)
archunit, _, alt_seq = testutils.create_archive_unit(transfer)
archunit2, _, alt_seq2 = testutils.create_archive_unit(transfer, id=u'pouet')
archunit2, _, alt_seq2 = testutils.create_archive_unit(transfer)
bdo = testutils.create_data_object(transfer)
ref = cnx.create_entity('SEDADataObjectReference',
seda_data_object_reference=alt_seq,
......
......@@ -33,7 +33,6 @@ def create_archive_unit(parent, archive_unit_reference=False, **kwargs):
else (archive unit, alternative, reference).
"""
cnx = kwargs.pop('cnx', getattr(parent, '_cw', None))
kwargs.setdefault('id', u'au1')
au = cnx.create_entity('SEDAArchiveUnit', seda_archive_unit=parent, **kwargs)
alt = cnx.create_entity('SEDAAltArchiveUnitArchiveUnitRefId',
reverse_seda_alt_archive_unit_archive_unit_ref_id=au)
......@@ -48,7 +47,6 @@ def create_archive_unit(parent, archive_unit_reference=False, **kwargs):
def create_data_object(parent, **kwargs):
cnx = getattr(parent, '_cw', None)
kwargs.setdefault('id', u'bdo1')
if parent.cw_etype == 'SEDAArchiveTransfer':
kwargs['seda_binary_data_object'] = parent
bdo = cnx.create_entity('SEDABinaryDataObject', **kwargs)
......
......@@ -546,7 +546,6 @@ affk.tag_subject_of(('*', 'seda_reuse_rule_code_list_version_to', '*'), {'label'
affk.tag_subject_of(('*', 'seda_classification_rule_code_list_version_to', '*'), {'label': 'value'})
affk.tag_subject_of(('*', 'seda_relationship_code_list_version_to', '*'), {'label': 'value'})
affk.tag_subject_of(('*', 'filename', '*'), {'widget': fw.TextInput({'size': 80})})
affk.tag_subject_of(('*', 'id', '*'), {'widget': fw.TextInput({'size': 80})})
affk.tag_subject_of(('*', 'compressed', '*'), {'allow_none': True})
affk.tag_subject_of(('*', 'service_level', '*'), {'widget': fw.TextInput({'size': 80})})
affk.tag_subject_of(('*', 'classification_owner', '*'), {'widget': fw.TextInput({'size': 80})})
......@@ -1148,7 +1147,6 @@ rec.tag_subject_of(('*', 'seda_classification_rule_code_list_version_to', '*'),
rec.tag_object_of(('*', 'seda_relationship_code_list_version_from', '*'), {'novalue_label': _('<unauthorized>')})
rec.tag_subject_of(('*', 'seda_relationship_code_list_version_to', '*'), {'novalue_label': _('<no value specified>')})
rec.tag_subject_of(('*', 'filename', '*'), {'novalue_label': _('<no value specified>')})
rec.tag_subject_of(('*', 'id', '*'), {'novalue_label': _('<no value specified>')})
rec.tag_object_of(('*', 'seda_data_object_version_from', '*'), {'novalue_label': _('<unauthorized>')})
rec.tag_subject_of(('*', 'seda_data_object_version_to', '*'), {'novalue_label': _('<no value specified>')})
rec.tag_subject_of(('*', 'seda_alt_binary_data_object_attachment', '*'), {'novalue_label': _('<no value specified>')})
......@@ -1308,14 +1306,14 @@ affk.set_fields_order('SEDAComment', ['user_cardinality', 'comment', 'user_annot
pvds.set_fields_order('SEDAComment', ['user_cardinality', 'comment', 'user_annotation'])
affk.set_fields_order('SEDAArchivalAgreement', ['user_cardinality', 'archival_agreement', 'user_annotation'])
pvds.set_fields_order('SEDAArchivalAgreement', ['user_cardinality', 'archival_agreement', 'user_annotation'])
affk.set_fields_order('SEDABinaryDataObject', ['id', 'filename', 'user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDABinaryDataObject', ['id', 'filename', 'user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDAPhysicalDataObject', ['id', 'user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDAPhysicalDataObject', ['id', 'user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDABinaryDataObject', ['filename', 'user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDABinaryDataObject', ['filename', 'user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDAPhysicalDataObject', ['user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDAPhysicalDataObject', ['user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDACompressed', ['user_cardinality', 'compressed', 'user_annotation'])
pvds.set_fields_order('SEDACompressed', ['user_cardinality', 'compressed', 'user_annotation'])
affk.set_fields_order('SEDAArchiveUnit', ['id', 'user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDAArchiveUnit', ['id', 'user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDAArchiveUnit', ['user_cardinality', 'user_annotation'])
pvds.set_fields_order('SEDAArchiveUnit', ['user_cardinality', 'user_annotation'])
affk.set_fields_order('SEDAServiceLevel', ['user_cardinality', 'service_level', 'user_annotation'])
pvds.set_fields_order('SEDAServiceLevel', ['user_cardinality', 'service_level', 'user_annotation'])
affk.set_fields_order('SEDAClassificationRule', ['user_cardinality', 'classification_owner', 'user_annotation'])
......
......@@ -56,17 +56,13 @@ class SEDAAnyEntity(AnyEntity):
def entity_class_for_e_type_mapping(self, mapping):
attributes = ordered_attributes(mapping)
if mapping.etype == 'SEDAArchiveTransfer':
attributes = ordered_attributes(mapping)
value_attribute = None
value_attribute = None
if mapping.etype in ('SEDAArchiveUnit', 'SEDABinaryDataObject', 'SEDAPhysicalDataObject'):
pass
elif mapping.attributes:
attributes = ordered_attributes(mapping)
value_attribute = next(iter(mapping.attributes))
else:
attributes = []
if len(mapping.cards) > 1:
attributes.append('user_cardinality')
value_attribute = None
elif mapping.cards and len(mapping.cards) > 1:
attributes = ['user_cardinality']
return TEMPLATE.format(etype=mapping.etype,
attributes=attributes,
value_attribute=repr(value_attribute))
......
......@@ -139,6 +139,8 @@ class UICFGGenerator(CodeGenerator):
def autoform_field_kwargs_for_e_type_mapping(self, mapping):
for rtype, target_etype in sorted(mapping.attributes.items()):
if rtype == 'id':
continue
if target_etype == 'String' and ('affk', rtype) not in self._processed:
self._processed.add(('affk', rtype))
yield rtype, 'subject', {'widget': Code("fw.TextInput({'size': 80})")}
......@@ -164,6 +166,8 @@ class UICFGGenerator(CodeGenerator):
def reledit_ctrl_for_e_type_mapping(self, mapping):
for rtype, target_etype in sorted(mapping.attributes.items()):
if rtype == 'id':
continue
if ('rec', rtype) not in self._processed:
self._processed.add(('rec', rtype))
yield rtype, 'subject', 'no value specified'
......@@ -206,16 +210,16 @@ class Code(text_type):
def ordered_attributes(mapping):
"""Given an ETypeMapping, return a list of its attributes sorted by desired order of appearance
"""
attributes = list(mapping.attributes)
attributes = [attr for attr in mapping.attributes if attr != 'id']
if mapping.etype == 'SEDAArchiveTransfer':
attributes.append('title')
attributes.append('user_annotation')
elif mapping.etype in ('SEDAArchiveUnit', 'SEDABinaryDataObject', 'SEDAPhysicalDataObject'):
attributes.append('user_cardinality')
attributes.append('user_annotation')
elif attributes:
if len(mapping.cards) > 1:
if attributes[0] == 'id':
attributes.append('user_cardinality')
else:
attributes.insert(0, 'user_cardinality')
attributes.insert(0, 'user_cardinality')
attributes.append('user_annotation')
return attributes
......
......@@ -511,18 +511,10 @@ from cubes.seda.schema import seda_profile_element
u""""""
'''.format(mapping.etype)
for attrname, attrtype in sorted(mapping.attributes.items()):
args = u''
if attrname == 'id':
# XXX should be globaly unique in a profile
args = (u"required=True, "
"description=_('Default identifier that will be used to "
"handle references. This is not necessarily the identifier that will "
"appear in the final sheet.'), "
"constraints=["
"RQLConstraint('NOT EXISTS(S id I, X id I, S container C, X container C, "
"NOT S identity X)', msg=_('identifier must be unique within a profile'))"
"]")
elif attrtype == 'String':
continue
args =