com.phloc.schematron.pure.exchange.PSReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phloc-schematron Show documentation
Show all versions of phloc-schematron Show documentation
Library for validating XML documents with Schematron
/**
* Copyright (C) 2014 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.phloc.schematron.pure.exchange;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.phloc.commons.ValueEnforcer;
import com.phloc.commons.io.IReadableResource;
import com.phloc.commons.microdom.IMicroDocument;
import com.phloc.commons.microdom.IMicroElement;
import com.phloc.commons.microdom.IMicroNode;
import com.phloc.commons.microdom.IMicroText;
import com.phloc.commons.string.StringParser;
import com.phloc.commons.string.ToStringGenerator;
import com.phloc.schematron.CSchematron;
import com.phloc.schematron.CSchematronXML;
import com.phloc.schematron.SchematronHelper;
import com.phloc.schematron.pure.errorhandler.IPSErrorHandler;
import com.phloc.schematron.pure.errorhandler.LoggingPSErrorHandler;
import com.phloc.schematron.pure.model.IPSElement;
import com.phloc.schematron.pure.model.PSActive;
import com.phloc.schematron.pure.model.PSAssertReport;
import com.phloc.schematron.pure.model.PSDiagnostic;
import com.phloc.schematron.pure.model.PSDiagnostics;
import com.phloc.schematron.pure.model.PSDir;
import com.phloc.schematron.pure.model.PSDir.EDirValue;
import com.phloc.schematron.pure.model.PSEmph;
import com.phloc.schematron.pure.model.PSExtends;
import com.phloc.schematron.pure.model.PSInclude;
import com.phloc.schematron.pure.model.PSLet;
import com.phloc.schematron.pure.model.PSLinkableGroup;
import com.phloc.schematron.pure.model.PSNS;
import com.phloc.schematron.pure.model.PSName;
import com.phloc.schematron.pure.model.PSP;
import com.phloc.schematron.pure.model.PSParam;
import com.phloc.schematron.pure.model.PSPattern;
import com.phloc.schematron.pure.model.PSPhase;
import com.phloc.schematron.pure.model.PSRichGroup;
import com.phloc.schematron.pure.model.PSRichGroup.ESpace;
import com.phloc.schematron.pure.model.PSRule;
import com.phloc.schematron.pure.model.PSSchema;
import com.phloc.schematron.pure.model.PSSpan;
import com.phloc.schematron.pure.model.PSTitle;
import com.phloc.schematron.pure.model.PSValueOf;
/**
* Utility class for reading all Schematron elements from a resource.
*
* @author Philip Helger
*/
@Immutable
public class PSReader
{
private final IReadableResource m_aResource;
private final IPSErrorHandler m_aErrorHandler;
/**
* Constructor without an error handler
*
* @param aResource
* The resource to read the Schematron from. May not be
* null
.
*/
public PSReader (@Nonnull final IReadableResource aResource)
{
this (aResource, null);
}
/**
* Constructor with an error handler
*
* @param aResource
* The resource to read the Schematron from. May not be
* null
.
* @param aErrorHandler
* The error handler to use. May be null
. If the error
* handler is null
a {@link LoggingPSErrorHandler} is
* automatically created and used.
*/
public PSReader (@Nonnull final IReadableResource aResource, @Nullable final IPSErrorHandler aErrorHandler)
{
ValueEnforcer.notNull (aResource, "Resource");
m_aResource = aResource;
m_aErrorHandler = aErrorHandler != null ? aErrorHandler : new LoggingPSErrorHandler ();
}
/**
* @return The resource from which the Schematron schema is read. Never
* null
.
*/
@Nonnull
public IReadableResource getResource ()
{
return m_aResource;
}
/**
* @return The error handler used. If no error handler was passed in the
* constructor, than a {@link LoggingPSErrorHandler} is automatically
* used.
*/
@Nonnull
public IPSErrorHandler getErrorHandler ()
{
return m_aErrorHandler;
}
/**
* Utility method to get a real attribute value, by trimming spaces, if the
* value is non-null
.
*
* @param sAttrValue
* The source attribute value. May be null
.
* @return null
if the input parameter is null
.
*/
@Nullable
private static String _getAttributeValue (@Nullable final String sAttrValue)
{
return sAttrValue == null ? null : sAttrValue.trim ();
}
/**
* Emit a warning with the registered error handler.
*
* @param aSourceElement
* The source element where the error occurred.
* @param sMessage
* The main warning message.
*/
private void _warn (@Nonnull final IPSElement aSourceElement, @Nonnull final String sMessage)
{
ValueEnforcer.notNull (aSourceElement, "SourceElement");
ValueEnforcer.notNull (sMessage, "Message");
m_aErrorHandler.warn (m_aResource, aSourceElement, sMessage);
}
/**
* Read an <active> element
*
* @param eActive
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSActive readActiveFromXML (@Nonnull final IMicroElement eActive)
{
final PSActive ret = new PSActive ();
final Map aAttrs = eActive.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_PATTERN))
ret.setPattern (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
if (eActive.hasChildren ())
for (final IMicroNode aActiveChild : eActive.getChildren ())
switch (aActiveChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aActiveChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aActiveChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
final String sLocalName = eElement.getLocalName ();
if (sLocalName.equals (CSchematronXML.ELEMENT_DIR))
ret.addDir (readDirFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_EMPH))
ret.addEmph (readEmphFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_SPAN))
ret.addSpan (readSpanFromXML (eElement));
else
_warn (ret, "Unsupported Schematron element '" + sLocalName + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aActiveChild);
}
return ret;
}
/**
* Read an <assert> or a <report> element
*
* @param eAssertReport
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSAssertReport readAssertReportFromXML (@Nonnull final IMicroElement eAssertReport)
{
final PSAssertReport ret = new PSAssertReport (eAssertReport.getLocalName ().equals (CSchematronXML.ELEMENT_ASSERT));
final Map aAttrs = eAssertReport.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_TEST))
ret.setTest (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_FLAG))
ret.setFlag (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_DIAGNOSTICS))
ret.setDiagnostics (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName) && !PSLinkableGroup.isLinkableAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
ret.setLinkable (readLinkableGroupFromXML (aAttrs));
}
if (eAssertReport.hasChildren ())
for (final IMicroNode aAssertReportChild : eAssertReport.getChildren ())
switch (aAssertReportChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aAssertReportChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aAssertReportChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
final String sLocalName = eElement.getLocalName ();
if (sLocalName.equals (CSchematronXML.ELEMENT_NAME))
ret.addName (readNameFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_VALUE_OF))
ret.addValueOf (readValueOfFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_EMPH))
ret.addEmph (readEmphFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_DIR))
ret.addDir (readDirFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_SPAN))
ret.addSpan (readSpanFromXML (eElement));
else
_warn (ret, "Unsupported Schematron element '" + sLocalName + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aAssertReportChild);
}
return ret;
}
/**
* Read a <diagnostic> element
*
* @param eDiagnostic
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSDiagnostic readDiagnosticFromXML (@Nonnull final IMicroElement eDiagnostic)
{
final PSDiagnostic ret = new PSDiagnostic ();
final Map aAttrs = eDiagnostic.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
}
if (eDiagnostic.hasChildren ())
for (final IMicroNode aDiagnosticChild : eDiagnostic.getChildren ())
switch (aDiagnosticChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aDiagnosticChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aDiagnosticChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
final String sLocalName = eElement.getLocalName ();
if (sLocalName.equals (CSchematronXML.ELEMENT_VALUE_OF))
ret.addValueOf (readValueOfFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_EMPH))
ret.addEmph (readEmphFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_DIR))
ret.addDir (readDirFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_SPAN))
ret.addSpan (readSpanFromXML (eElement));
else
_warn (ret, "Unsupported Schematron element '" + sLocalName + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aDiagnosticChild);
}
return ret;
}
/**
* Read a <diagnostics> element
*
* @param eDiagnostics
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSDiagnostics readDiagnosticsFromXML (@Nonnull final IMicroElement eDiagnostics)
{
final PSDiagnostics ret = new PSDiagnostics ();
final Map aAttrs = eDiagnostics.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
ret.addForeignAttribute (sAttrName, sAttrValue);
}
for (final IMicroElement eDiagnosticsChild : eDiagnostics.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eDiagnosticsChild.getNamespaceURI ()))
{
if (eDiagnosticsChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
ret.addInclude (readIncludeFromXML (eDiagnosticsChild));
else
if (eDiagnosticsChild.getLocalName ().equals (CSchematronXML.ELEMENT_DIAGNOSTIC))
ret.addDiagnostic (readDiagnosticFromXML (eDiagnosticsChild));
else
_warn (ret, "Unsupported Schematron element '" + eDiagnosticsChild.getLocalName () + "'");
}
else
ret.addForeignElement (eDiagnosticsChild.getClone ());
}
return ret;
}
/**
* Read a <dir> element
*
* @param eDir
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSDir readDirFromXML (@Nonnull final IMicroElement eDir)
{
final PSDir ret = new PSDir ();
final Map aAttrs = eDir.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_VALUE))
ret.setValue (EDirValue.getFromIDOrNull (sAttrValue));
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
if (eDir.hasChildren ())
for (final IMicroNode aDirChild : eDir.getChildren ())
switch (aDirChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aDirChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aDirChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eElement.getLocalName () + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aDirChild);
}
return ret;
}
/**
* Read an <emph> element
*
* @param eEmph
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSEmph readEmphFromXML (@Nonnull final IMicroElement eEmph)
{
final PSEmph ret = new PSEmph ();
final Map aAttrs = eEmph.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
_warn (ret, "Unsupported attribute '" + sAttrName + "'='" + sAttrValue + "'");
}
if (eEmph.hasChildren ())
for (final IMicroNode aEmphChild : eEmph.getChildren ())
switch (aEmphChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aEmphChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aEmphChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eElement.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eElement.getNamespaceURI () + "'");
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aEmphChild);
}
return ret;
}
/**
* Read an <extends> element
*
* @param eExtends
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSExtends readExtendsFromXML (@Nonnull final IMicroElement eExtends)
{
final PSExtends ret = new PSExtends ();
final Map aAttrs = eExtends.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_RULE))
ret.setRule (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
for (final IMicroElement eChild : eExtends.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read an <include> element
*
* @param eInclude
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSInclude readIncludeFromXML (@Nonnull final IMicroElement eInclude)
{
final PSInclude ret = new PSInclude ();
final Map aAttrs = eInclude.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_HREF))
ret.setHref (sAttrValue);
else
_warn (ret, "Unsupported attribute '" + sAttrName + "'='" + sAttrValue + "'");
}
for (final IMicroElement eValueOfChild : eInclude.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eValueOfChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eValueOfChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eValueOfChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read a <let> element
*
* @param eLet
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSLet readLetFromXML (@Nonnull final IMicroElement eLet)
{
final PSLet ret = new PSLet ();
final Map aAttrs = eLet.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_NAME))
ret.setName (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_VALUE))
ret.setValue (sAttrValue);
else
_warn (ret, "Unsupported attribute '" + sAttrName + "'='" + sAttrValue + "'");
}
for (final IMicroElement eLetChild : eLet.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eLetChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eLetChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eLetChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read all attributes for a linkable group
*
* @param aAttrs
* The attributes of a micro element. May be null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSLinkableGroup readLinkableGroupFromXML (@Nullable final Map aAttrs)
{
final PSLinkableGroup ret = new PSLinkableGroup ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ROLE))
ret.setRole (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_SUBJECT))
ret.setSubject (sAttrValue);
}
return ret;
}
/**
* Read a <name> element
*
* @param eName
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSName readNameFromXML (@Nonnull final IMicroElement eName)
{
final PSName ret = new PSName ();
final Map aAttrs = eName.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_PATH))
ret.setPath (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
for (final IMicroElement eNameChild : eName.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eNameChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eNameChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eNameChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read a <ns> element
*
* @param eNS
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSNS readNSFromXML (@Nonnull final IMicroElement eNS)
{
final PSNS ret = new PSNS ();
final Map aAttrs = eNS.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_URI))
ret.setUri (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_PREFIX))
ret.setPrefix (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
for (final IMicroElement eLetChild : eNS.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eLetChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eLetChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eLetChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read a <p> element
*
* @param eP
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSP readPFromXML (@Nonnull final IMicroElement eP)
{
final PSP ret = new PSP ();
final Map aAttrs = eP.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_CLASS))
ret.setClazz (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_ICON))
ret.setIcon (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
if (eP.hasChildren ())
for (final IMicroNode aChild : eP.getChildren ())
switch (aChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
final String sLocalName = eElement.getLocalName ();
if (sLocalName.equals (CSchematronXML.ELEMENT_DIR))
ret.addDir (readDirFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_EMPH))
ret.addEmph (readEmphFromXML (eElement));
else
if (sLocalName.equals (CSchematronXML.ELEMENT_SPAN))
ret.addSpan (readSpanFromXML (eElement));
else
_warn (ret, "Unsupported Schematron element '" + sLocalName + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aChild);
}
return ret;
}
/**
* Read a <param> element
*
* @param eParam
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSParam readParamFromXML (@Nonnull final IMicroElement eParam)
{
final PSParam ret = new PSParam ();
final Map aAttrs = eParam.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_NAME))
ret.setName (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_VALUE))
ret.setValue (sAttrValue);
else
_warn (ret, "Unsupported attribute '" + sAttrName + "'='" + sAttrValue + "'");
}
for (final IMicroElement eParamChild : eParam.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eParamChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eParamChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eParamChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read a <pattern> element
*
* @param ePattern
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSPattern readPatternFromXML (@Nonnull final IMicroElement ePattern)
{
final PSPattern ret = new PSPattern ();
final Map aAttrs = ePattern.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ABSTRACT))
ret.setAbstract (StringParser.parseBool (sAttrValue));
else
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_IS_A))
ret.setIsA (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
}
for (final IMicroElement ePatternChild : ePattern.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (ePatternChild.getNamespaceURI ()))
{
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
ret.addInclude (readIncludeFromXML (ePatternChild));
else
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_TITLE))
ret.setTitle (readTitleFromXML (ePatternChild));
else
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_P))
ret.addP (readPFromXML (ePatternChild));
else
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_LET))
ret.addLet (readLetFromXML (ePatternChild));
else
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_RULE))
ret.addRule (readRuleFromXML (ePatternChild));
else
if (ePatternChild.getLocalName ().equals (CSchematronXML.ELEMENT_PARAM))
ret.addParam (readParamFromXML (ePatternChild));
else
_warn (ret,
"Unsupported Schematron element '" +
ePatternChild.getLocalName () +
"' in " +
ret.toString ());
}
else
ret.addForeignElement (ePatternChild.getClone ());
}
return ret;
}
/**
* Read a <phase> element
*
* @param ePhase
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSPhase readPhaseFromXML (@Nonnull final IMicroElement ePhase)
{
final PSPhase ret = new PSPhase ();
final Map aAttrs = ePhase.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
}
for (final IMicroElement ePhaseChild : ePhase.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (ePhaseChild.getNamespaceURI ()))
{
if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
ret.addInclude (readIncludeFromXML (ePhaseChild));
else
if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_P))
ret.addP (readPFromXML (ePhaseChild));
else
if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_LET))
ret.addLet (readLetFromXML (ePhaseChild));
else
if (ePhaseChild.getLocalName ().equals (CSchematronXML.ELEMENT_ACTIVE))
ret.addActive (readActiveFromXML (ePhaseChild));
else
_warn (ret, "Unsupported Schematron element '" + ePhaseChild.getLocalName () + "'");
}
else
ret.addForeignElement (ePhaseChild.getClone ());
}
return ret;
}
/**
* Read all attributes that make up a rich group
*
* @param aAttrs
* The attributes of a micro element. May be null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSRichGroup readRichGroupFromXML (@Nullable final Map aAttrs)
{
final PSRichGroup ret = new PSRichGroup ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ICON))
ret.setIcon (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_SEE))
ret.setSee (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_FPI))
ret.setFPI (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_XML_LANG))
ret.setXmlLang (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_XML_SPACE))
ret.setXmlSpace (ESpace.getFromIDOrNull (sAttrValue));
}
return ret;
}
/**
* Read a <rule> element
*
* @param eRule
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSRule readRuleFromXML (@Nonnull final IMicroElement eRule)
{
final PSRule ret = new PSRule ();
final Map aAttrs = eRule.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_FLAG))
ret.setFlag (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_ABSTRACT))
ret.setAbstract (StringParser.parseBool (sAttrValue));
else
if (sAttrName.equals (CSchematronXML.ATTR_CONTEXT))
ret.setContext (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName) && !PSLinkableGroup.isLinkableAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
ret.setLinkable (readLinkableGroupFromXML (aAttrs));
}
for (final IMicroElement eRuleChild : eRule.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eRuleChild.getNamespaceURI ()))
{
if (eRuleChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
ret.addInclude (readIncludeFromXML (eRuleChild));
else
if (eRuleChild.getLocalName ().equals (CSchematronXML.ELEMENT_LET))
ret.addLet (readLetFromXML (eRuleChild));
else
if (eRuleChild.getLocalName ().equals (CSchematronXML.ELEMENT_ASSERT) ||
eRuleChild.getLocalName ().equals (CSchematronXML.ELEMENT_REPORT))
ret.addAssertReport (readAssertReportFromXML (eRuleChild));
else
if (eRuleChild.getLocalName ().equals (CSchematronXML.ELEMENT_EXTENDS))
ret.addExtends (readExtendsFromXML (eRuleChild));
else
_warn (ret, "Unsupported Schematron element '" + eRuleChild.getLocalName () + "'");
}
else
ret.addForeignElement (eRuleChild.getClone ());
}
return ret;
}
/**
* Parse the Schematron into a pure Java object. This method makes no
* assumptions on the validity of the document!
*
* @param eSchema
* The XML element to use. May not be null
.
* @return The created {@link PSSchema} object or null
in case of
* null
document or a fatal error.
* @throws SchematronReadException
* If reading fails
*/
@Nonnull
public PSSchema readSchemaFromXML (@Nonnull final IMicroElement eSchema) throws SchematronReadException
{
ValueEnforcer.notNull (eSchema, "Schema");
if (!CSchematron.NAMESPACE_SCHEMATRON.equals (eSchema.getNamespaceURI ()))
throw new SchematronReadException (m_aResource, "The passed element is not an ISO Schematron element!");
final PSSchema ret = new PSSchema (m_aResource);
final Map aAttrs = eSchema.getAllAttributes ();
if (aAttrs != null)
{
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_ID))
ret.setID (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_SCHEMA_VERSION))
ret.setSchemaVersion (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_DEFAULT_PHASE))
ret.setDefaultPhase (sAttrValue);
else
if (sAttrName.equals (CSchematronXML.ATTR_QUERY_BINDING))
ret.setQueryBinding (sAttrValue);
else
if (!PSRichGroup.isRichAttribute (sAttrName))
ret.addForeignAttribute (sAttrName, sAttrValue);
}
ret.setRich (readRichGroupFromXML (aAttrs));
}
for (final IMicroElement eSchemaChild : eSchema.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eSchemaChild.getNamespaceURI ()))
{
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_INCLUDE))
ret.addInclude (readIncludeFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_TITLE))
ret.setTitle (readTitleFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_NS))
ret.addNS (readNSFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_P))
{
final PSP aP = readPFromXML (eSchemaChild);
if (ret.hasNoPatterns ())
ret.addStartP (aP);
else
ret.addEndP (aP);
}
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_LET))
ret.addLet (readLetFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_PHASE))
ret.addPhase (readPhaseFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_PATTERN))
ret.addPattern (readPatternFromXML (eSchemaChild));
else
if (eSchemaChild.getLocalName ().equals (CSchematronXML.ELEMENT_DIAGNOSTICS))
ret.setDiagnostics (readDiagnosticsFromXML (eSchemaChild));
else
_warn (ret, "Unsupported Schematron element '" + eSchemaChild.getLocalName () + "'");
}
else
ret.addForeignElement (eSchemaChild.getClone ());
}
return ret;
}
/**
* Read a <span> element
*
* @param eSpan
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSSpan readSpanFromXML (@Nonnull final IMicroElement eSpan)
{
final PSSpan ret = new PSSpan ();
final Map aAttrs = eSpan.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_CLASS))
ret.setClazz (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
if (eSpan.hasChildren ())
for (final IMicroNode aSpanChild : eSpan.getChildren ())
switch (aSpanChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aSpanChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aSpanChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eElement.getLocalName () + "'");
}
else
ret.addForeignElement (eElement.getClone ());
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aSpanChild);
}
return ret;
}
/**
* Read a <title> element
*
* @param eTitle
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSTitle readTitleFromXML (@Nonnull final IMicroElement eTitle)
{
final PSTitle ret = new PSTitle ();
final Map aAttrs = eTitle.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
_warn (ret, "Unsupported attribute '" + sAttrName + "'='" + sAttrValue + "'");
}
if (eTitle.hasChildren ())
for (final IMicroNode aTitleChild : eTitle.getChildren ())
switch (aTitleChild.getType ())
{
case TEXT:
ret.addText (((IMicroText) aTitleChild).getNodeValue ());
break;
case ELEMENT:
final IMicroElement eElement = (IMicroElement) aTitleChild;
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eElement.getNamespaceURI ()))
{
final String sLocalName = eElement.getLocalName ();
if (sLocalName.equals (CSchematronXML.ELEMENT_DIR))
ret.addDir (readDirFromXML (eElement));
else
_warn (ret, "Unsupported Schematron element '" + sLocalName + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eElement.getNamespaceURI () + "'");
break;
case COMMENT:
// Ignore comments
break;
default:
_warn (ret, "Unsupported child node: " + aTitleChild);
}
return ret;
}
/**
* Read a <value-of> element
*
* @param eValueOf
* The source micro element. Never null
.
* @return The created domain object. May not be null
.
*/
@Nonnull
public PSValueOf readValueOfFromXML (@Nonnull final IMicroElement eValueOf)
{
final PSValueOf ret = new PSValueOf ();
final Map aAttrs = eValueOf.getAllAttributes ();
if (aAttrs != null)
for (final Map.Entry aEntry : aAttrs.entrySet ())
{
final String sAttrName = aEntry.getKey ();
final String sAttrValue = _getAttributeValue (aEntry.getValue ());
if (sAttrName.equals (CSchematronXML.ATTR_SELECT))
ret.setSelect (sAttrValue);
else
ret.addForeignAttribute (sAttrName, sAttrValue);
}
for (final IMicroElement eValueOfChild : eValueOf.getAllChildElements ())
{
if (CSchematron.NAMESPACE_SCHEMATRON.equals (eValueOfChild.getNamespaceURI ()))
{
_warn (ret, "Unsupported Schematron element '" + eValueOfChild.getLocalName () + "'");
}
else
_warn (ret, "Unsupported namespace URI '" + eValueOfChild.getNamespaceURI () + "'");
}
return ret;
}
/**
* Read the schema from the resource supplied in the constructor. First all
* includes are resolved and the {@link #readSchemaFromXML(IMicroElement)} is
* called.
*
* @return The read {@link PSSchema}.
* @throws SchematronReadException
* If reading fails
*/
@Nonnull
public PSSchema readSchema () throws SchematronReadException
{
// Resolve all includes as the first action
final IMicroDocument aDoc = SchematronHelper.getWithResolvedSchematronIncludes (m_aResource);
if (aDoc == null || aDoc.getDocumentElement () == null)
throw new SchematronReadException (m_aResource, "Failed to resolve includes in resource " + m_aResource);
return readSchemaFromXML (aDoc.getDocumentElement ());
}
@Override
public String toString ()
{
return new ToStringGenerator (this).append ("resource", m_aResource)
.append ("errorHandler", m_aErrorHandler)
.toString ();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy