org.opentestsystem.delivery.AccValidator.handlers.ValidationHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.opentestsystem.delivery.AccValidator.handlers.ValidationHandler.java

Source

/*******************************************************************************
 * Educational Online Test Delivery System Copyright (c) 2015 American
 * Institutes for Research
 * 
 * Distributed under the AIR Open Source License, Version 1.0 See accompanying
 * file AIR-License-1_0.txt or at http://www.smarterapp.org/documents/
 * American_Institutes_for_Research_Open_Source_Software_License.pdf
 ******************************************************************************/
package org.opentestsystem.delivery.AccValidator.handlers;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import javax.xml.XMLConstants;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.lang.StringUtils;
import org.opentestsystem.delivery.AccValidator.Data.AccFamilySubject;
import org.opentestsystem.delivery.AccValidator.Data.AccommodationOption;
import org.opentestsystem.delivery.AccValidator.Data.AccommodationText;
import org.opentestsystem.delivery.AccValidator.Data.MasterResourceAccommodation;
import org.opentestsystem.delivery.AccValidator.Data.ResourceFamily;
import org.opentestsystem.delivery.AccValidator.Exception.StoringException;
import org.opentestsystem.delivery.AccValidator.Exception.ValidationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.CommandFailureException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;

/**
 * Handles requests for the application home page.
 */

public class ValidationHandler {

    private static final Logger _logger = LoggerFactory.getLogger(ValidationHandler.class);

    @Value("${XmlValidation.configFilePath}")
    String _filePath;

    @Value("${XmlValidation.xsdFilePath}")
    String _xsdPath;

    @Value("${mongo.hostname}")
    String _mongoHostName;
    @Value("${mongo.portNumber}")
    String _mongoPort;
    @Value("${mongo.username}")
    String _mongoUserName;
    @Value("${mongo.password}")
    String _mongoPassword;
    @Value("${mongo.databasename}")
    String _mongoDatabaseName;

    String _nodeName = null;
    static List<MasterResourceAccommodation> _masterResourceAccommodations = null;
    static List<ResourceFamily> _resourceFamilies = new ArrayList<ResourceFamily>();
    static String _hostName = null;
    static String _port = null;
    static String _userName = null;
    static String _password = null;
    static String _databaseName = null;
    static final String EMPTY = "";

    public void setDBInfo(String hostName, String port, String user, String password, String databaseName) {
        this._hostName = hostName;
        this._port = port;
        this._userName = user;
        this._password = password;
        this._databaseName = databaseName;
    }

    public void validateXmlAccs(String filePath, String xsdPath) throws ValidationException {
        try {
            InputStream xmlInput = new FileInputStream(new File(filePath));
            InputStream xsdInput = new FileInputStream(new File(xsdPath));

            String text = null;
            XMLInputFactory factory = XMLInputFactory.newInstance();
            factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
            XMLStreamReader reader = factory.createXMLStreamReader(xmlInput);

            boolean firstSelect = true;
            MasterResourceAccommodation masterResource = null;
            List<MasterResourceAccommodation> resourceFamiltyMasterResourceAccommodations = null;
            AccommodationText accommodationText = null;
            List<AccommodationText> accommodationTexts = null;
            AccommodationOption accommodationOption = null;
            List<AccommodationOption> accommodationOptions = null;
            AccFamilySubject familySubject = null;
            List<AccFamilySubject> familySubjects = null;
            ResourceFamily resourceFamily = null;
            List<String> grades = null;

            while (reader.hasNext()) {
                int Event = reader.next();
                switch (Event) {
                case XMLStreamConstants.START_ELEMENT: {
                    switch (reader.getLocalName()) {
                    case "MasterResourceFamily":
                        _masterResourceAccommodations = new ArrayList<MasterResourceAccommodation>();

                        break;
                    case "SingleSelectResource":
                        masterResource = new MasterResourceAccommodation();
                        accommodationTexts = new ArrayList<AccommodationText>();
                        accommodationOptions = new ArrayList<AccommodationOption>();
                        break;

                    case "MultiSelectResource":
                        masterResource = new MasterResourceAccommodation();
                        accommodationTexts = new ArrayList<AccommodationText>();
                        accommodationOptions = new ArrayList<AccommodationOption>();
                        break;
                    case "EditResource":
                        masterResource = new MasterResourceAccommodation();
                        accommodationTexts = new ArrayList<AccommodationText>();
                        accommodationOptions = new ArrayList<AccommodationOption>();
                        break;
                    case "ResourceFamily":
                        masterResource = new MasterResourceAccommodation();
                        familySubjects = new ArrayList<AccFamilySubject>();
                        resourceFamily = new ResourceFamily();
                        accommodationTexts = new ArrayList<AccommodationText>();
                        accommodationText = new AccommodationText();
                        resourceFamiltyMasterResourceAccommodations = new ArrayList<MasterResourceAccommodation>();
                        grades = new ArrayList<String>();
                        break;
                    case "Subject":
                        familySubject = new AccFamilySubject();
                        break;
                    case "Selection":
                        if (firstSelect) {
                            masterResource.setHeader(accommodationTexts);
                            accommodationOption = new AccommodationOption();
                            accommodationTexts = new ArrayList<AccommodationText>();
                        } else {
                            accommodationOption = new AccommodationOption();
                        }
                        firstSelect = false;
                        break;

                    case "Text":
                        accommodationText = new AccommodationText();

                        break;
                    default:
                        break;
                    }
                    break;
                }
                case XMLStreamConstants.CHARACTERS: {
                    String nodeValue = getContents(reader.getText());
                    if (nodeValue.length() > 0) {
                        text = nodeValue;
                    }
                    break;
                }
                case XMLStreamConstants.END_ELEMENT: {
                    switch (reader.getLocalName()) {
                    case "Code":
                        if (accommodationOption == null) {
                            if (familySubject == null) {
                                masterResource.setCode(text);
                            } else {
                                familySubject.setCode(text);
                            }
                        } else {
                            accommodationOption.setCode(text);
                        }
                        text = null;
                        break;
                    case "Order":
                        if (accommodationOption == null) {
                            masterResource.setOrder(Integer.valueOf(text));
                        } else {
                            accommodationOption.setOrder(Integer.valueOf(text));
                        }
                        text = null;
                        break;
                    case "MutuallyExclusive":
                        accommodationOption.setMutuallyExclusive(true);
                        text = null;
                        break;
                    case "DefaultSelection":
                        masterResource.setDefaultSelection(text);
                        text = null;
                        break;
                    case "Disabled":
                        masterResource.setDisabled(true);
                        text = null;
                        break;
                    case "Language":
                        accommodationText.setLanguage(text);
                        text = null;
                        break;
                    case "Label":
                        accommodationText.setLabel(text);
                        text = null;
                        break;
                    case "Description":
                        accommodationText.setDescription(text);
                        text = null;
                        break;
                    case "Message":
                        accommodationText.setMessage(text);
                        text = null;
                        break;
                    case "Text":
                        accommodationTexts.add(accommodationText);
                        text = null;
                        break;
                    case "Selection":
                        accommodationOption.setText(accommodationTexts);
                        accommodationOptions.add(accommodationOption);
                        accommodationOption = new AccommodationOption();
                        accommodationTexts = new ArrayList<AccommodationText>();
                        text = null;
                        break;
                    case "SingleSelectResource":
                        masterResource.setResourceType("SingleSelectResource");
                        if (accommodationTexts.size() > 0) {
                            masterResource.setHeader(accommodationTexts);
                        }
                        masterResource.setOptions(accommodationOptions);
                        if (resourceFamily == null) {
                            _masterResourceAccommodations.add(masterResource);
                        } else {
                            resourceFamiltyMasterResourceAccommodations.add(masterResource);
                        }
                        masterResource = null;
                        accommodationOption = null;
                        accommodationOption = null;
                        firstSelect = true;
                        text = null;
                        break;
                    case "MultiSelectResource":
                        masterResource.setResourceType("MultiSelectResource");
                        if (accommodationTexts.size() > 0) {
                            masterResource.setHeader(accommodationTexts);
                        }
                        masterResource.setOptions(accommodationOptions);
                        if (resourceFamily == null) {
                            _masterResourceAccommodations.add(masterResource);
                        } else {
                            resourceFamiltyMasterResourceAccommodations.add(masterResource);
                        }
                        masterResource = null;
                        accommodationOption = null;
                        accommodationOption = null;
                        firstSelect = true;
                        text = null;
                        break;
                    case "EditResource":
                        masterResource.setResourceType("EditResource");
                        if (accommodationTexts.size() > 0) {
                            masterResource.setHeader(accommodationTexts);
                        }
                        masterResource.setOptions(accommodationOptions);
                        if (resourceFamily == null) {
                            _masterResourceAccommodations.add(masterResource);
                        } else {
                            resourceFamiltyMasterResourceAccommodations.add(masterResource);
                        }
                        masterResource = null;
                        accommodationOption = null;
                        accommodationOption = null;
                        firstSelect = true;
                        text = null;
                        break;
                    case "ResourceFamily":
                        resourceFamily.setSubject(familySubjects);
                        resourceFamily.setGrade(grades);
                        resourceFamily.setMasterResourceAccommodation(resourceFamiltyMasterResourceAccommodations);
                        _resourceFamilies.add(resourceFamily);
                        familySubjects = null;
                        grades = null;
                        resourceFamily = null;
                        resourceFamiltyMasterResourceAccommodations = null;
                        text = null;
                        break;
                    case "Name":
                        familySubject.setName(text);
                        text = null;
                        break;
                    case "Subject":
                        familySubjects.add(familySubject);
                        familySubject = null;
                        text = null;
                        break;
                    case "Grade":
                        grades.add(text);
                        text = null;
                        break;
                    }
                    break;
                }
                }
            }

            validateRules(_masterResourceAccommodations, _resourceFamilies);
            // validation against xsd
            xmlInput = new FileInputStream(new File(filePath));
            xsdInput = new FileInputStream(new File(xsdPath));
            validateAgainstXSD(xmlInput, xsdInput);

        } catch (IOException e) {
            throw new ValidationException("failed",
                    "The xml could not be parsed into objects. The error message is:" + e.getMessage());
        } catch (XMLStreamException e) {
            throw new ValidationException("failed",
                    "The xml could not be parsed into objects. The error message is:" + e.getMessage());
        }
    }

    /**
     * @param masterResourceAccommodations
     * @param resourceFamilies
     * @throws ValidationException
     */
    private boolean validateRules(List<MasterResourceAccommodation> masterResourceAccommodations,
            List<ResourceFamily> resourceFamilies) throws ValidationException {
        HashMap<String, MasterResourceAccommodation> masterResourcesMap = new HashMap<String, MasterResourceAccommodation>();
        HashSet<Integer> resourceOrders = new HashSet<Integer>();
        for (MasterResourceAccommodation resource : masterResourceAccommodations) {
            if (masterResourcesMap.containsKey(resource.getCode())) {
                _logger.error(
                        "Multiple resource with code:" + resource.getCode() + " within MasterResourceFamily.");
                throw new ValidationException("failed",
                        "Multiple resource with code:" + resource.getCode() + " within MasterResourceFamily.");
            }
            // Validating resource code to see if there is any invalid character
            if (!validateCode(resource.getCode())) {
                _logger.error("Code contains invalid character ('\"',''','&','<','>',' ') for resource:"
                        + resource.getCode() + " within Masterresourcefamily");
                throw new ValidationException("failed",
                        "Code contains invalid character ('\"',''','&','<','>',' ') for resource:"
                                + resource.getCode() + " within Masterresourcefamily");
            }

            if (!validateAccommodationCodes(resource.getCode())) {
                _logger.error("Code contains invalid character (' ',',',';','\t') for resource:"
                        + resource.getCode() + " within Masterresourcefamily");
                throw new ValidationException("failed",
                        "Code contains invalid character (' ',',',';','\t') for resource:" + resource.getCode()
                                + " within Masterresourcefamily");
            }

            // Order must be positive integer
            if (resource.getOrder() <= 0) {
                _logger.error("Order must be positive for resource:" + resource.getCode()
                        + " within Masterresourcefamily");
                throw new ValidationException("failed", "Order must be positive integer for resource:"
                        + resource.getCode() + " within Masterresourcefamily");
            } else {
                HashSet<Integer> selectionOrders = new HashSet<Integer>();
                if (resourceOrders.contains(resource.getOrder())) {
                    _logger.error("Order must not repeat:" + resource.getCode() + " within Masterresourcefamily ");
                    throw new ValidationException("failed",
                            "Order must not repeat:" + resource.getCode() + " within Masterresourcefamily");
                } else {
                    resourceOrders.add(resource.getOrder());
                }
                for (AccommodationOption selection : resource.getOptions()) {

                    if (!validateAccommodationCodes(selection.getCode())) {
                        _logger.error("Code contains invalid character (' ',',',';','\t') in Selection code :"
                                + selection.getCode() + "for Resource: " + resource.getCode()
                                + " within Masterresourcefamily");
                        throw new ValidationException("failed",
                                "Code contains invalid character (' ',',',';','\t') in Selection code :"
                                        + selection.getCode() + "for Resource: " + resource.getCode()
                                        + " within Masterresourcefamily");
                    }

                    if (selection.getOrder() <= 0) {
                        _logger.error("Order must be positive for resource:" + resource.getCode()
                                + " within Masterresourcefamily and selection: " + selection.getCode());
                        throw new ValidationException("failed",
                                "Order must be positive integer for resource:" + resource.getCode()
                                        + " within Masterresourcefamily and selection: " + selection.getCode());
                    }
                    if (selectionOrders.contains(selection.getOrder())) {
                        _logger.error("Order must not repeat:" + resource.getCode()
                                + " within Masterresourcefamily and selection: " + selection.getCode());
                        throw new ValidationException("failed", "Order must not repeat:" + resource.getCode()
                                + " within Masterresourcefamily and selection: " + selection.getCode());
                    } else {
                        selectionOrders.add(selection.getOrder());
                    }
                    List<AccommodationText> accTexts = selection.getText();
                    if (accTexts != null) {
                        Boolean isValidText = false;
                        for (AccommodationText text : accTexts) {
                            if (text.getLanguage().equalsIgnoreCase("eng")) {
                                isValidText = true;
                                break;
                            }
                        }
                        if (!isValidText) {
                            _logger.error("English is a required language:" + resource.getCode()
                                    + " within Masterresourcefamily and selection: " + selection.getCode());
                            throw new ValidationException("failed",
                                    "English is a required language:" + resource.getCode()
                                            + " within Masterresourcefamily and selection: " + selection.getCode());
                        }
                    }
                }
            }
            masterResourcesMap.put(resource.getCode(), resource);
        }

        HashMap<String, List<String>> resourceFamilyMap = new HashMap<String, List<String>>();

        for (ResourceFamily resourceFamily : resourceFamilies) {
            /*
             * 2. The subject and grade(s) for a Resource Family must be defined in
             * the Resource Family.
             */
            if (resourceFamily.getSubject() == null || resourceFamily.getSubject().size() <= 0) {
                _logger.error(
                        "ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + " has no subject defined");
                throw new ValidationException("failed",
                        "ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + " has no subject defined");
            }
            if (resourceFamily.getGrade() == null || resourceFamily.getGrade().size() <= 0) {
                _logger.error(
                        "ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + " has no grade defined");
                throw new ValidationException("failed",
                        "ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + " has no grade defined");
            }
            /*
             * 4. If a Resource Family is defined for a subject-grade combination that
             * is already defined by a previous Resource Family, The second Resource
             * Family will be ignored in favor of the settings of the first Resource
             * Family that covers the particular subject-grade combination.
             */
            String subjectCode = resourceFamily.getSubject().get(0).getCode();
            if (!StringUtils.isEmpty(subjectCode) && resourceFamilyMap.containsKey(subjectCode)) {
                List<String> grades = resourceFamilyMap.get(subjectCode);
                List<String> newGrades = resourceFamily.getGrade();
                List<String> commonGrades = new ArrayList<String>();
                if (!grades.isEmpty() && !newGrades.isEmpty()) {
                    for (int i = 0; i < newGrades.size(); i++) {
                        if (grades.contains(newGrades.get(i))) {
                            commonGrades.add(newGrades.get(i));
                        }
                    }
                    if (!commonGrades.isEmpty()) {
                        _logger.error(
                                "Subject:" + subjectCode + " and grades:" + commonGrades + " in ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily) + " already exists.");
                        throw new ValidationException("failed",
                                "Subject:" + subjectCode + " and grades:" + commonGrades + " in ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily) + " already exists.");
                    } else {
                        List<String> modifiedGrades = new ArrayList<String>();
                        modifiedGrades.addAll(grades);
                        modifiedGrades.addAll(newGrades);
                        resourceFamilyMap.put(subjectCode, modifiedGrades);
                    }
                }
            } else {
                resourceFamilyMap.put(subjectCode, resourceFamily.getGrade());
            }
            /*
             * 1. Resource codes and selection codes in Resource Families must be
             * present in the Master Resource Family. No new resources or selections
             * can be defined in subesquent Resource Familes.
             */
            HashMap<String, Boolean> resourcesCode = new HashMap<String, Boolean>();

            for (MasterResourceAccommodation resource : resourceFamily.getMasterResourceAccommodation()) {
                MasterResourceAccommodation masterResource = masterResourcesMap.get(resource.getCode());

                if (masterResource == null) {
                    _logger.error("Resource code:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                            + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                            + " does not exist in master.");
                    throw new ValidationException("failed",
                            "Resource code:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                    + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                                    + " does not exist in master.");
                }

                if (!validateAccommodationCodes(resource.getCode())) {
                    _logger.error("Resource code:" + resource.getCode()
                            + "contains invalid character (' ',',',';','\t') in ResourceFamily:"
                            + resourceFamilies.indexOf(resourceFamily));
                    throw new ValidationException("failed",
                            "Resource code:" + resource.getCode()
                                    + "contains invalid character (' ',',',';','\t') in ResourceFamily:"
                                    + resourceFamilies.indexOf(resourceFamily));
                }

                // Duplicate resources not allowed
                if (resourcesCode.containsKey(resource.getCode())) {
                    _logger.error("Resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                            + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + " is duplicated.");
                    throw new ValidationException("failed",
                            "Resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                    + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                                    + " is duplicated.");
                } else {
                    resourcesCode.put(resource.getCode(), true);
                }
                /*
                 * 6. The following things for a resource defined in the Master Resource
                 * Family cannot be overriden: Code, Order Type, Text/Label,
                 * Text/Description. This restriction ensures consistency of the
                 * resource for tabular user interface and file upload formats. Only the
                 * resource default selection can be overridden.
                 */

                // header can't be overridden in resource
                if (resource.getHeader() != null && resource.getHeader().size() > 0) {
                    _logger.error("Header for resource:" + resource.getCode() + "(" + resource.getResourceType()
                            + ")" + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                            + " can't be overridden.");
                    throw new ValidationException("failed",
                            "Header for resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                    + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                                    + " can't be overridden.");
                }

                // order can't be overridden in resource
                if (resource.getOrder() > 0 && masterResource.getOrder() != resource.getOrder()) {
                    _logger.error("For resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                            + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                            + " there is mismatch in order.");
                    throw new ValidationException("failed",
                            "For resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                    + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                                    + " there is mismatch in order.");
                }
                HashMap<String, AccommodationOption> selectionsMap = new HashMap<String, AccommodationOption>();
                for (AccommodationOption selection : masterResource.getOptions()) {
                    if (selectionsMap.containsKey(selection.getCode())) {
                        _logger.error("For master resource:" + masterResource.getCode() + "("
                                + masterResource.getResourceType() + ")" + " has duplicate selection:"
                                + selection.getCode());
                        throw new ValidationException("failed",
                                "For master resource:" + masterResource.getCode() + "("
                                        + masterResource.getResourceType() + ")" + " has duplicate selection:"
                                        + selection.getCode());
                    }
                    selectionsMap.put(selection.getCode(), selection);
                }

                boolean defaultFound = false;
                HashMap<String, Boolean> resourceFamilySelectionsMap = new HashMap<String, Boolean>();
                for (AccommodationOption selection : resource.getOptions()) {

                    if (!validateAccommodationCodes(selection.getCode())) {
                        _logger.error("Code contains invalid character (' ',',',';','\t') in Selection code:("
                                + selection.getCode() + ") for Resource: (" + resource.getCode() + ")" + "("
                                + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                + resourceFamilies.indexOf(resourceFamily));
                        throw new ValidationException("failed",
                                "Code contains invalid character (' ',',',';','\t') in Selection code :("
                                        + selection.getCode() + ") for Resource: (" + resource.getCode() + ")" + "("
                                        + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily));
                    }

                    if (resourceFamilySelectionsMap.containsKey(selection.getCode())) {
                        _logger.error("For resource(ResourceFamily:" + resourceFamilies.indexOf(resourceFamily)
                                + "):" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                + " has duplicate selection:" + selection.getCode());
                        throw new ValidationException("failed",
                                "For resource(ResourceFamily:" + resourceFamilies.indexOf(resourceFamily) + "):"
                                        + resource.getCode() + "(" + resource.getResourceType() + ")"
                                        + " has duplicate selection:" + selection.getCode());
                    }
                    resourceFamilySelectionsMap.put(selection.getCode(), true);

                    String code = selection.getCode();
                    // Order must be positive integer
                    if (selection.getOrder() != null && selection.getOrder() <= 0) {
                        _logger.error("Order must be positive integer for selection:" + selection.getCode()
                                + " in resource:" + resource.getCode() + "(" + resource.getResourceType() + ")"
                                + " inside ResourceFamily:" + resourceFamilies.indexOf(resourceFamily));
                        throw new ValidationException("failed",
                                "Order must be positive integer for selection:" + selection.getCode()
                                        + " in resource:" + resource.getCode() + "(" + resource.getResourceType()
                                        + ")" + " inside ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily));
                    }
                    // order can't be overridden in selection
                    if (selection.getOrder() != null
                            && selection.getOrder() != selectionsMap.get(code).getOrder()) {
                        _logger.error("Selection:" + selection.getCode() + "for Resource:" + resource.getCode()
                                + "(" + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                + resourceFamilies.indexOf(resourceFamily) + " has mismatch in order.");
                        throw new ValidationException("failed",
                                "Selection:" + selection.getCode() + "for Resource:" + resource.getCode() + "("
                                        + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily) + " has mismatch in order.");
                    }
                    if (!selectionsMap.containsKey(code)) {
                        _logger.error("Selection code:" + selection.getCode() + "for Resource:" + resource.getCode()
                                + "(" + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                + resourceFamilies.indexOf(resourceFamily) + " does not exist in master resource.");
                        throw new ValidationException("failed",
                                "Selection code:" + selection.getCode() + "for Resource:" + resource.getCode() + "("
                                        + resource.getResourceType() + ")" + " inside ResourceFamily:"
                                        + resourceFamilies.indexOf(resourceFamily)
                                        + " does not exist in master resource.");
                    }

                }
                // Rami-4. The default selection must appear as one of the resource
                // selections
                if (masterResource.getDefaultSelection() != null
                        && !selectionsMap.containsKey(masterResource.getDefaultSelection())) {
                    _logger.error("Default selection:" + masterResource.getDefaultSelection()
                            + " not found in resource:" + masterResource.getCode() + " in MasterResourceFamily");
                    throw new ValidationException("failed",
                            "Default selection:" + masterResource.getDefaultSelection() + " not found in resource:"
                                    + masterResource.getCode() + " in MasterResourceFamily");
                }
                if (resource.getDefaultSelection() != null
                        && !resourceFamilySelectionsMap.containsKey(resource.getDefaultSelection())) {
                    _logger.error("Default selection:" + resource.getDefaultSelection() + " not found in resource:"
                            + resource.getCode() + " in ResourceFamily:"
                            + resourceFamilies.indexOf(resourceFamily));
                    throw new ValidationException("failed",
                            "Default selection:" + resource.getDefaultSelection() + " not found in resource:"
                                    + resource.getCode() + " in ResourceFamily:"
                                    + resourceFamilies.indexOf(resourceFamily));
                }
                if (resource.getDefaultSelection() == null && masterResource.getDefaultSelection() != null
                        && !resourceFamilySelectionsMap.containsKey(masterResource.getDefaultSelection())) {
                    _logger.error("Default selection:" + masterResource.getDefaultSelection()
                            + " from MasterResourceFamily not found in resource:" + resource.getCode()
                            + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily));
                    throw new ValidationException("failed",
                            "Default selection:" + masterResource.getDefaultSelection()
                                    + " from MasterResourceFamily not found in resource:" + resource.getCode()
                                    + " in ResourceFamily:" + resourceFamilies.indexOf(resourceFamily));
                }
                /*
                 * Nothing to validate. 2. If a resource defined in the Master Resource
                 * Family is completely omitted from a Resource Family, then the ART UI
                 * will inherit all text and selection information about the resource
                 * from the Master Resource Family. position defined by the Order
                 * attribute
                 */
                /*
                 * Already handled. 3(a). If a resource defined in the Master Resource
                 * Family is also present in a Resource Family, then: a. The code and
                 * English and translated text of the resource cannot be overridden
                 */
                /*
                 * Nothing to validate in xml 3(b). The default code and translations
                 * for the resource may be overridden.
                 */
                /*
                 * Nothing to validate in xml 3(c). The UI will only display resource
                 * selections that are repeated in the Resource Family for the resource
                 * and will not display any selections that are omitted for the resource
                 * in the Resource Family. This permits configuration of display of only
                 * certain selections and suppression of other selections for the
                 * subject/grade combination of a Resource Family.
                 */
                /*
                 * Already handled 3(d). No new codes can be created for a selection in
                 * a Resource Family that are not already provided in the Master
                 * Resource Family.
                 */
                /*
                 * No validation required in xml 3(e). All text fields for resource
                 * selections defined in the Master Resource Family can be overridden in
                 * a Resource Family.
                 */

                /*
                 * Resource Families modify the behavior of the Master Resource Family
                 * for specific subjects and for specific student grades. The following
                 * rules apply to resource families:
                 */

                /*
                 * Nothing to validate in xml 1. Resource families are not strictly
                 * required. If the intent is that all subjects and grades get exactly
                 * the same resources and selections, then the configuration from the
                 * Master REsource Family will be used for all grades and subjects.
                 */

                /*
                 * Nothing to validate in xml 3. Resource Families can be defined for
                 * some subjects and grades, but do not have to be provided for every
                 * possible subject and grade. The Master Resource Family will be used
                 * for any subject/grade combination for which there is no Resource
                 * Family defined. nothing to check
                 */

                /*
                 * Already checked 5. No new codes can be defined in Resource Families
                 * that are not already defined in the Master Resource Family. Another
                 * way of looking at this is that new resources cannot be defined in
                 * Resource Families, only in the Master Resource Family.
                 */

                /*
                 * Already handled 7. The following things for a resource selection
                 * cannot be overridden: Code, Order. Text/Label, Text/Description and
                 * Text/Message can all be overridden for resource selections.
                 */

            }
        }

        return true;
    }

    /**
     * @param code
     * @return
     */
    private boolean validateCode(String code) {
        String invalidChars = "<>& \"'";
        try {
            int firstChar = Integer.parseInt("" + code.charAt(0));
            return false;
        } catch (Exception e) {
            for (int i = 0; i < invalidChars.length(); i++) {
                if (code.contains("" + invalidChars.charAt(i)))
                    return false;
            }
            return true;
        }
    }

    private void validateAgainstXSD(InputStream xml, InputStream xsd) throws ValidationException {
        try {
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            Schema schema = factory.newSchema(new StreamSource(xsd));
            Validator validator = schema.newValidator();
            validator.validate(new StreamSource(xml));

        } catch (Exception ex) {
            throw new ValidationException("failed", "Failed against schema. Error message:" + ex.getMessage());
        }
    }

    private String getContents(String nodeValue) {
        StringBuffer sb = new StringBuffer();
        if (nodeValue != null) {
            char[] ch = nodeValue.toCharArray();
            for (char c : ch) {

                if (c == '\t' || c == '\n') {

                } else {
                    sb.append(c);
                }
            }
        }
        return sb.toString();

    }

    private Boolean checkWhiteSpaces(String code) {
        boolean containsWhitespace = false;
        for (int i = 0; i < code.length() && !containsWhitespace; i++) {
            if (Character.isWhitespace(code.charAt(i))) {
                containsWhitespace = true;
            }
        }
        return containsWhitespace;
    }

    private Boolean validateAccommodationCodes(String code) {
        Boolean isValid = true;
        if (checkWhiteSpaces(code)) {
            isValid = false;
        } else {

            List<String> specialAllowedCharacters = new ArrayList<String>();
            specialAllowedCharacters.add("&amp;");
            specialAllowedCharacters.add("&apos;");
            specialAllowedCharacters.add("&gt;");
            specialAllowedCharacters.add("&lt;");
            specialAllowedCharacters.add("&quot;");
            if (code.contains(",")) {
                isValid = false;
            } else if (code.contains(";")) {
                for (String test : specialAllowedCharacters) {
                    if (StringUtils.countMatches(code, ";") > StringUtils.countMatches(code, test)) {
                        isValid = false;
                        break;
                    }
                }
            }
        }
        return isValid;
    }

    /**
     * @param resourceFamilies
     */
    public void storeResourceFamiliesIntoDB(List<ResourceFamily> resourceFamilies) throws StoringException {

        DB database = getMongoDBConnection();
        DBCollection collection = database.getCollection("resourceFamily");

        collection.drop();

        String name = null;
        String language = null;
        String label = null;
        String message = null;
        String description = null;
        String code = null;
        Integer order = null;
        String defaultSelection = null;
        String resourceType = null;
        Boolean mutuallyExclusive;
        Boolean disabled;

        for (ResourceFamily rf : resourceFamilies) {
            BasicDBObject resourceFamily = new BasicDBObject();
            BasicDBList subjects = new BasicDBList();

            List<AccFamilySubject> accFamilySubjects = rf.getSubject();

            for (int i = 0; i < accFamilySubjects.size(); i++) {
                BasicDBObject subject = new BasicDBObject();
                AccFamilySubject sub = accFamilySubjects.get(i);
                code = sub.getCode();
                if (code != null)
                    subject.append("code", code);

                name = sub.getName();
                if (name != null)
                    subject.append("name", name);

                subjects.add(subject);
            }

            BasicDBList grade = new BasicDBList();
            List<String> dbGrades = rf.getGrade();
            for (int j = 0; j < dbGrades.size(); j++) {
                grade.add(dbGrades.get(j).toString());

            }
            List<MasterResourceAccommodation> accommodations = rf.getMasterResourceAccommodation();
            BasicDBList masterResourceAccommodation = new BasicDBList();
            for (int k = 0; k < accommodations.size(); k++) {
                MasterResourceAccommodation mracc = accommodations.get(k);
                BasicDBObject accommodation = new BasicDBObject();
                BasicDBObject header = new BasicDBObject();
                BasicDBList headersList = new BasicDBList();
                BasicDBList options = new BasicDBList();
                List<AccommodationText> headerTexts = mracc.getHeader();
                if (headerTexts != null) {
                    for (AccommodationText headerText : headerTexts) {
                        if (headerText != null) {
                            language = headerText.getLanguage();
                            if (language != null)
                                header.append("language", language);

                            label = headerText.getLabel();
                            if (label != null)
                                header.append("label", label);

                            message = headerText.getMessage();
                            if (message != null)
                                header.append("message", message);

                            description = headerText.getDescription();
                            if (description != null)
                                header.append("description", description);

                            headersList.add(header);
                        }
                    }
                }
                code = mracc.getCode();
                if (code != null)
                    accommodation.append("code", code);

                order = mracc.getOrder();
                if (order != 0)
                    accommodation.append("order", order);

                defaultSelection = mracc.getDefaultSelection();
                if (defaultSelection != null)
                    accommodation.append("defaultSelection", defaultSelection);

                if (header.size() > 0)
                    accommodation.append("header", headersList);

                resourceType = mracc.getResourceType();
                if (mracc.getResourceType() != null)
                    accommodation.append("resourceType", resourceType);

                disabled = mracc.isDisabled();
                if (mracc.isDisabled() != false) {
                    accommodation.append("disabled", disabled);
                }

                List<AccommodationOption> accOptions = mracc.getOptions();
                for (int i = 0; i < accOptions.size(); i++) {
                    AccommodationOption accOption = accOptions.get(i);

                    if (accOption != null) {
                        BasicDBObject option = new BasicDBObject();
                        code = accOption.getCode();
                        if (code != null)
                            option.append("code", code);

                        order = accOption.getOrder();
                        if (order != null && Integer.valueOf(order) != 0)
                            option.append("order", order);

                        mutuallyExclusive = accOption.isMutuallyExclusive();
                        if (mutuallyExclusive != false)
                            option.append("mutuallyExclusive", mutuallyExclusive);
                        BasicDBList textList = new BasicDBList();
                        List<AccommodationText> accTexts = accOption.getText();
                        if (accTexts != null) {
                            for (AccommodationText accText : accTexts) {
                                if (accText != null) {
                                    BasicDBObject text = new BasicDBObject();

                                    language = accText.getLanguage();
                                    if (language != null)
                                        text.append("language", language);

                                    label = accText.getLabel();
                                    if (label != null)
                                        text.append("label", label);

                                    description = accText.getDescription();
                                    if (description != null)
                                        text.append("description", description);

                                    message = accText.getMessage();
                                    if (message != null)
                                        text.append("message", message);
                                    textList.add(text);

                                }
                                if (textList.size() > 0)
                                    option.append("text", textList);
                            }
                        }
                        if (option.size() > 0)
                            options.add(option);
                    }
                }

                if (options.size() > 0)
                    accommodation.append("options", options);

                if (accommodation.size() > 0)
                    masterResourceAccommodation.add(accommodation);
            }

            resourceFamily.append("subject", subjects);
            resourceFamily.append("grade", grade);
            resourceFamily.append("masterResourceAccommodation", masterResourceAccommodation);

            collection.insert(resourceFamily);
        }

    }

    /**
     * @param masterResourceAccommodations
     */
    public void storeMasterResourceAccommodationIntoDB(
            List<MasterResourceAccommodation> masterResourceAccommodations) throws StoringException {

        String language = null;
        String label = null;
        String message = null;
        String description = null;
        String code = null;
        Integer order = null;
        String defaultSelection = null;
        String resourceType = null;
        Boolean mutuallyExclusive;

        try {

            DB database = getMongoDBConnection();
            DBCollection collection = database.getCollection("masterResourceAccommodation");

            collection.drop();
            for (MasterResourceAccommodation mracc : masterResourceAccommodations) {
                BasicDBObject accommodation = new BasicDBObject();
                BasicDBList headers = new BasicDBList();
                BasicDBObject header = new BasicDBObject();
                BasicDBList options = new BasicDBList();
                List<AccommodationText> headerTexts = mracc.getHeader();
                if (headerTexts != null) {
                    for (AccommodationText headerText : headerTexts) {
                        language = headerText.getLanguage();
                        if (language != null)
                            header.append("language", language);

                        label = headerText.getLabel();
                        if (label != null)
                            header.append("label", label);

                        message = headerText.getMessage();
                        if (message != null)
                            header.append("message", message);

                        description = headerText.getDescription();
                        if (description != null)
                            header.append("description", description);
                        headers.add(header);
                    }
                }
                code = mracc.getCode();
                if (code != null)
                    accommodation.append("code", code);

                order = mracc.getOrder();
                if (order != null && Integer.valueOf(order) != 0)
                    accommodation.append("order", order);

                defaultSelection = mracc.getDefaultSelection();
                if (defaultSelection != null)
                    accommodation.append("defaultSelection", defaultSelection);

                accommodation.append("header", headers);

                resourceType = mracc.getResourceType();
                if (mracc.getResourceType() != null)
                    accommodation.append("resourceType", resourceType);

                List<AccommodationOption> accOptions = mracc.getOptions();

                for (int i = 0; i < accOptions.size(); i++) {
                    AccommodationOption accOption = accOptions.get(i);
                    BasicDBObject option = new BasicDBObject();
                    code = accOption.getCode();
                    if (code != null)
                        option.append("code", code);

                    order = accOption.getOrder();
                    if (order != null)
                        option.append("order", order);

                    mutuallyExclusive = accOption.isMutuallyExclusive();
                    if (mutuallyExclusive != false)
                        option.append("mutuallyExclusive", mutuallyExclusive);

                    List<AccommodationText> accTexts = accOption.getText();
                    if (accTexts != null) {
                        BasicDBList textList = new BasicDBList();

                        for (AccommodationText accText : accTexts) {
                            BasicDBObject text = new BasicDBObject();

                            language = accText.getLanguage();
                            if (language != null)
                                text.append("language", language);

                            label = accText.getLabel();
                            if (label != null)
                                text.append("label", label);

                            description = accText.getDescription();
                            if (description != null)
                                text.append("description", description);

                            message = accText.getMessage();
                            if (message != null)
                                text.append("message", message);

                            textList.add(text);

                        }
                        if (textList.size() > 0)
                            option.append("text", textList);
                    }

                    if (option.size() > 0)
                        options.add(option);
                }

                if (options.size() > 0)
                    accommodation.append("options", options);

                if (accommodation != null)
                    collection.insert(accommodation);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * @return
     */
    private DB getMongoDBConnection() throws StoringException {
        MongoClient mongoClient = null;
        DB database = null;
        try {

            MongoClientURI uri = null;

            if (!_userName.equalsIgnoreCase(EMPTY) && !_password.equalsIgnoreCase(EMPTY)) {
                uri = new MongoClientURI("mongodb://" + _userName + ":" + _password + "@" + _hostName + ":" + _port
                        + "/?authSource=" + _databaseName);
            } else {
                uri = new MongoClientURI("mongodb://" + _hostName + ":" + _port);
            }
            mongoClient = new MongoClient(uri);
            database = mongoClient.getDB(_databaseName);
        } catch (UnknownHostException e) {
            throw new StoringException(e.getMessage());
        } catch (CommandFailureException e) {

            if (e.getCode() == 18) {
                throw new StoringException("Authentication Exception:Invalid Credentials");
            } else {
                throw new StoringException(e.getMessage());
            }
        } catch (Exception e) {
            throw new StoringException(e.getMessage());
        }

        return database;
    }

}