org.orcid.core.manager.impl.ValidationManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.orcid.core.manager.impl.ValidationManagerImpl.java

Source

/**
 * =============================================================================
 *
 * ORCID (R) Open Source
 * http://orcid.org
 *
 * Copyright (c) 2012-2014 ORCID, Inc.
 * Licensed under an MIT-Style License (MIT)
 * http://orcid.org/open-source-license
 *
 * This copyright and license information (including a link to the full license)
 * shall be included in its entirety in all copies or substantial portion of
 * the software.
 *
 * =============================================================================
 */
package org.orcid.core.manager.impl;

import java.io.IOException;
import java.util.List;

import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.lang3.StringUtils;
import org.orcid.core.cli.ValidateOrcidMessage;
import org.orcid.core.exception.OrcidValidationException;
import org.orcid.core.manager.ValidationBehaviour;
import org.orcid.core.manager.ValidationManager;
import org.orcid.jaxb.model.message.ContactDetails;
import org.orcid.jaxb.model.message.Email;
import org.orcid.jaxb.model.message.Funding;
import org.orcid.jaxb.model.message.FundingList;
import org.orcid.jaxb.model.message.OrcidActivities;
import org.orcid.jaxb.model.message.OrcidBio;
import org.orcid.jaxb.model.message.OrcidMessage;
import org.orcid.jaxb.model.message.OrcidProfile;
import org.orcid.jaxb.model.message.OrcidWork;
import org.orcid.jaxb.model.message.OrcidWorks;
import org.orcid.jaxb.model.message.WorkTitle;
import org.orcid.pojo.ajaxForm.PojoUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;

/**
 * 
 * @author Will Simpson
 * 
 */
public class ValidationManagerImpl implements ValidationManager {

    private ValidationBehaviour validationBehaviour = ValidationBehaviour.LOG_WARNING;

    private String version = OrcidMessage.DEFAULT_VERSION;

    private boolean requireOrcidProfile;

    private boolean validateBibtex = true;

    private boolean validateTitle = false;

    private boolean validateOnlyOnePrimaryEmail = false;

    private boolean validateWorksHaveExternalIds = false;

    private boolean validateFundingHaveExternalIds = false;

    private Schema schema;

    private static final Logger LOG = LoggerFactory.getLogger(ValidationManagerImpl.class);

    @Override
    public void setValidationBehaviour(ValidationBehaviour validationBehaviour) {
        this.validationBehaviour = validationBehaviour;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public void setRequireOrcidProfile(boolean requireOrcidProfile) {
        this.requireOrcidProfile = requireOrcidProfile;
    }

    public void setValidateBibtex(boolean validateBibtex) {
        this.validateBibtex = validateBibtex;
    }

    public void setValidateTitle(boolean validateTitle) {
        this.validateTitle = validateTitle;
    }

    public boolean isValidateOnlyOnePrimaryEmail() {
        return validateOnlyOnePrimaryEmail;
    }

    public void setValidateOnlyOnePrimaryEmail(boolean validateOnlyOnePrimaryEmail) {
        this.validateOnlyOnePrimaryEmail = validateOnlyOnePrimaryEmail;
    }

    public boolean isValidateWorksHaveExternalIds() {
        return validateWorksHaveExternalIds;
    }

    public void setValidateWorksHaveExternalIds(boolean validateWorksHaveExternalIds) {
        this.validateWorksHaveExternalIds = validateWorksHaveExternalIds;
    }

    public boolean isValidateFundingHaveExternalIds() {
        return validateFundingHaveExternalIds;
    }

    public void setValidateFundingHaveExternalIds(boolean validateFundingHaveExternalIds) {
        this.validateFundingHaveExternalIds = validateFundingHaveExternalIds;
    }

    @Override
    public void validateMessage(OrcidMessage orcidMessage) {
        if (ValidationBehaviour.IGNORE.equals(validationBehaviour)) {
            return;
        }
        doMessageVersionValidation(orcidMessage);
        doWorkTypeValidation(orcidMessage);
        doSchemaValidation(orcidMessage);
        doCustomValidation(orcidMessage);
    }

    @Override
    public void validateBioMessage(OrcidMessage orcidMessage) {
        if (ValidationBehaviour.IGNORE.equals(validationBehaviour)) {
            return;
        }
        doMessageVersionValidation(orcidMessage);
        doSchemaValidation(orcidMessage);
    }

    private void doMessageVersionValidation(OrcidMessage orcidMessage) {
        if (orcidMessage != null) {
            if (PojoUtil.isEmpty(orcidMessage.getMessageVersion())) {
                handleError("Message version is required");
            }
        }
    }

    private void doWorkTypeValidation(OrcidMessage orcidMessage) {
        if (orcidMessage == null || orcidMessage.getOrcidProfile() == null
                || orcidMessage.getOrcidProfile().getOrcidActivities() == null
                || orcidMessage.getOrcidProfile().getOrcidActivities().getOrcidWorks() == null
                || orcidMessage.getOrcidProfile().getOrcidActivities().getOrcidWorks().getOrcidWork() == null
                || orcidMessage.getOrcidProfile().getOrcidActivities().getOrcidWorks().getOrcidWork().isEmpty())
            return;
        List<OrcidWork> works = orcidMessage.getOrcidProfile().getOrcidActivities().getOrcidWorks().getOrcidWork();
        for (OrcidWork work : works) {
            if (work.getWorkType() == null)
                if (work.getWorkTitle() != null && work.getWorkTitle().getTitle() != null
                        && !PojoUtil.isEmpty(work.getWorkTitle().getTitle().getContent()))
                    handleError("work-type is missing or invalid for work: '"
                            + work.getWorkTitle().getTitle().getContent() + "'");
                else
                    handleError("work-type is missing or invalid");
        }
    }

    protected void doSchemaValidation(OrcidMessage orcidMessage) {
        Validator validator = createValidator();
        if (validator != null) {
            try {
                validator.validate(orcidMessage.toSource());
            } catch (SAXException e) {
                handleError("ORCID message is invalid", e, orcidMessage);
            } catch (IOException e) {
                handleError("Unable to read ORCID message", e, orcidMessage);
            }
        }
    }

    public void doCustomValidation(OrcidMessage orcidMessage) {
        try {
            checkMessage(orcidMessage);
        } catch (OrcidValidationException e) {
            handleError("Custom validation found a problem", e, orcidMessage);
        }
    }

    private void checkMessage(OrcidMessage orcidMessage) {
        OrcidProfile orcidProfile = orcidMessage != null ? orcidMessage.getOrcidProfile() : null;
        if (orcidProfile == null) {
            if (requireOrcidProfile) {
                throw new OrcidValidationException("There must be an orcid-profile element");
            }
        } else {
            checkBio(orcidProfile.getOrcidBio());
            checkActivities(orcidProfile.getOrcidActivities());
        }
    }

    private void checkBio(OrcidBio orcidBio) {
        if (orcidBio != null) {
            checkContactDetails(orcidBio.getContactDetails());
        }
    }

    private void checkContactDetails(ContactDetails contactDetails) {
        if (contactDetails != null) {
            List<Email> emailList = contactDetails.getEmail();
            int primaryCount = 0;
            for (Email email : emailList) {
                if (email.isPrimary()) {
                    primaryCount++;
                }
            }
            if (primaryCount > 1) {
                throw new OrcidValidationException("There must not be more than one primary email");
            }

            if (validateOnlyOnePrimaryEmail) {
                if (primaryCount == 0)
                    throw new OrcidValidationException("There must be at least one primary email");
            }
        }
    }

    private void checkActivities(OrcidActivities orcidActivities) {
        if (orcidActivities != null) {
            OrcidWorks works = orcidActivities.getOrcidWorks();
            if (works != null && works.getOrcidWork() != null && !works.getOrcidWork().isEmpty()) {
                checkWorks(works.getOrcidWork());
            }

            FundingList funding = orcidActivities.getFundings();
            if (funding != null && funding.getFundings() != null && !funding.getFundings().isEmpty()) {
                checkFunding(funding.getFundings());
            }
        }
    }

    private void checkWorks(List<OrcidWork> orcidWork) {
        for (OrcidWork work : orcidWork) {
            checkWork(work);
        }
    }

    public void checkWork(OrcidWork orcidWork) {

        if (validateTitle) {
            WorkTitle title = orcidWork.getWorkTitle();
            if (title == null || title.getTitle() == null || StringUtils.isEmpty(title.getTitle().getContent())) {
                throw new OrcidValidationException("Invalid Title: title cannot be null nor emtpy");
            }
        }

        if (validateWorksHaveExternalIds) {
            if (orcidWork.getWorkExternalIdentifiers() == null
                    || orcidWork.getWorkExternalIdentifiers().getWorkExternalIdentifier() == null
                    || orcidWork.getWorkExternalIdentifiers().getWorkExternalIdentifier().isEmpty()) {
                throw new OrcidValidationException(
                        "Invalid work: Works added using message version 1.2_rc5 or greater must contain at least one external identifier");
            }
        }
    }

    private void checkFunding(List<Funding> fundings) {
        for (Funding funding : fundings) {
            checkFunding(funding);
        }
    }

    private void checkFunding(Funding funding) {
        if (validateFundingHaveExternalIds) {
            if (funding.getFundingExternalIdentifiers() == null
                    || funding.getFundingExternalIdentifiers().getFundingExternalIdentifier() == null
                    || funding.getFundingExternalIdentifiers().getFundingExternalIdentifier().isEmpty()) {
                throw new OrcidValidationException(
                        "Invalid funding: Funding added using message version 1.2_rc5 or greater must contain at least one external identifier");
            }
        }

        if (funding.getStartDate() != null) {
            if (!PojoUtil.isEmpty(funding.getStartDate().getMonth())
                    && PojoUtil.isEmpty(funding.getStartDate().getYear())) {
                throw new OrcidValidationException("Invalid funding: Invalid start date");
            }
        }

        if (funding.getEndDate() != null) {
            if (!PojoUtil.isEmpty(funding.getEndDate().getMonth())
                    && PojoUtil.isEmpty(funding.getEndDate().getYear())) {
                throw new OrcidValidationException("Invalid funding: Invalid end date");
            }
        }
    }

    private void initSchema() {
        if (schema == null) {
            SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
            try {
                schema = factory
                        .newSchema(ValidateOrcidMessage.class.getResource("/orcid-message-" + version + ".xsd"));
            } catch (SAXException e) {
                handleError("Error initializing schema", e);
            }
        }
    }

    private Validator createValidator() {
        initSchema();
        if (schema == null) {
            handleError("Unable to create validator because schema is null");
        }
        return schema.newValidator();
    }

    private void handleError(String message) {
        handleError(message, null, null);
    }

    private void handleError(String message, Throwable t) {
        handleError(message, t, null);
    }

    private void handleError(String message, Throwable t, OrcidMessage orcidMessage) {
        switch (validationBehaviour) {
        case IGNORE:
            break;
        case LOG_INFO:
            LOG.info(message, t);
            break;
        case LOG_WARNING:
            LOG.warn(message, t);
            break;
        case LOG_ERROR:
            LOG.error(message, t);
            break;
        case LOG_INFO_WITH_XML:
            LOG.info(message, t);
            if (orcidMessage != null) {
                LOG.info("ORCID message is: {}", orcidMessage);
            }
            break;
        case LOG_WARNING_WITH_XML:
            LOG.warn(message, t);
            if (orcidMessage != null) {
                LOG.warn("ORCID message is: {}", orcidMessage);
            }
            break;
        case LOG_ERROR_WITH_XML:
            LOG.error(message, t);
            if (orcidMessage != null) {
                LOG.error("ORCID message is: {}", orcidMessage);
            }
            break;
        case THROW_VALIDATION_EXCEPTION:
            if (t instanceof OrcidValidationException) {
                throw (OrcidValidationException) t;
            } else {
                throw new OrcidValidationException(message, t);
            }
        default:
            throw new RuntimeException("Unknown validation behaviour: " + validationBehaviour);
        }
    }
}