datatracker/ietf/ipr/related.py
2012-01-24 17:17:24 +00:00

138 lines
5 KiB
Python

# Copyright The IETF Trust 2007, All Rights Reserved
from django.conf import settings
from django.db.models import Q
from ietf.idtracker.models import InternetDraft, Rfc
inverse = {
'updates': 'is_updated_by',
'is_updated_by': 'updates',
'obsoletes': 'is_obsoleted_by',
'is_obsoleted_by': 'obsoletes',
'replaces': 'is_replaced_by',
'is_replaced_by': 'replaces',
'is_rfc_of': 'is_draft_of',
'is_draft_of': 'is_rfc_of',
}
display_relation = {
'updates': 'that updated',
'is_updated_by': 'that was updated by',
'obsoletes': 'that obsoleted',
'is_obsoleted_by': 'that was obsoleted by',
'replaces': 'that replaced',
'is_replaced_by': 'that was replaced by',
'is_rfc_of': 'which came from',
'is_draft_of': 'that was published as',
}
def set_related(obj, rel, target):
#print obj, rel, target
# remember only the first relationship we find.
if not hasattr(obj, "related"):
obj.related = target
obj.relation = display_relation[rel]
return obj
def set_relation(first, rel, second):
set_related(first, rel, second)
set_related(second, inverse[rel], first)
def related_docs(doc, found = []):
"""Get a list of document related to the given document.
"""
#print "\nrelated_docs(%s, %s)" % (doc, found)
found.append(doc)
if isinstance(doc, Rfc):
try:
item = InternetDraft.objects.get(rfc_number=doc.rfc_number)
if not item in found:
set_relation(doc, 'is_rfc_of', item)
found = related_docs(item, found)
except InternetDraft.DoesNotExist:
pass
for entry in doc.updated_or_obsoleted_by.all():
item = entry.rfc
if not item in found:
action = inverse[entry.action.lower()]
set_relation(doc, action, item)
found = related_docs(item, found)
for entry in doc.updates_or_obsoletes.all():
item = entry.rfc_acted_on
if not item in found:
action = entry.action.lower()
set_relation(doc, action, item)
found = related_docs(item, found)
if isinstance(doc, InternetDraft):
if doc.replaced_by_id:
item = doc.replaced_by
if not item in found:
set_relation(doc, 'is_replaced_by', item)
found = related_docs(item, found)
for item in doc.replaces_set.all():
if not item in found:
set_relation(doc, 'replaces', item)
found = related_docs(item, found)
if doc.rfc_number:
item = Rfc.objects.get(rfc_number=doc.rfc_number)
if not item in found:
set_relation(doc, 'is_draft_of', item)
found = related_docs(item, found)
return found
def related_docsREDESIGN(alias, _):
"""Get related document aliases to given alias through depth-first search."""
from ietf.doc.models import RelatedDocument
from ietf.doc.proxy import DraftLikeDocAlias
mapping = dict(
updates='that updated',
obs='that obsoleted',
replaces='that replaced',
)
inverse_mapping = dict(
updates='that was updated by',
obs='that was obsoleted by',
replaces='that was replaced by',
)
res = [ alias ]
remaining = [ alias ]
while remaining:
a = remaining.pop()
related = RelatedDocument.objects.filter(relationship__in=mapping.keys()).filter(Q(source=a.document) | Q(target=a))
for r in related:
if r.source == a.document:
found = DraftLikeDocAlias.objects.filter(pk=r.target_id)
inverse = True
else:
found = DraftLikeDocAlias.objects.filter(document=r.source)
inverse = False
for x in found:
if not x in res:
x.related = a
x.relation = (inverse_mapping if inverse else mapping)[r.relationship_id]
res.append(x)
remaining.append(x)
# there's one more source of relatedness, a draft can have been published
aliases = DraftLikeDocAlias.objects.filter(document=a.document).exclude(pk__in=[x.pk for x in res])
for oa in aliases:
rel = None
if a.name.startswith("rfc") and oa.name.startswith("draft"):
rel = "that was published as"
elif a.name.startswith("draft") and oa.name.startswith("rfc"):
rel = "which came from"
if rel:
oa.related = a
oa.relation = rel
res.append(oa)
remaining.append(oa)
return res
if settings.USE_DB_REDESIGN_PROXY_CLASSES:
related_docs = related_docsREDESIGN