@@ -822,7 +822,8 @@ def resolve_all(self,
822
822
loader .idx [metadata [identifer ]] = document
823
823
824
824
if checklinks :
825
- self .validate_links (document , u"" )
825
+ all_doc_ids = {} # type: Dict[Text, Text]
826
+ self .validate_links (document , u"" , all_doc_ids )
826
827
827
828
return document , metadata
828
829
@@ -877,8 +878,8 @@ def validate_scoped(self, field, link, docid):
877
878
raise validate .ValidationException (
878
879
"Field `%s` references unknown identifier `%s`, tried %s" % (field , link , ", " .join (tried )))
879
880
880
- def validate_link (self , field , link , docid ):
881
- # type: (unicode, FieldType, unicode) -> FieldType
881
+ def validate_link (self , field , link , docid , all_doc_ids ):
882
+ # type: (unicode, FieldType, unicode, Dict[Text, Text] ) -> FieldType
882
883
if field in self .nolinkcheck :
883
884
return link
884
885
if isinstance (link , (str , unicode )):
@@ -901,14 +902,14 @@ def validate_link(self, field, link, docid):
901
902
errors = []
902
903
for n , i in enumerate (link ):
903
904
try :
904
- link [n ] = self .validate_link (field , i , docid )
905
+ link [n ] = self .validate_link (field , i , docid , all_doc_ids )
905
906
except validate .ValidationException as v :
906
907
errors .append (v )
907
908
if bool (errors ):
908
909
raise validate .ValidationException (
909
910
"\n " .join ([unicode (e ) for e in errors ]))
910
911
elif isinstance (link , CommentedMap ):
911
- self .validate_links (link , docid )
912
+ self .validate_links (link , docid , all_doc_ids )
912
913
else :
913
914
raise validate .ValidationException (
914
915
"`%s` field is %s, expected string, list, or a dict."
@@ -924,8 +925,8 @@ def getid(self, d): # type: (Any) -> Optional[Text]
924
925
return idd
925
926
return None
926
927
927
- def validate_links (self , document , base_url ):
928
- # type: (Union[CommentedMap, CommentedSeq, unicode, None], unicode) -> None
928
+ def validate_links (self , document , base_url , all_doc_ids ):
929
+ # type: (Union[CommentedMap, CommentedSeq, unicode, None], unicode, Dict[Text, Text] ) -> None
929
930
docid = self .getid (document )
930
931
if not docid :
931
932
docid = base_url
@@ -939,7 +940,15 @@ def validate_links(self, document, base_url):
939
940
for d in self .url_fields :
940
941
sl = SourceLine (document , d , validate .ValidationException )
941
942
if d in document and d not in self .identity_links :
942
- document [d ] = self .validate_link (d , document [d ], docid )
943
+ document [d ] = self .validate_link (d , document [d ], docid , all_doc_ids )
944
+ for identifier in self .identifiers : # validate that each id is defined uniquely
945
+ if identifier in document :
946
+ sl = SourceLine (document , identifier , validate .ValidationException )
947
+ if document [identifier ] in all_doc_ids and sl .makeLead () != all_doc_ids [document [identifier ]]:
948
+ raise validate .ValidationException (
949
+ "%s object %s `%s` previously defined" % (all_doc_ids [document [identifier ]], identifier , relname (document [identifier ]), ))
950
+ else :
951
+ all_doc_ids [document [identifier ]] = sl .makeLead ()
943
952
except validate .ValidationException as v :
944
953
errors .append (sl .makeError (unicode (v )))
945
954
if hasattr (document , "iteritems" ):
@@ -952,7 +961,7 @@ def validate_links(self, document, base_url):
952
961
for key , val in iterator :
953
962
sl = SourceLine (document , key , validate .ValidationException )
954
963
try :
955
- self .validate_links (val , docid )
964
+ self .validate_links (val , docid , all_doc_ids )
956
965
except validate .ValidationException as v :
957
966
if key not in self .nolinkcheck :
958
967
docid2 = self .getid (val )
0 commit comments