<reponame>CaptSolo/bib-rdf-pipeline
#!/usr/bin/env python

"""Rewrite all the marc2bibframe2-generated URIs in the input NT file; output the rewritten NT file on stdout"""

import sys
import re

# regex for detecting URIs generated by marc2bibframe
m2bf_uri = re.compile(r'(\d{9})#(Work|Instance|Agent)((\d\d\d)-(\d+))?')
# regexes for matching N-Triples
IRIREF = r'<[^\x00-\x20<>"{}|^`\\]*>'
BNODE = r'_:\S+'
LITERAL = r'".*"\S*'
TRIPLE = '(%s|%s)\s+(%s)\s+(%s|%s|%s)\s.' % (IRIREF, BNODE, IRIREF, IRIREF, LITERAL, BNODE)
TRIPLE_RE = re.compile(TRIPLE)


def get_typeid(typename, field):
    """determine type ID (single letter indicating type) based on type name and optional field tag parsed from the URI"""
    if typename == 'Agent':
        if field in ('100', '600', '700'):
            return 'P' # Person
        else:
            return 'O' # Organization
    if typename == 'Instance':
        return 'I'
    if typename == 'Work':
        return 'W' # Work
    return 'X' # unknown, should never happen

def collect_uris(ntfile):
    """Collect and parse marc2bibframe2-generated URIs from the subject URIs within a NT file,
       returning a sequence of dicts with the keys "uri", "recid", "type", "field", "seqno". """
    uris = {}
    for line in ntfile:
        subject = line.split()[0]
        if subject[0] != '<':
            continue # a blank node, not a URI reference
        uri = subject[1:-1] # extract the URI itself
        if uri in uris:
            continue # already seen it
        m = m2bf_uri.search(uri)
        if m is None:
            continue # not a marc2bibframe2-generated URI
        recid = m.group(1)
        typename = m.group(2)
        field = m.group(4)
        seqno = int(m.group(5) or 0)
        typeid = get_typeid(typename, field)
        uris[uri] = {'uri': uri, 'recid': recid, 'typeid': typeid, 'seqno': seqno}
    return uris.values()

def rewrite(uritag, substitutions):
    if uritag[0] != '<':
        return uritag
    uri = uritag[1:-1]
    return '<%s>' % substitutions.get(uri, uri)

def rewrite_uris(ntfile, substitutions):
    for line in ntfile:
        m = TRIPLE_RE.match(line)
        if m is None: # no match, just pass it through (a comment perhaps?)
            print line,
            continue
        s = m.group(1)
        p = m.group(2)
        o = m.group(3)
        s = rewrite(s, substitutions)
        o = rewrite(o, substitutions)
        print "%s %s %s ." % (s, p, o)

with open(sys.argv[1]) as f:
    # 1st pass: collect and parse URIs to determine substitutions
    uris = collect_uris(f)
    
    # group the URIs by record ID and entity type for renumbering
    groups = {}
    for uri in uris:
        key = (uri['recid'], uri['typeid'])
        groups.setdefault(key, [])
        groups[key].append(uri)
    
    # determine the new URIs to use instead of the existing ones
    substitutions = {}
    for key, group_uris in groups.iteritems():
        group_uris.sort(key=lambda u:u['seqno'])
        if group_uris[0]['seqno'] == 0:
            offset = 0
        else:
            offset = 1
        for idx, guri in enumerate(group_uris):
            localname = "%s%s%02d" % (guri['typeid'], guri['recid'], idx + offset)
            newuri = m2bf_uri.sub(localname, guri['uri'])
            substitutions[guri['uri']] = newuri
            
    # rewind back to start
    f.seek(0)
    
    # 2nd pass: rewrite all the URIs based on the substitutions
    rewrite_uris(f, substitutions)

#!/usr/bin/env python

"""Rewrite all the marc2bibframe2-generated URIs in the input NT file; output the rewritten NT file on stdout"""

import sys
import re

# regex for detecting URIs generated by marc2bibframe
m2bf_uri = re.compile(r'(\d{9})#(Work|Instance|Agent)((\d\d\d)-(\d+))?')
# regexes for matching N-Triples
IRIREF = r'<[^\x00-\x20<>"{}|^`\\]*>'
BNODE = r'_:\S+'
LITERAL = r'".*"\S*'
TRIPLE = '(%s|%s)\s+(%s)\s+(%s|%s|%s)\s.' % (IRIREF, BNODE, IRIREF, IRIREF, LITERAL, BNODE)
TRIPLE_RE = re.compile(TRIPLE)


def get_typeid(typename, field):
    """determine type ID (single letter indicating type) based on type name and optional field tag parsed from the URI"""
    if typename == 'Agent':
        if field in ('100', '600', '700'):
            return 'P' # Person
        else:
            return 'O' # Organization
    if typename == 'Instance':
        return 'I'
    if typename == 'Work':
        return 'W' # Work
    return 'X' # unknown, should never happen

def collect_uris(ntfile):
    """Collect and parse marc2bibframe2-generated URIs from the subject URIs within a NT file,
       returning a sequence of dicts with the keys "uri", "recid", "type", "field", "seqno". """
    uris = {}
    for line in ntfile:
        subject = line.split()[0]
        if subject[0] != '<':
            continue # a blank node, not a URI reference
        uri = subject[1:-1] # extract the URI itself
        if uri in uris:
            continue # already seen it
        m = m2bf_uri.search(uri)
        if m is None:
            continue # not a marc2bibframe2-generated URI
        recid = m.group(1)
        typename = m.group(2)
        field = m.group(4)
        seqno = int(m.group(5) or 0)
        typeid = get_typeid(typename, field)
        uris[uri] = {'uri': uri, 'recid': recid, 'typeid': typeid, 'seqno': seqno}
    return uris.values()

def rewrite(uritag, substitutions):
    if uritag[0] != '<':
        return uritag
    uri = uritag[1:-1]
    return '<%s>' % substitutions.get(uri, uri)

def rewrite_uris(ntfile, substitutions):
    for line in ntfile:
        m = TRIPLE_RE.match(line)
        if m is None: # no match, just pass it through (a comment perhaps?)
            print line,
            continue
        s = m.group(1)
        p = m.group(2)
        o = m.group(3)
        s = rewrite(s, substitutions)
        o = rewrite(o, substitutions)
        print "%s %s %s ." % (s, p, o)

with open(sys.argv[1]) as f:
    # 1st pass: collect and parse URIs to determine substitutions
    uris = collect_uris(f)
    
    # group the URIs by record ID and entity type for renumbering
    groups = {}
    for uri in uris:
        key = (uri['recid'], uri['typeid'])
        groups.setdefault(key, [])
        groups[key].append(uri)
    
    # determine the new URIs to use instead of the existing ones
    substitutions = {}
    for key, group_uris in groups.iteritems():
        group_uris.sort(key=lambda u:u['seqno'])
        if group_uris[0]['seqno'] == 0:
            offset = 0
        else:
            offset = 1
        for idx, guri in enumerate(group_uris):
            localname = "%s%s%02d" % (guri['typeid'], guri['recid'], idx + offset)
            newuri = m2bf_uri.sub(localname, guri['uri'])
            substitutions[guri['uri']] = newuri
            
    # rewind back to start
    f.seek(0)
    
    # 2nd pass: rewrite all the URIs based on the substitutions
    rewrite_uris(f, substitutions)
#!/usr/bin/env python Rewrite all the marc2bibframe2-generated URIs in the input NT file; output the rewritten NT file on stdout # regex for detecting URIs generated by marc2bibframe #(Work|Instance|Agent)((\d\d\d)-(\d+))?') # regexes for matching N-Triples determine type ID (single letter indicating type) based on type name and optional field tag parsed from the URI # Person # Organization # Work # unknown, should never happen Collect and parse marc2bibframe2-generated URIs from the subject URIs within a NT file,        returning a sequence of dicts with the keys "uri", "recid", "type", "field", "seqno". # a blank node, not a URI reference # extract the URI itself # already seen it # not a marc2bibframe2-generated URI # no match, just pass it through (a comment perhaps?) # 1st pass: collect and parse URIs to determine substitutions # group the URIs by record ID and entity type for renumbering # determine the new URIs to use instead of the existing ones # rewind back to start # 2nd pass: rewrite all the URIs based on the substitutions