view src/main/java/org/mpi/openmind/scripts/CheckXmlExport.java @ 32:9c54842f5e86

better names for XML importer sub-classes.
author casties
date Thu, 25 Aug 2016 11:29:47 +0200
parents 7d8ebe8ac8a2
children
line wrap: on
line source

package org.mpi.openmind.scripts;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.mpi.openmind.cache.WrapperService;
import org.mpi.openmind.configuration.ConfigurationService;
import org.mpi.openmind.repository.bo.Attribute;
import org.mpi.openmind.repository.bo.Entity;
import org.mpi.openmind.repository.bo.Relation;
import org.mpi.openmind.repository.services.PersistenceService;
import org.mpi.openmind.repository.services.ServiceRegistry;
import org.mpi.openmind.repository.utils.OM4XmlEventReader;
import org.mpi.openmind.repository.utils.OM4XmlEventReader.OmXmlAttribute;
import org.mpi.openmind.repository.utils.OM4XmlEventReader.OmXmlEntity;
import org.mpi.openmind.repository.utils.OM4XmlEventReader.OmXmlRelation;


/**
 * Class that reads an OM4 XML dump and compares the content to the content of the database.
 * 
 * Does not deal with definitions.
 * 
 * @author casties
 */
public class CheckXmlExport {
    
	private static Logger logger = Logger.getLogger(OM4XmlEventReader.class);
    private static ConfigurationService configurationService;
    private static PersistenceService persistenceService;

	public static void execute(String fileName){
	    logger.setLevel(Level.DEBUG);
	    
	    // set up OpenMind
		ServiceRegistry services = new ServiceRegistry();
        configurationService = services.getConfigurationService();
        persistenceService = services.getPS();
        
        // read XML file
        OM4XmlEventReader xmlReader = importXml(fileName);
        
        // check content of XML file
		checkEntsAndRels(xmlReader, services.getWrapper());
	}
	
    /**
     * Reads the XML file and returns the OM4XmlEventReader with the content.
     *  
     * @param fileName
     * @return
     */
    private static OM4XmlEventReader importXml(String fileName){
	    // get path from configuration service
        String schedulingPath = configurationService.getSchedulingPath();
	    //String schedulingPath = "/tmp";
        if (schedulingPath.charAt(schedulingPath.length() - 1) != '/'){
            schedulingPath += "/";
        }
        // import XML
        logger.info("Import entities from XML file: " + fileName);
        File xmlFile = new File(schedulingPath + fileName);
        try {
            OM4XmlEventReader reader = new OM4XmlEventReader(new FileInputStream(xmlFile));
            reader.read();
            logger.info("supposed number of entities: "+reader.numEntities);
            logger.info("number of entities read: "+reader.entities.size());
            logger.info("supposed number of relations: "+reader.numRelations);
            logger.info("number of relations read: "+reader.relations.size());
            return reader;
        } catch (XMLStreamException e) {
            logger.error("Error reading XML", e);
        } catch (FileNotFoundException e) {
            logger.error("File not found: "+xmlFile);
        }
        return null;
	}
	
    /**
     * Compares the entities and relations in the content of the OM4XmlEventReader with
     * the content of the database.
     * 
     * @param xmlReader
     * @param wrapper
     */
    private static void checkEntsAndRels(OM4XmlEventReader xmlReader, WrapperService wrapper) {
        /*
         * create hashes by id as indices
         */
        logger.info("indexing entities...");
        List<OmXmlEntity> xmlEntList = xmlReader.entities;
        List<OmXmlRelation> xmlRelList = xmlReader.relations;
        Map<Long, OmXmlEntity> xmlEntMap = new HashMap<Long, OmXmlEntity>(xmlEntList.size());
        for (OmXmlEntity e : xmlEntList) {
            Long id = Long.parseLong(e.getId());
            if (xmlEntMap.put(id, e) != null) {
                logger.error("XML entity with duplicate id: "+id);
            }
        }
        logger.info("indexing relations...");
        Map<Long,OmXmlRelation> xmlRelMap = new HashMap<Long, OmXmlRelation>(xmlRelList.size());
        for (OmXmlRelation e : xmlRelList) {
            Long id = Long.parseLong(e.getId());
            if (xmlRelMap.put(id, e) != null) {
                logger.error("XML relation with duplicate id: "+id);                
            };
        }

        List<Relation> relations = new ArrayList<Relation>(xmlRelList.size());

        /*
         * load all entities from OM and compare with XML
         */
        int itemsPerPage = 500;
        int entitiesCount = persistenceService.getEntityCount(null).intValue();
        int numberOfPages = entitiesCount / itemsPerPage;
        int entcnt = 0;
        int entErrCnt = 0;
        int relcnt = 0;
        int relErrCnt = 0;
        for (int currentPage = 0; currentPage <= numberOfPages; currentPage++) {
            int startRecord = currentPage * itemsPerPage;
            // get page of entities from OM
            List<Entity> entities = persistenceService.getEntityPage(null, startRecord, itemsPerPage);

            for (Entity ent : entities) {
                if (ent.isLightweight()) {
                    ent = persistenceService.getEntityContent(ent);
                }

                // save (source)relations to list
                relations.addAll(ent.getSourceRelations());
                
                // get xml entity
                Long id = ent.getId();
                OmXmlEntity xmlEnt = xmlEntMap.get(id);
                if (xmlEnt == null) {
                    logger.error("OM entity not found in XML: "+id);
                    entErrCnt += 1;
                } else if (!entEquals(ent, xmlEnt)) {
                    logger.error("OM entity different from XML: "+id);
                    entErrCnt += 1;
                    //return;
                }
                
                if ((++entcnt % 500) == 0) {
                    logger.debug(""+entcnt+" entities processed...");
                }
            }
        }
        
        /*
         * go through all relations from OM
         */
        for (Relation rel : relations) {
            // get xml entity
            Long id = rel.getId();
            OmXmlRelation xmlRel = xmlRelMap.get(id);
            if (xmlRel == null) {
                logger.error("OM relation not found in XML: "+id);
                relErrCnt += 1;
            } else if (!relEquals(rel, xmlRel)) {
                logger.error("OM relation different from XML: "+id);                    
                relErrCnt += 1;
            }
            
            if ((++relcnt % 500) == 0) {
                logger.debug(""+relcnt+" relations processed...");
            }
           
        }
        
        logger.info("Errors comparing entities: "+entErrCnt);
        logger.info("Errors comparing relations: "+relErrCnt);
        logger.info("Done.");
    }


	
	/**
	 * Compares a OM-Entity with an entity from an OM4XmlEventReader.
	 * 
	 * @param entity
	 * @param xmlEnt
	 * @return
	 */
	private static boolean entEquals(Entity entity, OmXmlEntity xmlEnt) {
        /*
         * check XML attributes
         */
        if (!equalsString(entity.getObjectClass(), xmlEnt.xmlAtts.get("object-class"))) {
            logger.error("Entities object-class not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };
        if (!equalsString(entity.getRowId(), xmlEnt.xmlAtts.get("row-id"))) {
            logger.error("Entities row-id not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };
        if (!equalsString(entity.getVersion(), xmlEnt.xmlAtts.get("version"))) {
            logger.error("Entities version not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };
        if (!equalsString(entity.getModificationTime(), xmlEnt.xmlAtts.get("mtime"))) {
            logger.error("Entities mtime not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };
        if (!equalsString(entity.getUser(), xmlEnt.xmlAtts.get("user"))) {
            logger.error("Entities user not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };
        if (!equalsString(entity.getIsPublic(), (xmlEnt.xmlAtts.get("public") == null) ? "false" : xmlEnt.xmlAtts.get("public"))) {
            logger.error("Entities public not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };

        /*
         * check OpenMind attributes of this entity
         */
        if (entity.getAttributes().size() > 0 && entity.getAttributes().size() == xmlEnt.attributes.size()) {
            if (!attsEquals(entity.getAttributes(), xmlEnt.attributes)) {
                logger.error("Entities attribute values not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
                return false; 
            }
        } else if (entity.getAttributes().size() != xmlEnt.attributes.size()) {
            logger.error("Entities attribute numbers not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        }

        /*
         * check own value
         */
        if (!equalsString(entity.getOwnValue(), xmlEnt.value)) {
            logger.error("Entities own-value not equal: om["+entity.getId()+"] xml["+xmlEnt.getId()+"]");
            return false;
        };

        return true;
    }

	
    /**
     * Compares a OM-Relation with a relation from an OM4XmlEventReader.
     * 
     * @param relation
     * @param xmlRel
     * @return
     */
    private static boolean relEquals(Relation relation, OmXmlRelation xmlRel) {
        /*
         * check XML attributes
         */
        if (!equalsString(relation.getObjectClass(), xmlRel.xmlAtts.get("object-class"))) {
            logger.error("Relations object-class not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getRowId(), xmlRel.xmlAtts.get("row-id"))) {
            logger.error("Relations row-id not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getSourceId(), xmlRel.xmlAtts.get("source-id"))) {
            logger.error("Relations source-id not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getTargetId(), xmlRel.xmlAtts.get("target-id"))) {
            logger.error("Relations target-id not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getVersion(), xmlRel.xmlAtts.get("version"))) {
            logger.error("Relations version not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getModificationTime(), xmlRel.xmlAtts.get("mtime"))) {
            logger.error("Relations mtime not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getUser(), xmlRel.xmlAtts.get("user"))) {
            logger.error("Relations user not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };
        if (!equalsString(relation.getIsPublic(), (xmlRel.xmlAtts.get("public") == null) ? "false" : xmlRel.xmlAtts.get("public"))) {
            logger.error("Relations public not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };

        /*
         * check OpenMind attributes of this relation
         */
        if (relation.getAttributes().size() > 0 && relation.getAttributes().size() == xmlRel.attributes.size()) {
            if (!attsEquals(relation.getAttributes(), xmlRel.attributes)) {
                logger.error("Relations attribute values not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
                return false; 
            }
        } else if (relation.getAttributes().size() != xmlRel.attributes.size()) {
            logger.error("Relations attribute numbers not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        }

        /*
         * check own value
         */
        if (!equalsString(relation.getOwnValue(), xmlRel.value)) {
            logger.error("Relations own-value not equal: om["+relation.getId()+"] xml["+xmlRel.getId()+"]");
            return false;
        };

        return true;
    }


    /**
     * Compares a List of OM-Attributes with a List of attributes from an OM4XmlEventReader.
     * 
     * @param atts
     * @param xmlAtts
     * @return
     */
    private static boolean attsEquals(List<Attribute> atts, List<OmXmlAttribute> xmlAtts) {
        for (Attribute att : atts) {
            // get the matching attribute from the XML file
            OmXmlAttribute xmlAtt = null;
            for (OmXmlAttribute xa : xmlAtts) {
                if (equalsString(att.getId(), xa.getId())) {
                    xmlAtt = xa;
                    break;
                }
            }
            if (xmlAtt == null) {
                logger.error("Attributes id does not match: om["+att.getId()+"] xml[null]");
                return false;
            }
            /*
             * check the attributes of the attribute
             */
            if (!equalsString(att.getRowId(), xmlAtt.xmlAtts.get("row-id"))) {
                logger.error("Attributes row-id not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getName(), xmlAtt.xmlAtts.get("name"))) {
                logger.error("Attributes name not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getContentType(), xmlAtt.xmlAtts.get("content-type"))) {
                logger.error("Attributes content-type not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getVersion(), xmlAtt.xmlAtts.get("version"))) {
                logger.error("Attributes version not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getModificationTime(), xmlAtt.xmlAtts.get("mtime"))) {
                logger.error("Attributes mtime not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getUser(), xmlAtt.xmlAtts.get("user"))) {
                logger.error("Attributes user not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            if (!equalsString(att.getIsPublic(), (xmlAtt.xmlAtts.get("public") == null) ? "false" : xmlAtt.xmlAtts.get("public"))) {
                logger.error("Attributes public not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
            /*
             * check own value of the attribute
             */
            if (!equalsStringCR(att.getOwnValue(), xmlAtt.value)) {
                logger.error("Attributes own-value not equal: om["+att.getId()+"] xml["+xmlAtt.getId()+"]");
                return false;
            };
        }
        return true;
    }

	
    /**
     * Compares an Object with a toString() method to a String.
     * 
     * Treats null, "" and "null" as same.
     * 
     * @param o
     * @param s
     * @return
     */
    private static boolean equalsString(Object o, String s) {
	    if (o == null || o instanceof String) {
	        // treat all forms of null equally
	        if ((o == null || ((String) o).isEmpty() || ((String) o).equals("null") 
	                && (s == null || s.isEmpty()) || s.equals("null"))) {
	            return true;
	        } else {
	            return StringUtils.equals((String) o, s);
	        }
	    } else {
	        // o is not String
	        return StringUtils.equals(o.toString(), s);
	    }
	}
	
    /**
     * Compares two Strings ignoring CR characters.
     * 
     * Treats null and "" as same.
     * 
     * @param o
     * @param s
     * @return
     */
    private static boolean equalsStringCR(String o, String s) {
        if ((o == null || o.isEmpty()) && (s == null || s.isEmpty())) {
            return true;
        }
        return StringUtils.equals(o.replace("\r", ""), s.replace("\r", ""));
    }

    public static void main(String[] args){
        if (args.length > 0) {
            String fn = args[0];
            execute(fn);
        } else {
            System.out.println("Parameter/s not found! Should be: filename");
            System.exit(1);
        }
		System.exit(0);
	}
}