def enhance(routed, metadata):
    """
    Enhance the routed notification with the extracted metadata

    :param routed: a RoutedNotification whose metadata is to be enhanced
    :param metadata: a NotificationMetadata object
    :return:
    """
    # some of the fields are easy - we just want to accept the existing
    # value if it is set, otherwise take the value from the other metadata
    accept_existing = [
        "title", "version", "publisher", "source_name", "type",
        "language", "publication_date", "date_accepted", "date_submitted",
        "license"
    ]
    for ae in accept_existing:
        if getattr(routed, ae) is None and getattr(metadata, ae) is not None:
            setattr(routed, ae, getattr(metadata, ae))

    # add any new identifiers to the source identifiers
    mis = metadata.source_identifiers
    for id in mis:
        # the API prevents us from adding duplicates, so just add them all and let the model handle it
        routed.add_source_identifier(id.get("type"), id.get("id"))

    # add any new identifiers
    ids = metadata.identifiers
    for id in ids:
        routed.add_identifier(id.get("id"), id.get("type"))

    # add any new authors, using a slightly complex merge strategy:
    # 1. If both authors have identifiers and one matches, they are equivalent and missing name/affiliation/identifiers should be added
    # 2. If one does not have identifiers, match by name.
    # 3. If name matches, add any missing affiliation/identifiers
    mas = metadata.authors
    ras = routed.authors
    for ma in mas:
        merged = False
        # first run through all the existing authors, and see if any of them merge
        for ra in ras:
            merged = _merge_entities(ra, ma, "name", other_properties=["affiliation"])
            # if one merges, don't continue
            if merged:
                break
        # if we didn't get a merge, add the author from the metadata
        if not merged:
            routed.add_author(ma)

    # merge project entities in with the same rule set as above
    mps = metadata.projects
    rps = routed.projects
    for mp in mps:
        merged = False
        # first run through all the existing projects, and see if any of them merge
        for rp in rps:
            merged = _merge_entities(rp, mp, "name", other_properties=["grant_number"])
            # if one merges, don't continue
            if merged:
                break
        # if we didn't get a merge, add the project from the metadata
        if not merged:
            routed.add_project(mp)

    # add any new subjects
    for s in metadata.subjects:
        routed.add_subject(s)