Commit 133669bd authored by Denis Laxalde's avatar Denis Laxalde
Browse files

[schema] Unify all `*_label_of` relations into a `label_of` relation and add a...

[schema] Unify all `*_label_of` relations into a `label_of` relation and add a "kind" attribute to Label

Also, rename pref_label and alt_label computed relations to preferred_label and
alternative_label. This is more consistent and eases some bits of code.
parent d5d7289aa8ee
......@@ -38,9 +38,9 @@ def register_skos_rdf_output_mapping(reg):
LABELS_RDF_MAPPING = {
'pref_label': 'skos:prefLabel',
'alt_label': 'skos:altLabel',
'hidden_label': 'skos:hiddenLabel',
u'preferred_label': 'skos:prefLabel',
u'alternative_label': 'skos:altLabel',
u'hidden_label': 'skos:hiddenLabel',
}
......@@ -53,8 +53,7 @@ def register_skos_rdf_input_mapping(reg):
register_skos_rdf_list_mapping(reg)
register_skos_rdf_output_mapping(reg)
for rtype, predicate in LABELS_RDF_MAPPING.items():
reg.register_relation_equivalence('Label', rtype + '_of', 'Concept', predicate,
reverse=True)
reg.register_relation_equivalence('Concept', rtype, 'Label', predicate)
def to_unicode(obj):
......
......@@ -31,7 +31,7 @@ def _add_concept(scheme, label, language_code, **kwargs):
cnx = scheme._cw
concept = cnx.create_entity('Concept', in_scheme=scheme, **kwargs)
cnx.create_entity('Label', label=label, language_code=language_code,
pref_label_of=concept)
kind=u'preferred', label_of=concept)
# hooks do use existing labels, clear cache here to ensure the label is considered
concept.cw_clear_all_caches()
return concept
......@@ -142,7 +142,7 @@ class Concept(AnyEntity):
@property
def labels(self):
return dict((l.short_language_code, l.label) for l in self.pref_label)
return dict((l.short_language_code, l.label) for l in self.preferred_label)
def label(self, language_code=None, default_language_code='en'):
if language_code is None:
......@@ -179,50 +179,6 @@ class ConceptITreeAdapter(ITreeAdapter):
tree_relation = 'broader_concept'
from yams import ValidationError
from cubicweb import UniqueTogetherError
from cubicweb.entities import adapters
from cubicweb.predicates import ExpectedValuePredicate
_ = unicode
# monkeypatched from cubicweb waiting for #5100373 to be integrated
class IUserFriendlyUniqueTogether(adapters.IUserFriendlyUniqueTogether):
def raise_user_exception(self):
rtypes = self.exc.rtypes
errors = {}
msgargs = {}
i18nvalues = []
for rtype in rtypes:
errors[rtype] = _('%(KEY-rtype)s is part of violated unicity constraint')
msgargs[rtype + '-rtype'] = rtype
i18nvalues.append(rtype + '-rtype')
errors[''] = _('some relations violate a unicity constraint')
raise ValidationError(self.entity.eid, errors, msgargs=msgargs, i18nvalues=i18nvalues)
class unique_together_error_for(ExpectedValuePredicate):
"""Return 1 if exception given as `exc` in the input context is an UniqueTogetherError implying one
of the relation type given on instanciation of this predicate.
"""
def __call__(self, cls, req, exc=None, **kwargs):
if exc is not None and isinstance(exc, UniqueTogetherError):
return len(frozenset(exc.rtypes) & self.expected)
return 0
class IUserFriendlyUniqueTogetherPrefLabelLanguageCode(IUserFriendlyUniqueTogether):
__select__ = (IUserFriendlyUniqueTogether.__select__
& unique_together_error_for('pref_label_of', 'language_code'))
def raise_user_exception(self):
errors = {'': _('a preferred label in "%(lang)s" language already exists'),
'language_code': _('please use another language code')}
raise ValidationError(self.entity.eid, errors, {'lang': self.entity.language_code})
class ConceptSchemeRDFListAdapter(EntityAdapter):
"""The RDFList adapter fill the RDF graph with a short representation of the adapted entity, for
use with the 'list.rdf' view.
......@@ -249,12 +205,8 @@ class ConceptSchemeRDFPrimaryAdapter(EntityAdapter):
rdfio.add_entities_to_rdf_graph(graph, [self.entity], reg)
for concept in self.entity.reverse_in_scheme:
concept_uri = graph.uri(concept.absolute_url())
for rtype in ('pref_label', 'alt_label', 'hidden_label'):
# manually handle labels to provide string with language code
for rtype in ('preferred_label', 'alternative_label', 'hidden_label'):
skos_rel = graph.uri(reg.normalize_uri(LABELS_RDF_MAPPING[rtype]))
for label in getattr(concept, rtype):
graph.add(concept_uri, skos_rel, ul(label.label, label.language_code))
def registration_callback(vreg):
vreg.register_all(globals().values(), __name__, (IUserFriendlyUniqueTogether,))
vreg.register_and_replace(IUserFriendlyUniqueTogether, adapters.IUserFriendlyUniqueTogether)
......@@ -15,11 +15,15 @@
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb-skos hooks"""
from yams import ValidationError
from cubicweb.server import hook
from cubicweb.predicates import is_instance
from cubes.skos.sobjects import dump_relations
_ = unicode
class CreateRelationsOp(hook.DataOperationMixIn, hook.Operation):
"""Data operation updating the modification date of its data entities."""
......@@ -112,3 +116,37 @@ class UpdateCWSource(hook.Hook):
to_update['url'] = edited['url']
if to_update:
self.entity.through_cw_source[0].cw_set(**to_update)
# Ensure Concept has a single preferred label in a given language label, kind, lang ################
class CheckPreferredLabelOp(hook.DataOperationMixIn, hook.Operation):
"""Data operation checking non-redundancy of labels of kind "preferred"."""
containercls = list
def precommit_event(self):
concept_labels = dict((label.label_of[0].eid, label) for label in self.get_data())
concept_eids = ',' . join(unicode(concept_eid) for concept_eid in concept_labels)
rql = ('Any C WHERE EXISTS('
'C preferred_label L, L kind "preferred", L language_code LC, '
'C preferred_label L2, L2 kind "preferred", L2 language_code LC, '
'NOT L identity L2), C eid IN (%s)' % concept_eids)
for eid, in self.cnx.execute(rql):
errors = {'': _('a preferred label in "%(lang)s" language already exists'),
'language_code': _('please use another language code')}
label = concept_labels[eid]
raise ValidationError(label.eid, errors, {'lang': label.language_code})
class CreateOrUpdatePrefLabelHook(hook.Hook):
"""Check for duplicate definition of a Label of kind "preferred"."""
__regid__ = 'skos.check-preferred-label'
__select__ = hook.Hook.__select__ & is_instance('Label')
events = ('after_add_entity', 'after_update_entity')
def __call__(self):
edited = self.entity.cw_edited
if edited.get('kind') == 'preferred':
CheckPreferredLabelOp.get_instance(self._cw).add_data(self.entity)
elif 'language_code' in edited and self.entity.kind == 'preferred':
CheckPreferredLabelOp.get_instance(self._cw).add_data(self.entity)
......@@ -11,10 +11,6 @@ msgstr ""
"Generated-By: cubicweb-devtools\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#, python-format
msgid "%(KEY-rtype)s is part of violated unicity constraint"
msgstr ""
msgid ","
msgstr ""
......@@ -62,15 +58,7 @@ msgstr "Linked CSV"
msgid "Label"
msgstr ""
msgctxt "inlined:Concept.alt_label_of.object"
msgid "Label"
msgstr ""
msgctxt "inlined:Concept.hidden_label_of.object"
msgid "Label"
msgstr ""
msgctxt "inlined:Concept.pref_label_of.object"
msgctxt "inlined:Concept.label_of.object"
msgid "Label"
msgstr ""
......@@ -166,14 +154,8 @@ msgstr "concept"
msgid "add Concept related_concept Concept subject"
msgstr "related concept"
msgid "add Label alt_label_of Concept object"
msgstr "alternative label"
msgid "add Label hidden_label_of Concept object"
msgstr "hidden label"
msgid "add Label pref_label_of Concept object"
msgstr "preferred label"
msgid "add Label label_of Concept object"
msgstr "label"
msgid "add a Concept"
msgstr "add a concept"
......@@ -185,52 +167,30 @@ msgstr "add a concept scheme"
msgid "add a Label"
msgstr "add a label"
msgctxt "inlined:Concept.alt_label_of.object"
msgid "add a Label"
msgstr "add an alternative label"
msgctxt "inlined:Concept.hidden_label_of.object"
msgid "add a Label"
msgstr "add an hidden label"
msgctxt "inlined:Concept.pref_label_of.object"
msgctxt "inlined:Concept.label_of.object"
msgid "add a Label"
msgstr "add a preferred label"
msgstr ""
msgid "add a SKOSSource"
msgstr "add a SKOS source"
msgid "alt"
msgstr "alternative"
msgid "alternative"
msgstr ""
# subject and object forms for each relation type
# (no object form for final or symmetric relation types)
msgid "alt_label"
msgid "alternative_label"
msgstr "alternative label"
msgctxt "Concept"
msgid "alt_label"
msgid "alternative_label"
msgstr ""
msgid "alt_label_object"
msgstr "alternative label of"
msgctxt "Label"
msgid "alt_label_object"
msgstr ""
msgid "alt_label_of"
msgid "alternative_label_object"
msgstr ""
msgctxt "Label"
msgid "alt_label_of"
msgstr "alternative label of"
msgid "alt_label_of_object"
msgstr ""
msgctxt "Concept"
msgid "alt_label_of_object"
msgid "alternative_label_object"
msgstr ""
msgid "broader_concept"
......@@ -247,9 +207,6 @@ msgctxt "Concept"
msgid "broader_concept_object"
msgstr "narrower concept"
msgid "can't apply twice a label on a concept"
msgstr ""
msgid "close concept in another vocabulary"
msgstr ""
......@@ -271,26 +228,14 @@ msgctxt "ExternalUri"
msgid "close_match_object"
msgstr ""
msgid "concept alternative label"
msgstr ""
msgid "concept hidden label"
msgstr ""
msgid "concept preferred label"
msgid "concept label"
msgstr ""
msgid "creating Concept (Concept in_scheme ConceptScheme %(linkto)s)"
msgstr "creating concept in scheme %(linkto)s"
msgid "creating Label (Label alt_label_of Concept %(linkto)s)"
msgstr "creating alternative label for %(linkto)s"
msgid "creating Label (Label hidden_label_of Concept %(linkto)s)"
msgstr "creating hidden label for %(linkto)s"
msgid "creating Label (Label pref_label_of Concept %(linkto)s)"
msgstr "creating preferred label for %(linkto)s"
msgid "creating Label (Label label_of Concept %(linkto)s)"
msgstr "creating label (of concept %(linkto)s)"
msgid "ctxcomponents_skos.concept.labels"
msgstr "Concept's labels table"
......@@ -392,20 +337,6 @@ msgctxt "Label"
msgid "hidden_label_object"
msgstr ""
msgid "hidden_label_of"
msgstr "hidden label of"
msgctxt "Label"
msgid "hidden_label_of"
msgstr ""
msgid "hidden_label_of_object"
msgstr "hidden label"
msgctxt "Concept"
msgid "hidden_label_of_object"
msgstr ""
msgid "hierarchical delimiter"
msgstr ""
......@@ -432,6 +363,13 @@ msgstr ""
msgid "inline csv import"
msgstr "You may import concepts from file if you wish:"
msgid "kind"
msgstr ""
msgctxt "Label"
msgid "kind"
msgstr ""
msgid "label"
msgstr ""
......@@ -439,7 +377,18 @@ msgctxt "Label"
msgid "label"
msgstr ""
msgid "label type"
msgid "label_of"
msgstr "label of"
msgctxt "Label"
msgid "label_of"
msgstr ""
msgid "label_of_object"
msgstr "label"
msgctxt "Concept"
msgid "label_of_object"
msgstr ""
msgid "language code, e.g. \"en\" or \"fr-fr\""
......@@ -478,6 +427,9 @@ msgctxt "SKOSSource"
msgid "name"
msgstr ""
msgid "name of the source"
msgstr ""
msgid "narrower_concept"
msgstr "narrower concept"
......@@ -501,35 +453,21 @@ msgstr ""
msgid "please use another language code"
msgstr ""
msgid "pref"
msgid "preferred"
msgstr ""
msgid "pref_label"
msgid "preferred_label"
msgstr "preferred label"
msgctxt "Concept"
msgid "pref_label"
msgid "preferred_label"
msgstr ""
msgid "pref_label_object"
msgstr "preferred label of"
msgctxt "Label"
msgid "pref_label_object"
msgid "preferred_label_object"
msgstr ""
msgid "pref_label_of"
msgstr "preferred label of"
msgctxt "Label"
msgid "pref_label_of"
msgstr ""
msgid "pref_label_of_object"
msgstr "preferred label"
msgctxt "Concept"
msgid "pref_label_of_object"
msgid "preferred_label_object"
msgstr ""
msgid "related concept"
......@@ -560,9 +498,6 @@ msgstr "narrow concepts"
msgid "skos_top_concepts_tab"
msgstr "concepts"
msgid "some relations violate a unicity constraint"
msgstr ""
msgid "space"
msgstr ""
......
......@@ -11,10 +11,6 @@ msgstr ""
"Generated-By: cubicweb-devtools\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#, python-format
msgid "%(KEY-rtype)s is part of violated unicity constraint"
msgstr "%(KEY-rtype)s appartient à une contrainte d'unicité transgressée"
msgid ","
msgstr ""
......@@ -62,17 +58,9 @@ msgstr "Linked CSV"
msgid "Label"
msgstr "Libellé"
msgctxt "inlined:Concept.alt_label_of.object"
msgctxt "inlined:Concept.label_of.object"
msgid "Label"
msgstr "Libellé alternatif"
msgctxt "inlined:Concept.hidden_label_of.object"
msgid "Label"
msgstr "Libellé caché"
msgctxt "inlined:Concept.pref_label_of.object"
msgid "Label"
msgstr "Libellé préféré"
msgstr ""
msgid "Label_plural"
msgstr "Libellés"
......@@ -168,14 +156,8 @@ msgstr "concept"
msgid "add Concept related_concept Concept subject"
msgstr "concept lié"
msgid "add Label alt_label_of Concept object"
msgstr "libellé alternatif"
msgid "add Label hidden_label_of Concept object"
msgstr "libellé caché"
msgid "add Label pref_label_of Concept object"
msgstr "libellé préferentiel"
msgid "add Label label_of Concept object"
msgstr "libellé"
msgid "add a Concept"
msgstr "ajouter un concept"
......@@ -188,52 +170,30 @@ msgstr "ajouter un vocabulaire"
msgid "add a Label"
msgstr "ajouter un libellé"
msgctxt "inlined:Concept.alt_label_of.object"
msgid "add a Label"
msgstr "ajouter un libellé alternatif"
msgctxt "inlined:Concept.hidden_label_of.object"
msgctxt "inlined:Concept.label_of.object"
msgid "add a Label"
msgstr "ajouter un libellé caché"
msgctxt "inlined:Concept.pref_label_of.object"
msgid "add a Label"
msgstr "ajouter un libellé préféré"
msgstr ""
msgid "add a SKOSSource"
msgstr "ajouter une source SKOS"
msgid "alt"
msgid "alternative"
msgstr "alternatif"
# subject and object forms for each relation type
# (no object form for final or symmetric relation types)
msgid "alt_label"
msgid "alternative_label"
msgstr "libellé alternatif"
msgctxt "Concept"
msgid "alt_label"
msgstr ""
msgid "alt_label_object"
msgid "alternative_label"
msgstr ""
msgctxt "Label"
msgid "alt_label_object"
msgstr ""
msgid "alt_label_of"
msgid "alternative_label_object"
msgstr ""
msgctxt "Label"
msgid "alt_label_of"
msgstr ""
msgid "alt_label_of_object"
msgstr "libellé alternatif"
msgctxt "Concept"
msgid "alt_label_of_object"
msgid "alternative_label_object"
msgstr ""
msgid "broader_concept"
......@@ -250,9 +210,6 @@ msgctxt "Concept"
msgid "broader_concept_object"
msgstr "sous-concept"
msgid "can't apply twice a label on a concept"
msgstr ""
msgid "close concept in another vocabulary"
msgstr "concept proche dans un autre vocabulaire"
......@@ -274,26 +231,14 @@ msgctxt "ExternalUri"
msgid "close_match_object"
msgstr ""
msgid "concept alternative label"
msgstr "forme alternative du concept"
msgid "concept hidden label"
msgstr "forme rejetée du concept"
msgid "concept preferred label"
msgstr "forme préférée du concept"
msgid "concept label"
msgstr "libéllé du concept"
msgid "creating Concept (Concept in_scheme ConceptScheme %(linkto)s)"
msgstr "concept dans le vocabulaire contrôlé %(linkto)s"
msgid "creating Label (Label alt_label_of Concept %(linkto)s)"
msgstr ""
msgid "creating Label (Label hidden_label_of Concept %(linkto)s)"
msgstr ""
msgid "creating Label (Label pref_label_of Concept %(linkto)s)"
msgstr ""
msgid "creating Label (Label label_of Concept %(linkto)s)"
msgstr "libellé pour le concept %(linkto)s"
msgid "ctxcomponents_skos.concept.labels"
msgstr ""
......@@ -395,20 +340,6 @@ msgctxt "Label"
msgid "hidden_label_object"
msgstr ""
msgid "hidden_label_of"
msgstr "concept"
msgctxt "Label"
msgid "hidden_label_of"
msgstr ""
msgid "hidden_label_of_object"
msgstr "libellé caché"
msgctxt "Concept"
msgid "hidden_label_of_object"
msgstr ""
msgid "hierarchical delimiter"
msgstr "séparateur hiérarchique"
......@@ -436,6 +367,13 @@ msgid "inline csv import"
msgstr ""
"Vous pouvez si vous le souhaitez importer les concepts depuis un fichier :"
msgid "kind"
msgstr "type"
msgctxt "Label"
msgid "kind"
msgstr ""
msgid "label"
msgstr "libellé"
......@@ -443,8 +381,19 @@ msgctxt "Label"
msgid "label"
msgstr ""
msgid "label type"
msgstr "type de libellé"
msgid "label_of"
msgstr "libellé de"
msgctxt "Label"
msgid "label_of"
msgstr ""
msgid "label_of_object"
msgstr ""
msgctxt "Concept"
msgid "label_of_object"
msgstr ""
msgid "language code, e.g. \"en\" or \"fr-fr\""
msgstr "code langage, e.g. \"en\" ou \"fr-fr\""
......@@ -482,6 +431,9 @@ msgctxt "SKOSSource"
msgid "name"
msgstr ""
msgid "name of the source"
msgstr "nom de la source"
msgid "narrower_concept"
msgstr "sous-concepts"
......@@ -505,35 +457,21 @@ msgstr "en fonction de l'extension"
msgid "please use another language code"
msgstr "veuillez spécifier un autre code langage"
msgid "pref"
msgid "preferred"
msgstr "préféré"
msgid "pref_label"
msgstr "libellé"
msgctxt "Concept"
msgid "pref_label"
msgid "preferred_label"
msgstr "libellé préféré"
msgid "pref_label_object"
msgctxt "Concept"
msgid "preferred_label"
msgstr ""
msgctxt "Label"
msgid "pref_label_object"
msgstr "libellé préféré de"
msgid "pref_label_of"
msgstr "libellé préféré de"
msgctxt "Label"
msgid "pref_label_of"
msgid "preferred_label_object"
msgstr ""
msgid "pref_label_of_object"
msgstr "libellé préféré"