Mercurial > hg > openmind
changeset 31:7d8ebe8ac8a2
create reader and check script for XML dumps.
author | casties |
---|---|
date | Wed, 24 Aug 2016 19:12:24 +0200 |
parents | 2f19cdf8e60b |
children | 9c54842f5e86 |
files | src/main/java/org/mpi/openmind/repository/utils/OM4StreamWriter.java src/main/java/org/mpi/openmind/repository/utils/OM4XmlEventReader.java src/main/java/org/mpi/openmind/scripts/CheckXmlExport.java |
diffstat | 3 files changed, 814 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/org/mpi/openmind/repository/utils/OM4StreamWriter.java Tue Aug 23 17:43:09 2016 +0200 +++ b/src/main/java/org/mpi/openmind/repository/utils/OM4StreamWriter.java Wed Aug 24 19:12:24 2016 +0200 @@ -19,6 +19,15 @@ import org.mpi.openmind.repository.bo.Relation; import org.mpi.openmind.repository.services.PersistenceService; +/** + * Export all entities and relations and definitions to XML. + * + * Saves (real) entities and relations (i.e. assertions) and definitions + * (i.e. definition entities and relations) in separate files. + * + * @author jurzua, casties + * + */ public class OM4StreamWriter { private static Logger logger = Logger.getLogger(OM4StreamWriter.class); @@ -31,7 +40,7 @@ * @param s * @return */ - public static String defaultString(Object s) { + private static String defaultString(Object s) { if (s == null) { return "null"; } else { @@ -69,11 +78,11 @@ if (type.equals(Node.TYPE_ABOX)) { writer.writeStartElement(XMLUtil.OPENMIND_DATA); - writer.writeAttribute("version", "3.0"); + writer.writeAttribute("version", "4.3"); entitiesCount = ps.getEntityCount(null).intValue(); } else { writer.writeStartElement(XMLUtil.META_DATA); - writer.writeAttribute("version", "3.0"); + writer.writeAttribute("version", "4.3"); entitiesCount = ps.getEntityCount(Node.TYPE_TBOX).intValue(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/mpi/openmind/repository/utils/OM4XmlEventReader.java Wed Aug 24 19:12:24 2016 +0200 @@ -0,0 +1,368 @@ +/** + * + */ +package org.mpi.openmind.repository.utils; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.Characters; +import javax.xml.stream.events.EndElement; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; + +import org.apache.log4j.Logger; + +/** + * Class that reads an OM4 XML dump into lists of simple objects. + * + * The constructor takes an InputStream. + * + * The read() method reads the contents of the file into the members + * .entities and .relations. + * + * The contents are Lists of OmEntities and OmRelations also holding + * Lists of omAttributes. + * + * @author casties + * + */ +public class OM4XmlEventReader { + + private static Logger logger = Logger.getLogger(OM4XmlEventReader.class); + + public OM4XmlEventReader(InputStream xmlStream) { + super(); + this.xmlStream = xmlStream; + } + + InputStream xmlStream; + + public int numEntities; + public List<OmEntity> entities; + private int entCnt = 0; + + public int numRelations; + public List<OmRelation> relations; + private int relCnt = 0; + + /** + * Simple class holding the representation of an OpenMind Attribute from XML. + * + * @author casties + */ + public class OmAttribute { + public Map<String, String> xmlAtts; + public String value; + + public String getId() { + return xmlAtts.get("id"); + } + } + + /** + * Simple class holding the representation of an OpenMind Entity from XML. + * + * @author casties + */ + public class OmEntity { + public Map<String, String> xmlAtts; + public String value; + public List<OmAttribute> attributes; + + public String getId() { + return xmlAtts.get("id"); + } + } + + /** + * Simple class holding the representation of an OpenMind Relation from XML. + * + * @author casties + */ + public class OmRelation { + public Map<String, String> xmlAtts; + public String value; + public List<OmAttribute> attributes; + + public String getId() { + return xmlAtts.get("id"); + } + } + + /** + * Reads the XML from xmlStream and populates entities and relations. + * + * @throws XMLStreamException + */ + public void read() throws XMLStreamException { + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + XMLEventReader reader = inputFactory.createXMLEventReader(xmlStream, "UTF-8"); + try { + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isStartDocument()) { + continue; + } else if (e.isStartElement()) { + StartElement es = e.asStartElement(); + String lname = es.getName().getLocalPart(); + if (lname == XMLUtil.ENTITIES) { + entities = processEntities(es, reader); + } else if (lname == XMLUtil.RELATIONS) { + relations = processRelations(es, reader); + } + } + } + } finally { + reader.close(); + } + } + + /** + * Process the entities tag and its contents. + * + * @param elem + * @param reader + * @return + * @throws XMLStreamException + */ + private List<OmEntity> processEntities(StartElement elem, XMLEventReader reader) throws XMLStreamException { + logger.debug("loading entities..."); + // get number attribute + Attribute numa = elem.getAttributeByName(new QName("number")); + if (numa != null) { + numEntities = Integer.parseInt(numa.getValue()); + } + // start reading sub-elements + List<OmEntity> entities = new ArrayList<OmEntity>(); + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isStartElement()) { + // start of next element + StartElement es = e.asStartElement(); + String lname = es.getName().getLocalPart(); + if (lname == XMLUtil.ENTITY) { + // process entity tag + entities.add(processEntity(es, reader)); + } + } else if (e.isEndElement()) { + EndElement ee = e.asEndElement(); + if (ee.getName().getLocalPart().equals(XMLUtil.ENTITIES)) { + // end of this element + break; + } else { + logger.warn("Unexpected EndElement: "+ee); + } + } + } + return entities; + } + + /** + * Process the entity tag and its contents. + * + * @param elem + * @param reader + * @return + * @throws XMLStreamException + */ + private OmEntity processEntity(StartElement elem, XMLEventReader reader) throws XMLStreamException { + //logger.debug("entity"); + OmEntity ent = new OmEntity(); + Map<String, String> xmlAtts = new HashMap<String, String>(); + @SuppressWarnings("unchecked") + Iterator<Attribute> atts = elem.getAttributes(); + while (atts.hasNext()) { + Attribute att = atts.next(); + xmlAtts.put(att.getName().getLocalPart(), att.getValue()); + } + ent.xmlAtts = xmlAtts; + // start reading sub-elements + ent.attributes = new ArrayList<OmAttribute>(); + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isStartElement()) { + // start of next element + StartElement es = e.asStartElement(); + String lname = es.getName().getLocalPart(); + if (lname == XMLUtil.ATTRIBUTES) { + // ignore attributes tag + continue; + } + if (lname == XMLUtil.ATTRIBUTE) { + // process attribute tag + ent.attributes.add(processAttribute(es, reader)); + } + } else if (e.isCharacters()) { + // text content + Characters ec = e.asCharacters(); + if (ent.value == null) { + ent.value = ec.getData(); + } else { + ent.value += ec.getData(); + } + } else if (e.isEndElement()) { + EndElement ee = e.asEndElement(); + if (ee.getName().getLocalPart().equals(XMLUtil.ENTITY)) { + // end of this element + break; + } + } + } + if (++entCnt % 500 == 0) { + logger.debug(""+entCnt+" entities read..."); + } + return ent; + } + + /** + * Process the relations tag and its contents. + * + * @param elem + * @param reader + * @return + * @throws XMLStreamException + */ + private List<OmRelation> processRelations(StartElement elem, XMLEventReader reader) throws XMLStreamException { + logger.debug("loading relations..."); + // get number attribute + Attribute numa = elem.getAttributeByName(new QName("number")); + if (numa != null) { + numRelations = Integer.parseInt(numa.getValue()); + } + // start reading sub-elements + List<OmRelation> rels = new ArrayList<OmRelation>(); + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isStartElement()) { + // start of next element + StartElement es = e.asStartElement(); + String lname = es.getName().getLocalPart(); + if (lname == XMLUtil.RELATION) { + // process entity tag + rels.add(processRelation(es, reader)); + } + } else if (e.isEndElement()) { + EndElement ee = e.asEndElement(); + if (ee.getName().getLocalPart().equals(XMLUtil.RELATIONS)) { + // end of this element + break; + } else { + logger.warn("Unexpected EndElement: "+ee); + } + } + } + return rels; + } + + + /** + * Process the relation tag and its contents. + * + * @param elem + * @param reader + * @return + * @throws XMLStreamException + */ + private OmRelation processRelation(StartElement elem, XMLEventReader reader) throws XMLStreamException { + //logger.debug("relation"); + OmRelation rel = new OmRelation(); + Map<String, String> xmlAtts = new HashMap<String, String>(); + @SuppressWarnings("unchecked") + Iterator<Attribute> atts = elem.getAttributes(); + while (atts.hasNext()) { + Attribute att = atts.next(); + xmlAtts.put(att.getName().getLocalPart(), att.getValue()); + } + rel.xmlAtts = xmlAtts; + // start reading sub-elements + rel.attributes = new ArrayList<OmAttribute>(); + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isStartElement()) { + // start of next element + StartElement es = e.asStartElement(); + String lname = es.getName().getLocalPart(); + if (lname == XMLUtil.ATTRIBUTES) { + // ignore attributes tag + continue; + } + if (lname == XMLUtil.ATTRIBUTE) { + // process attribute tag + rel.attributes.add(processAttribute(es, reader)); + } + } else if (e.isCharacters()) { + // text content + Characters ec = e.asCharacters(); + if (rel.value == null) { + rel.value = ec.getData(); + } else { + rel.value += ec.getData(); + } + } else if (e.isEndElement()) { + EndElement ee = e.asEndElement(); + if (ee.getName().getLocalPart().equals(XMLUtil.RELATION)) { + // end of this element + break; + } + } + } + if (++relCnt % 100 == 0) { + logger.debug(""+relCnt+" relations read..."); + } + return rel; + } + + /** + * Process the attribute tag and its contents. + * + * @param elem + * @param reader + * @return + * @throws XMLStreamException + */ + private OmAttribute processAttribute(StartElement elem, XMLEventReader reader) throws XMLStreamException { + //logger.debug("attribute"); + OmAttribute oma = new OmAttribute(); + Map<String, String> xmlAtts = new HashMap<String, String>(); + @SuppressWarnings("unchecked") + Iterator<Attribute> atts = elem.getAttributes(); + while (atts.hasNext()) { + Attribute att = atts.next(); + xmlAtts.put(att.getName().getLocalPart(), att.getValue()); + } + oma.xmlAtts = xmlAtts; + // start reading sub-elements + while (reader.hasNext()) { + XMLEvent e = reader.nextEvent(); + if (e.isCharacters()) { + // text content + Characters ec = e.asCharacters(); + if (oma.value == null) { + oma.value = ec.getData(); + } else { + oma.value += ec.getData(); + } + } else if (e.isEndElement()) { + EndElement ee = e.asEndElement(); + if (ee.getName().getLocalPart().equals(XMLUtil.ATTRIBUTE)) { + // end of this element + break; + } else { + logger.warn("Unexpected EndElement: "+ee); + } + } + } + return oma; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/org/mpi/openmind/scripts/CheckXmlExport.java Wed Aug 24 19:12:24 2016 +0200 @@ -0,0 +1,434 @@ +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.OmAttribute; +import org.mpi.openmind.repository.utils.OM4XmlEventReader.OmEntity; +import org.mpi.openmind.repository.utils.OM4XmlEventReader.OmRelation; + + +/** + * 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<OmEntity> xmlEntList = xmlReader.entities; + List<OmRelation> xmlRelList = xmlReader.relations; + Map<Long, OmEntity> xmlEntMap = new HashMap<Long, OmEntity>(xmlEntList.size()); + for (OmEntity 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,OmRelation> xmlRelMap = new HashMap<Long, OmRelation>(xmlRelList.size()); + for (OmRelation 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(); + OmEntity 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(); + OmRelation 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, OmEntity 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, OmRelation 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<OmAttribute> xmlAtts) { + for (Attribute att : atts) { + // get the matching attribute from the XML file + OmAttribute xmlAtt = null; + for (OmAttribute 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); + } +}