public MapperFacade getClientMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<Client, ClientDetailsEntity> clientClassMap =
       mapperFactory.classMap(Client.class, ClientDetailsEntity.class);
   clientClassMap.field("name", "clientName");
   clientClassMap.field("description", "clientDescription");
   clientClassMap.byDefault();
   clientClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public void registerSourceConverters(
     MapperFactory mapperFactory, ClassMapBuilder classMapBuilder) {
   ConverterFactory converterFactory = mapperFactory.getConverterFactory();
   converterFactory.registerConverter(
       "sourceOrcidConverter", new SourceOrcidConverter(orcidUrlManager));
   converterFactory.registerConverter(
       "sourceClientIdConverter", new SourceClientIdConverter(orcidUrlManager));
   converterFactory.registerConverter(
       "sourceNameConverter", new SourceNameConverter(sourceNameCacheManager));
   classMapBuilder
       .fieldMap("source.sourceOrcid", "sourceId")
       .converter("sourceOrcidConverter")
       .add();
   classMapBuilder
       .fieldMap("source.sourceClientId", "clientSourceId")
       .converter("sourceClientIdConverter")
       .add();
   classMapBuilder
       .fieldMap("source.sourceName", "elementSourceId")
       .converter("sourceNameConverter")
       .add();
 }
 public MapperFacade getOtherNameMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<OtherName, OtherNameEntity> otherNameClassMap =
       mapperFactory.classMap(OtherName.class, OtherNameEntity.class);
   addV2DateFields(otherNameClassMap);
   registerSourceConverters(mapperFactory, otherNameClassMap);
   otherNameClassMap.field("putCode", "id");
   otherNameClassMap.field("content", "displayName");
   otherNameClassMap.field("path", "profile.orcid");
   otherNameClassMap.fieldBToA("displayIndex", "displayIndex");
   otherNameClassMap.byDefault();
   otherNameClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public MapperFacade getAddressMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<Address, AddressEntity> addressClassMap =
       mapperFactory.classMap(Address.class, AddressEntity.class);
   addV2DateFields(addressClassMap);
   registerSourceConverters(mapperFactory, addressClassMap);
   addressClassMap.field("putCode", "id");
   addressClassMap.field("country.value", "iso2Country");
   addressClassMap.field("visibility", "visibility");
   addressClassMap.fieldBToA("displayIndex", "displayIndex");
   addressClassMap.byDefault();
   addressClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public MapperFacade getResearcherUrlMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<ResearcherUrl, ResearcherUrlEntity> researcherUrlClassMap =
       mapperFactory.classMap(ResearcherUrl.class, ResearcherUrlEntity.class);
   addV2DateFields(researcherUrlClassMap);
   registerSourceConverters(mapperFactory, researcherUrlClassMap);
   researcherUrlClassMap.field("putCode", "id");
   researcherUrlClassMap.field("url.value", "url");
   researcherUrlClassMap.field("urlName", "urlName");
   researcherUrlClassMap.fieldBToA("displayIndex", "displayIndex");
   researcherUrlClassMap.byDefault();
   researcherUrlClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public MapperFacade getNameMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<Name, RecordNameEntity> nameClassMap =
       mapperFactory.classMap(Name.class, RecordNameEntity.class);
   addV2DateFields(nameClassMap);
   nameClassMap.field("creditName.content", "creditName");
   nameClassMap.field("givenNames.content", "givenNames");
   nameClassMap.field("familyName.content", "familyName");
   nameClassMap.field("path", "profile.id");
   nameClassMap.byDefault();
   nameClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public MapperFacade getEmailMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<Email, EmailEntity> emailClassMap =
       mapperFactory.classMap(Email.class, EmailEntity.class);
   emailClassMap.byDefault();
   emailClassMap.field("email", "id");
   emailClassMap.field("primary", "primary");
   emailClassMap.field("verified", "verified");
   addV2DateFields(emailClassMap);
   registerSourceConverters(mapperFactory, emailClassMap);
   emailClassMap.register();
   return mapperFactory.getMapperFacade();
 }
 public MapperFacade getKeywordMapperFacade() {
   MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
   ClassMapBuilder<Keyword, ProfileKeywordEntity> keywordClassMap =
       mapperFactory.classMap(Keyword.class, ProfileKeywordEntity.class);
   addV2DateFields(keywordClassMap);
   registerSourceConverters(mapperFactory, keywordClassMap);
   keywordClassMap.field("putCode", "id");
   keywordClassMap.field("content", "keywordName");
   keywordClassMap.fieldBToA("displayIndex", "displayIndex");
   keywordClassMap.byDefault();
   keywordClassMap.register();
   return mapperFactory.getMapperFacade();
 }
  public MapperFacade getExternalIdentifierMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    ClassMapBuilder<PersonExternalIdentifier, ExternalIdentifierEntity> externalIdentifierClassMap =
        mapperFactory.classMap(PersonExternalIdentifier.class, ExternalIdentifierEntity.class);
    addV2DateFields(externalIdentifierClassMap);
    externalIdentifierClassMap.field("putCode", "id");
    externalIdentifierClassMap.field("type", "externalIdCommonName");
    externalIdentifierClassMap.field("value", "externalIdReference");
    externalIdentifierClassMap.field("url.value", "externalIdUrl");
    externalIdentifierClassMap.fieldBToA("displayIndex", "displayIndex");
    externalIdentifierClassMap.byDefault();
    registerSourceConverters(mapperFactory, externalIdentifierClassMap);

    // TODO: add relationship to database schema for people.
    externalIdentifierClassMap.register();
    return mapperFactory.getMapperFacade();
  }
  public MapperFacade getGroupIdRecordMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    ClassMapBuilder<GroupIdRecord, GroupIdRecordEntity> classMap =
        mapperFactory.classMap(GroupIdRecord.class, GroupIdRecordEntity.class);
    addV2CommonFields(classMap);
    registerSourceConverters(mapperFactory, classMap);
    classMap.field("name", "groupName");
    classMap.field("groupId", "groupId");
    classMap.field("description", "groupDescription");
    classMap.field("type", "groupType");
    classMap.register();

    return mapperFactory.getMapperFacade();
  }
 private ClassMapBuilder<?, ?> mapCommonFields(ClassMapBuilder<?, ?> builder) {
   return builder.field("createdDate", "dateCreated").field("putCode", "id").byDefault();
 }
  public MapperFacade getPeerReviewMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
    converterFactory.registerConverter(
        "workExternalIdentifiersConverterId", new WorkExternalIDsConverter());
    converterFactory.registerConverter(
        "workExternalIdentifierConverterId", new PeerReviewWorkExternalIDConverter());
    // do same as work

    ClassMapBuilder<PeerReview, PeerReviewEntity> classMap =
        mapperFactory.classMap(PeerReview.class, PeerReviewEntity.class);
    addV2CommonFields(classMap);
    registerSourceConverters(mapperFactory, classMap);
    classMap.field("url.value", "url");
    classMap.field("organization.name", "org.name");
    classMap.field("organization.address.city", "org.city");
    classMap.field("organization.address.region", "org.region");
    classMap.field("organization.address.country", "org.country");
    classMap.field(
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier",
        "org.orgDisambiguated.sourceId");
    classMap.field(
        "organization.disambiguatedOrganization.disambiguationSource",
        "org.orgDisambiguated.sourceType");
    classMap.field("groupId", "groupId");
    classMap.field("subjectType", "subjectType");
    classMap.field("subjectUrl.value", "subjectUrl");
    classMap.field("subjectName.title.content", "subjectName");
    classMap.field("subjectName.translatedTitle.content", "subjectTranslatedName");
    classMap.field("subjectName.translatedTitle.languageCode", "subjectTranslatedNameLanguageCode");
    classMap.field("subjectContainerName.content", "subjectContainerName");
    classMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    classMap
        .fieldMap("subjectExternalIdentifier", "subjectExternalIdentifiersJson")
        .converter("workExternalIdentifierConverterId")
        .add();

    classMap.register();

    ClassMapBuilder<PeerReviewSummary, PeerReviewEntity> peerReviewSummaryClassMap =
        mapperFactory.classMap(PeerReviewSummary.class, PeerReviewEntity.class);
    addV2CommonFields(peerReviewSummaryClassMap);
    registerSourceConverters(mapperFactory, peerReviewSummaryClassMap);
    peerReviewSummaryClassMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    peerReviewSummaryClassMap.field("organization.name", "org.name");
    peerReviewSummaryClassMap.field("organization.address.city", "org.city");
    peerReviewSummaryClassMap.field("organization.address.region", "org.region");
    peerReviewSummaryClassMap.field("organization.address.country", "org.country");
    peerReviewSummaryClassMap.field(
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier",
        "org.orgDisambiguated.sourceId");
    peerReviewSummaryClassMap.field(
        "organization.disambiguatedOrganization.disambiguationSource",
        "org.orgDisambiguated.sourceType");
    peerReviewSummaryClassMap.register();

    mapperFactory
        .classMap(FuzzyDate.class, CompletionDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();

    return mapperFactory.getMapperFacade();
  }
  public MapperFacade getEmploymentMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    ClassMapBuilder<Employment, OrgAffiliationRelationEntity> classMap =
        mapperFactory.classMap(Employment.class, OrgAffiliationRelationEntity.class);
    addV2CommonFields(classMap);
    registerSourceConverters(mapperFactory, classMap);
    classMap.field("organization.name", "org.name");
    classMap.field("organization.address.city", "org.city");
    classMap.field("organization.address.region", "org.region");
    classMap.field("organization.address.country", "org.country");
    classMap.field(
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier",
        "org.orgDisambiguated.sourceId");
    classMap.field(
        "organization.disambiguatedOrganization.disambiguationSource",
        "org.orgDisambiguated.sourceType");
    classMap.field("departmentName", "department");
    classMap.field("roleTitle", "title");
    classMap.register();

    ClassMapBuilder<EmploymentSummary, OrgAffiliationRelationEntity> employmentSummaryClassMap =
        mapperFactory.classMap(EmploymentSummary.class, OrgAffiliationRelationEntity.class);
    addV2CommonFields(employmentSummaryClassMap);
    registerSourceConverters(mapperFactory, employmentSummaryClassMap);
    employmentSummaryClassMap.field("organization.name", "org.name");
    employmentSummaryClassMap.field("organization.address.city", "org.city");
    employmentSummaryClassMap.field("organization.address.region", "org.region");
    employmentSummaryClassMap.field("organization.address.country", "org.country");
    employmentSummaryClassMap.field(
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier",
        "org.orgDisambiguated.sourceId");
    employmentSummaryClassMap.field(
        "organization.disambiguatedOrganization.disambiguationSource",
        "org.orgDisambiguated.sourceType");
    employmentSummaryClassMap.field("departmentName", "department");
    employmentSummaryClassMap.field("roleTitle", "title");
    employmentSummaryClassMap.register();

    mapperFactory
        .classMap(FuzzyDate.class, StartDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();
    mapperFactory
        .classMap(FuzzyDate.class, EndDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();
    return mapperFactory.getMapperFacade();
  }
  public MapperFacade getWorkMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
    converterFactory.registerConverter(
        "workExternalIdentifiersConverterId", new WorkExternalIDsConverter());
    converterFactory.registerConverter(
        "workContributorsConverterId", new JsonOrikaConverter<WorkContributors>());

    ClassMapBuilder<Work, WorkEntity> workClassMap =
        mapperFactory.classMap(Work.class, WorkEntity.class);
    workClassMap.byDefault();
    workClassMap.field("putCode", "id");
    addV2DateFields(workClassMap);
    registerSourceConverters(mapperFactory, workClassMap);
    workClassMap.field("journalTitle.content", "journalTitle");
    workClassMap.field("workTitle.title.content", "title");
    workClassMap.field("workTitle.translatedTitle.content", "translatedTitle");
    workClassMap.field("workTitle.translatedTitle.languageCode", "translatedTitleLanguageCode");
    workClassMap.field("workTitle.subtitle.content", "subtitle");
    workClassMap.field("shortDescription", "description");
    workClassMap.field("workCitation.workCitationType", "citationType");
    workClassMap.field("workCitation.citation", "citation");
    workClassMap.field("workType", "workType");
    workClassMap.field("publicationDate", "publicationDate");
    workClassMap
        .fieldMap("workExternalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    workClassMap.field("url.value", "workUrl");
    workClassMap
        .fieldMap("workContributors", "contributorsJson")
        .converter("workContributorsConverterId")
        .add();
    workClassMap.field("languageCode", "languageCode");
    workClassMap.field("country.value", "iso2Country");
    workClassMap.register();

    ClassMapBuilder<WorkSummary, WorkEntity> workSummaryClassMap =
        mapperFactory.classMap(WorkSummary.class, WorkEntity.class);
    registerSourceConverters(mapperFactory, workSummaryClassMap);
    workSummaryClassMap.field("putCode", "id");
    workSummaryClassMap.field("title.title.content", "title");
    workSummaryClassMap.field("title.translatedTitle.content", "translatedTitle");
    workSummaryClassMap.field("title.translatedTitle.languageCode", "translatedTitleLanguageCode");
    workSummaryClassMap.field("type", "workType");
    workSummaryClassMap.field("publicationDate", "publicationDate");
    workSummaryClassMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    workSummaryClassMap.byDefault();
    workSummaryClassMap.register();

    ClassMapBuilder<WorkSummary, MinimizedWorkEntity> workSummaryMinimizedClassMap =
        mapperFactory.classMap(WorkSummary.class, MinimizedWorkEntity.class);
    addV2CommonFields(workSummaryMinimizedClassMap);
    registerSourceConverters(mapperFactory, workSummaryMinimizedClassMap);
    workSummaryMinimizedClassMap.field("title.title.content", "title");
    workSummaryMinimizedClassMap.field("title.translatedTitle.content", "translatedTitle");
    workSummaryMinimizedClassMap.field(
        "title.translatedTitle.languageCode", "translatedTitleLanguageCode");
    workSummaryMinimizedClassMap.field("type", "workType");
    workSummaryMinimizedClassMap.field("publicationDate.year.value", "publicationYear");
    workSummaryMinimizedClassMap.field("publicationDate.month.value", "publicationMonth");
    workSummaryMinimizedClassMap.field("publicationDate.day.value", "publicationDay");
    workSummaryMinimizedClassMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    workSummaryMinimizedClassMap.byDefault();
    workSummaryMinimizedClassMap.register();

    ClassMapBuilder<Work, MinimizedWorkEntity> minimizedWorkClassMap =
        mapperFactory.classMap(Work.class, MinimizedWorkEntity.class);
    minimizedWorkClassMap.byDefault();
    registerSourceConverters(mapperFactory, minimizedWorkClassMap);
    minimizedWorkClassMap.field("putCode", "id");
    minimizedWorkClassMap.field("journalTitle.content", "journalTitle");
    minimizedWorkClassMap.field("workTitle.title.content", "title");
    minimizedWorkClassMap.field("workTitle.translatedTitle.content", "translatedTitle");
    minimizedWorkClassMap.field(
        "workTitle.translatedTitle.languageCode", "translatedTitleLanguageCode");
    minimizedWorkClassMap.field("workTitle.subtitle.content", "subtitle");
    minimizedWorkClassMap.field("shortDescription", "description");
    minimizedWorkClassMap.field("workType", "workType");
    minimizedWorkClassMap.field("publicationDate.year.value", "publicationYear");
    minimizedWorkClassMap.field("publicationDate.month.value", "publicationMonth");
    minimizedWorkClassMap.field("publicationDate.day.value", "publicationDay");
    minimizedWorkClassMap
        .fieldMap("workExternalIdentifiers", "externalIdentifiersJson")
        .converter("workExternalIdentifiersConverterId")
        .add();
    minimizedWorkClassMap.field("url.value", "workUrl");
    minimizedWorkClassMap.register();

    mapperFactory
        .classMap(PublicationDate.class, PublicationDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();

    return mapperFactory.getMapperFacade();
  }
 private void addV2CommonFields(ClassMapBuilder<?, ?> classMap) {
   classMap.byDefault();
   classMap.field("putCode", "id");
   addV2DateFields(classMap);
 }
  public MapperFacade getFundingMapperFacade() {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
    converterFactory.registerConverter(
        "fundingExternalIdentifiersConverterId", new FundingExternalIDsConverter());
    converterFactory.registerConverter(
        "fundingContributorsConverterId", new JsonOrikaConverter<FundingContributors>());

    ClassMapBuilder<Funding, ProfileFundingEntity> fundingClassMap =
        mapperFactory.classMap(Funding.class, ProfileFundingEntity.class);
    addV2CommonFields(fundingClassMap);
    registerSourceConverters(mapperFactory, fundingClassMap);
    fundingClassMap.field("type", "type");
    fundingClassMap.field("organizationDefinedType.content", "organizationDefinedType");
    fundingClassMap.field("title.title.content", "title");
    fundingClassMap.field("title.translatedTitle.content", "translatedTitle");
    fundingClassMap.field("title.translatedTitle.languageCode", "translatedTitleLanguageCode");
    fundingClassMap.field("description", "description");
    fundingClassMap.field("amount.content", "numericAmount");
    fundingClassMap.field("amount.currencyCode", "currencyCode");
    fundingClassMap.field("url.value", "url");
    fundingClassMap.fieldBToA("org.name", "organization.name");
    fundingClassMap.fieldBToA("org.city", "organization.address.city");
    fundingClassMap.fieldBToA("org.region", "organization.address.region");
    fundingClassMap.fieldBToA("org.country", "organization.address.country");
    fundingClassMap.fieldBToA(
        "org.orgDisambiguated.sourceId",
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier");
    fundingClassMap.fieldBToA(
        "org.orgDisambiguated.sourceType",
        "organization.disambiguatedOrganization.disambiguationSource");
    fundingClassMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("fundingExternalIdentifiersConverterId")
        .add();
    fundingClassMap
        .fieldMap("contributors", "contributorsJson")
        .converter("fundingContributorsConverterId")
        .add();
    fundingClassMap.register();

    ClassMapBuilder<FundingSummary, ProfileFundingEntity> fundingSummaryClassMap =
        mapperFactory.classMap(FundingSummary.class, ProfileFundingEntity.class);
    addV2CommonFields(fundingSummaryClassMap);
    registerSourceConverters(mapperFactory, fundingSummaryClassMap);
    fundingSummaryClassMap.field("type", "type");
    fundingSummaryClassMap.field("title.title.content", "title");
    fundingSummaryClassMap.field("title.translatedTitle.content", "translatedTitle");
    fundingSummaryClassMap.field(
        "title.translatedTitle.languageCode", "translatedTitleLanguageCode");
    fundingSummaryClassMap
        .fieldMap("externalIdentifiers", "externalIdentifiersJson")
        .converter("fundingExternalIdentifiersConverterId")
        .add();

    fundingSummaryClassMap.fieldBToA("org.name", "organization.name");
    fundingSummaryClassMap.fieldBToA("org.city", "organization.address.city");
    fundingSummaryClassMap.fieldBToA("org.region", "organization.address.region");
    fundingSummaryClassMap.fieldBToA("org.country", "organization.address.country");
    fundingSummaryClassMap.fieldBToA(
        "org.orgDisambiguated.sourceId",
        "organization.disambiguatedOrganization.disambiguatedOrganizationIdentifier");
    fundingSummaryClassMap.fieldBToA(
        "org.orgDisambiguated.sourceType",
        "organization.disambiguatedOrganization.disambiguationSource");

    fundingSummaryClassMap.register();

    mapperFactory
        .classMap(FuzzyDate.class, StartDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();
    mapperFactory
        .classMap(FuzzyDate.class, EndDateEntity.class)
        .field("year.value", "year")
        .field("month.value", "month")
        .field("day.value", "day")
        .register();
    return mapperFactory.getMapperFacade();
  }
 private void addV2DateFields(ClassMapBuilder<?, ?> classMap) {
   classMap.field("createdDate.value", "dateCreated");
   classMap.field("lastModifiedDate.value", "lastModified");
 }
  @Override
  public MapperFacade getObject() throws Exception {
    MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    // Register converters
    ConverterFactory converterFactory = mapperFactory.getConverterFactory();
    converterFactory.registerConverter(
        "singleWorkExternalIdentifierFromJsonConverter",
        new SingleWorkExternalIdentifierFromJsonConverter());
    converterFactory.registerConverter(
        "externalIdentifierIdConverter", new ExternalIdentifierTypeConverter());

    // Register factories
    mapperFactory.registerObjectFactory(
        new WorkEntityFactory(workDao),
        TypeFactory.<NotificationWorkEntity>valueOf(NotificationWorkEntity.class),
        TypeFactory.<Item>valueOf(Item.class));

    // Custom notification
    ClassMapBuilder<NotificationCustom, NotificationCustomEntity> notificationCustomClassMap =
        mapperFactory.classMap(NotificationCustom.class, NotificationCustomEntity.class);
    registerSourceConverters(mapperFactory, notificationCustomClassMap);
    mapCommonFields(notificationCustomClassMap).register();

    // Permission notification
    ClassMapBuilder<NotificationPermission, NotificationAddItemsEntity>
        notificationPermissionClassMap =
            mapperFactory.classMap(NotificationPermission.class, NotificationAddItemsEntity.class);
    registerSourceConverters(mapperFactory, notificationPermissionClassMap);
    mapCommonFields(
            notificationPermissionClassMap
                .field("authorizationUrl.uri", "authorizationUrl")
                .field("items.items", "notificationItems")
                .customize(
                    new CustomMapper<NotificationPermission, NotificationAddItemsEntity>() {
                      @Override
                      public void mapAtoB(
                          NotificationPermission notification,
                          NotificationAddItemsEntity entity,
                          MappingContext context) {
                        if (StringUtils.isBlank(entity.getAuthorizationUrl())) {
                          String authUrl =
                              orcidUrlManager.getBaseUrl()
                                  + notification.getAuthorizationUrl().getPath();
                          // validate
                          validateAndConvertToURI(authUrl);
                          entity.setAuthorizationUrl(authUrl);
                        }
                      }

                      @Override
                      public void mapBtoA(
                          NotificationAddItemsEntity entity,
                          NotificationPermission notification,
                          MappingContext context) {
                        AuthorizationUrl authUrl = notification.getAuthorizationUrl();
                        if (authUrl != null) {
                          authUrl.setPath(extractFullPath(authUrl.getUri()));
                          authUrl.setHost(orcidUrlManager.getBaseHost());
                        }
                      }
                    }))
        .register();

    // Institutional sign in notification
    ClassMapBuilder<NotificationInstitutionalConnection, NotificationInstitutionalConnectionEntity>
        institutionalConnectionNotificationClassMap =
            mapperFactory.classMap(
                NotificationInstitutionalConnection.class,
                NotificationInstitutionalConnectionEntity.class);
    registerSourceConverters(mapperFactory, institutionalConnectionNotificationClassMap);
    mapCommonFields(
            institutionalConnectionNotificationClassMap
                .field("authorizationUrl.uri", "authorizationUrl")
                .customize(
                    new CustomMapper<
                        NotificationInstitutionalConnection,
                        NotificationInstitutionalConnectionEntity>() {
                      @Override
                      public void mapAtoB(
                          NotificationInstitutionalConnection notification,
                          NotificationInstitutionalConnectionEntity entity,
                          MappingContext context) {
                        if (StringUtils.isBlank(entity.getAuthorizationUrl())) {
                          String authUrl =
                              orcidUrlManager.getBaseUrl()
                                  + notification.getAuthorizationUrl().getPath();
                          // validate
                          validateAndConvertToURI(authUrl);
                          entity.setAuthorizationUrl(authUrl);
                        }
                      }

                      @Override
                      public void mapBtoA(
                          NotificationInstitutionalConnectionEntity entity,
                          NotificationInstitutionalConnection notification,
                          MappingContext context) {
                        AuthorizationUrl authUrl = notification.getAuthorizationUrl();
                        if (authUrl != null) {
                          authUrl.setPath(extractFullPath(authUrl.getUri()));
                          authUrl.setHost(orcidUrlManager.getBaseHost());
                        }
                        String providerId = entity.getAuthenticationProviderId();
                        if (StringUtils.isNotBlank(providerId)) {
                          String idpName =
                              identityProviderManager.retrieveIdentitifyProviderName(providerId);
                          notification.setIdpName(idpName);
                        } else {
                          notification.setIdpName(LAST_RESORT_IDENTITY_PROVIDER_NAME);
                        }
                      }
                    }))
        .register();

    // Amend notification
    ClassMapBuilder<NotificationAmended, NotificationAmendedEntity> amendNotificationClassMap =
        mapperFactory.classMap(NotificationAmended.class, NotificationAmendedEntity.class);
    registerSourceConverters(mapperFactory, amendNotificationClassMap);
    mapCommonFields(amendNotificationClassMap).register();
    mapperFactory
        .classMap(NotificationItemEntity.class, Item.class)
        .fieldMap("externalIdType", "externalIdentifier.type")
        .converter("externalIdentifierIdConverter")
        .add()
        .field("externalIdValue", "externalIdentifier.value")
        .byDefault()
        .register();

    return mapperFactory.getMapperFacade();
  }