diff --git a/README.md b/README.md
index af74e1f5..b5449dd4 100644
--- a/README.md
+++ b/README.md
@@ -15,17 +15,21 @@ ph-css and ph-csscompress-maven-plugin are both licensed under the **Apache 2.0
## News and noteworthy
* v5.0.2 - 2016-xx-yy
- * Made tab size configurable (issue #29)
- * Improved media expressions (issue #30)
+ * Made tab size configurable (issue #29)
+ * Improved media expressions (issue #30)
+ * Allowing to disable consistency checks in class `CSSValue`
+ * Made CSS interpretation warnings customizable with class `ICSSInterpretErrorHandler` (issue #33)
* v5.0.1 - 2016-08-17
* Using "modern java template" for JavaCC parser - results in quicker execution
* Enhancement issue #27
- * Intergated `ph-csscompress-maven-plugin` into this repository
+ * Integrated `ph-csscompress-maven-plugin` into this repository
* Bug fix wrong OutputStream (issue #28)
* v5.0.0 - 2016-06-12
* Using JDK8 as the basis
* removed explicit grammar for CSS 2.1 (issue #20)
* Added browser compliant error handler
+ * v4.1.6 - 2016-xx-yy
+ * Made CSS interpretation warnings customizable with class `ICSSInterpretErrorHandler` (issue #33)
* v4.1.5 - 2016-09-16
* Improved media expressions (issue #30)
* Integrated ph-csscompress-maven-plugin into this project (compatibility to 5.x)
diff --git a/ph-css/src/main/java/com/helger/css/ECSSVersion.java b/ph-css/src/main/java/com/helger/css/ECSSVersion.java
index bf57d4e8..067e74d8 100644
--- a/ph-css/src/main/java/com/helger/css/ECSSVersion.java
+++ b/ph-css/src/main/java/com/helger/css/ECSSVersion.java
@@ -30,8 +30,10 @@
public enum ECSSVersion implements IHasVersion
{
// Sort fields according to the version!
- @DevelopersNote ("No CSS parser is available for 1.0!") CSS10(new Version (1, 0)),
- @DevelopersNote ("Up to version 4.x of ph-css a special CSS 2.1 parser was available") CSS21(new Version (2, 1)),
+ @DevelopersNote ("No CSS parser is available for 1.0!")
+ CSS10(new Version (1, 0)),
+ @DevelopersNote ("Up to version 4.x of ph-css a special CSS 2.1 parser was available. Now it is the same as CSS 3.0")
+ CSS21(new Version (2, 1)),
CSS30 (new Version (3, 0));
/** Latest version is CSS 3.0 */
diff --git a/ph-css/src/main/java/com/helger/css/handler/CSSHandler.java b/ph-css/src/main/java/com/helger/css/handler/CSSHandler.java
index 6cad284b..eeefbc83 100644
--- a/ph-css/src/main/java/com/helger/css/handler/CSSHandler.java
+++ b/ph-css/src/main/java/com/helger/css/handler/CSSHandler.java
@@ -17,14 +17,19 @@
package com.helger.css.handler;
import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.PresentForCodeCoverage;
+import com.helger.commons.concurrent.SimpleReadWriteLock;
import com.helger.css.ECSSVersion;
import com.helger.css.decl.CSSDeclarationList;
import com.helger.css.decl.CascadingStyleSheet;
import com.helger.css.parser.CSSNode;
+import com.helger.css.reader.CSSReader;
+import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
+import com.helger.css.reader.errorhandler.LoggingCSSInterpretErrorHandler;
/**
* This class is the entry point for converting AST nodes from the parser to
@@ -35,6 +40,11 @@
@Immutable
public final class CSSHandler
{
+ private static final SimpleReadWriteLock s_aRWLock = new SimpleReadWriteLock ();
+
+ @GuardedBy ("s_aRWLock")
+ private static ICSSInterpretErrorHandler s_aDefaultInterpretErrorHandler = new LoggingCSSInterpretErrorHandler ();
+
@PresentForCodeCoverage
private static final CSSHandler s_aInstance = new CSSHandler ();
@@ -51,15 +61,37 @@ private CSSHandler ()
* @return Never null
.
*/
@Nonnull
+ @Deprecated
public static CascadingStyleSheet readCascadingStyleSheetFromNode (@Nonnull final ECSSVersion eVersion,
@Nonnull final CSSNode aNode)
+ {
+ return readCascadingStyleSheetFromNode (eVersion, aNode, CSSReader.getDefaultInterpretErrorHandler ());
+ }
+
+ /**
+ * Create a {@link CascadingStyleSheet} object from a parsed object.
+ *
+ * @param eVersion
+ * The CSS version to use. May not be null
.
+ * @param aNode
+ * The parsed CSS object to read. May not be null
.
+ * @param aErrorHandler
+ * The error handler to be used. May not be null
.
+ * @return Never null
.
+ * @since 5.0.2
+ */
+ @Nonnull
+ public static CascadingStyleSheet readCascadingStyleSheetFromNode (@Nonnull final ECSSVersion eVersion,
+ @Nonnull final CSSNode aNode,
+ @Nonnull final ICSSInterpretErrorHandler aErrorHandler)
{
ValueEnforcer.notNull (eVersion, "Version");
ValueEnforcer.notNull (aNode, "Node");
if (!ECSSNodeType.ROOT.isNode (aNode, eVersion))
throw new CSSHandlingException (aNode, "Passed node is not a root node!");
+ ValueEnforcer.notNull (aErrorHandler, "ErrorHandler");
- return new CSSNodeToDomainObject (eVersion).createCascadingStyleSheetFromNode (aNode);
+ return new CSSNodeToDomainObject (eVersion, aErrorHandler).createCascadingStyleSheetFromNode (aNode);
}
/**
@@ -72,14 +104,36 @@ public static CascadingStyleSheet readCascadingStyleSheetFromNode (@Nonnull fina
* @return Never null
.
*/
@Nonnull
+ @Deprecated
public static CSSDeclarationList readDeclarationListFromNode (@Nonnull final ECSSVersion eVersion,
@Nonnull final CSSNode aNode)
+ {
+ return readDeclarationListFromNode (eVersion, aNode, CSSReader.getDefaultInterpretErrorHandler ());
+ }
+
+ /**
+ * Create a {@link CSSDeclarationList} object from a parsed object.
+ *
+ * @param eVersion
+ * The CSS version to use. May not be null
.
+ * @param aNode
+ * The parsed CSS object to read. May not be null
.
+ * @param aErrorHandler
+ * The error handler to be used. May not be null
.
+ * @return Never null
.
+ * @since 5.0.2
+ */
+ @Nonnull
+ public static CSSDeclarationList readDeclarationListFromNode (@Nonnull final ECSSVersion eVersion,
+ @Nonnull final CSSNode aNode,
+ @Nonnull final ICSSInterpretErrorHandler aErrorHandler)
{
ValueEnforcer.notNull (eVersion, "Version");
ValueEnforcer.notNull (aNode, "Node");
if (!ECSSNodeType.STYLEDECLARATIONLIST.isNode (aNode, eVersion))
throw new CSSHandlingException (aNode, "Passed node is not a style declaration node!");
+ ValueEnforcer.notNull (aErrorHandler, "ErrorHandler");
- return new CSSNodeToDomainObject (eVersion).createDeclarationListFromNode (aNode);
+ return new CSSNodeToDomainObject (eVersion, aErrorHandler).createDeclarationListFromNode (aNode);
}
}
diff --git a/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java b/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java
index c2783589..fdd1dcf9 100644
--- a/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java
+++ b/ph-css/src/main/java/com/helger/css/handler/CSSNodeToDomainObject.java
@@ -22,9 +22,6 @@
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.Nonempty;
import com.helger.commons.collection.ext.CommonsArrayList;
@@ -77,6 +74,7 @@
import com.helger.css.media.ECSSMedium;
import com.helger.css.parser.CSSNode;
import com.helger.css.parser.CSSParseHelper;
+import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -89,19 +87,22 @@
@NotThreadSafe
final class CSSNodeToDomainObject
{
- private static final Logger s_aLogger = LoggerFactory.getLogger (CSSNodeToDomainObject.class);
-
private final ECSSVersion m_eVersion;
+ private final ICSSInterpretErrorHandler m_aErrorHandler;
/**
* Constructor
*
* @param eVersion
* The CSS version to use. May not be null
.
+ * @param aErrorHandler
+ * Error handler to use. May not be null
.
*/
- public CSSNodeToDomainObject (@Nonnull final ECSSVersion eVersion)
+ public CSSNodeToDomainObject (@Nonnull final ECSSVersion eVersion,
+ @Nonnull final ICSSInterpretErrorHandler aErrorHandler)
{
m_eVersion = ValueEnforcer.notNull (eVersion, "Version");
+ m_aErrorHandler = ValueEnforcer.notNull (aErrorHandler, "ErrorHandler");
}
private void _expectNodeType (@Nonnull final CSSNode aNode, @Nonnull final ECSSNodeType eExpected)
@@ -115,11 +116,11 @@ private void _expectNodeType (@Nonnull final CSSNode aNode, @Nonnull final ECSSN
"'");
}
- private static void _throwUnexpectedChildrenCount (@Nonnull final CSSNode aNode, @Nonnull @Nonempty final String sMsg)
+ private void _throwUnexpectedChildrenCount (@Nonnull final CSSNode aNode, @Nonnull @Nonempty final String sMsg)
{
- s_aLogger.error (sMsg);
+ m_aErrorHandler.onCSSInterpretationError (sMsg);
for (int i = 0; i < aNode.jjtGetNumChildren (); ++i)
- s_aLogger.error (" " + aNode.jjtGetChild (i));
+ m_aErrorHandler.onCSSInterpretationError (" " + aNode.jjtGetChild (i));
throw new CSSHandlingException (aNode, sMsg);
}
@@ -171,11 +172,12 @@ private CSSImportRule _createImportRule (@Nonnull final CSSNode aNode)
++nCurrentIndex;
}
else
- s_aLogger.error ("Expected an MEDIALIST node but got " + ECSSNodeType.getNodeName (aMediaListNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Expected an MEDIALIST node but got " +
+ ECSSNodeType.getNodeName (aMediaListNode, m_eVersion));
}
if (nCurrentIndex < nChildCount)
- s_aLogger.error ("Import statement has children which are unhandled.");
+ m_aErrorHandler.onCSSInterpretationError ("Import statement has children which are unhandled.");
return ret;
}
@@ -253,7 +255,7 @@ private ICSSSelectorMember _createSelectorMember (final CSSNode aNode)
final String sText = aNode.getText ();
final ECSSSelectorCombinator eCombinator = ECSSSelectorCombinator.getFromNameOrNull (sText);
if (eCombinator == null)
- s_aLogger.error ("Failed to parse CSS selector combinator '" + sText + "'");
+ m_aErrorHandler.onCSSInterpretationError ("Failed to parse CSS selector combinator '" + sText + "'");
return eCombinator;
}
@@ -309,7 +311,8 @@ private ICSSSelectorMember _createSelectorMember (final CSSNode aNode)
aNode.toString ());
}
- s_aLogger.error ("Unsupported selector child: " + ECSSNodeType.getNodeName (aNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported selector child: " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion));
return null;
}
@@ -375,15 +378,15 @@ private CSSExpressionMemberMathProduct _createExpressionMathProduct (@Nonnull fi
final String sText = aChildChildNode.getText ();
final ECSSMathOperator eMathOp = ECSSMathOperator.getFromNameOrNull (sText);
if (eMathOp == null)
- s_aLogger.error ("Failed to parse math operator '" + sText + "'");
+ m_aErrorHandler.onCSSInterpretationError ("Failed to parse math operator '" + sText + "'");
else
aNestedProduct.addMember (eMathOp);
}
else
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildChildNode, m_eVersion));
}
ret.addMember (new CSSExpressionMemberMathUnitProduct (aNestedProduct));
}
@@ -394,15 +397,15 @@ private CSSExpressionMemberMathProduct _createExpressionMathProduct (@Nonnull fi
final String sText = aChildNode.getText ();
final ECSSMathOperator eMathOp = ECSSMathOperator.getFromNameOrNull (sText);
if (eMathOp == null)
- s_aLogger.error ("Failed to parse math product operator '" + sText + "'");
+ m_aErrorHandler.onCSSInterpretationError ("Failed to parse math product operator '" + sText + "'");
else
ret.addMember (eMathOp);
}
else
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
@@ -470,15 +473,15 @@ private CSSExpressionMemberMath _createExpressionMathTerm (@Nonnull final CSSNod
final String sText = aChildNode.getText ();
final ECSSMathOperator eMathOp = ECSSMathOperator.getFromNameOrNull (sText);
if (eMathOp == null)
- s_aLogger.error ("Failed to parse math operator '" + sText + "'");
+ m_aErrorHandler.onCSSInterpretationError ("Failed to parse math operator '" + sText + "'");
else
ret.addMember (eMathOp);
}
else
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
@@ -540,16 +543,16 @@ private CSSExpression _createExpression (@Nonnull final CSSNode aNode)
final String sText = aChildNode.getText ();
final ECSSExpressionOperator eOp = ECSSExpressionOperator.getFromNameOrNull (sText);
if (eOp == null)
- s_aLogger.error ("Failed to parse expression operator '" + sText + "'");
+ m_aErrorHandler.onCSSInterpretationError ("Failed to parse expression operator '" + sText + "'");
else
ret.addMember (eOp);
}
else
{
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
}
return ret;
@@ -585,10 +588,10 @@ private CSSDeclaration _createDeclaration (@Nonnull final CSSNode aNode)
if (ECSSNodeType.IMPORTANT.isNode (aChildNode, m_eVersion))
bImportant = true;
else
- s_aLogger.error ("Expected an " +
- ECSSNodeType.IMPORTANT.getNodeName (m_eVersion) +
- " token but got a " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Expected an " +
+ ECSSNodeType.IMPORTANT.getNodeName (m_eVersion) +
+ " token but got a " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
final CSSDeclaration ret = new CSSDeclaration (sProperty, aExpression, bImportant);
@@ -628,7 +631,7 @@ private CSSStyleRule _createStyleRule (@Nonnull final CSSNode aNode)
if (ECSSNodeType.SELECTOR.isNode (aChildNode, m_eVersion))
{
if (!bSelectors)
- s_aLogger.error ("Found a selector after a declaration!");
+ m_aErrorHandler.onCSSInterpretationError ("Found a selector after a declaration!");
ret.addSelector (_createSelector (aChildNode));
}
@@ -643,10 +646,10 @@ private CSSStyleRule _createStyleRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
}
@@ -712,8 +715,8 @@ private CSSPageRule _createPageRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aBodyChildNode, m_eVersion))
- s_aLogger.error ("Unsupported page rule body child: " +
- ECSSNodeType.getNodeName (aBodyChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported page rule body child: " +
+ ECSSNodeType.getNodeName (aBodyChildNode, m_eVersion));
}
return ret;
@@ -745,7 +748,8 @@ private CSSPageRule _createPageRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported page rule child: " + ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported page rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -794,8 +798,8 @@ private CSSMediaRule _createMediaRule (@Nonnull final CSSNode aNode)
ret.addRule (_createSupportsRule (aChildNode));
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported media-rule child: " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported media-rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -809,7 +813,11 @@ private CSSMediaQuery _createMediaQuery (@Nonnull final CSSNode aNode)
// CSS 2.1 compatibility
final String sMedium = aNode.getText ();
if (ECSSMedium.getFromNameOrNull (sMedium) == null)
- s_aLogger.warn ("CSS " + m_eVersion.getVersionString () + " Media query uses unknown medium '" + sMedium + "'");
+ m_aErrorHandler.onCSSInterpretationWarning ("CSS " +
+ m_eVersion.getVersionString () +
+ " Media query uses unknown medium '" +
+ sMedium +
+ "'");
final CSSMediaQuery ret = new CSSMediaQuery (EModifier.NONE, sMedium);
ret.setSourceLocation (aNode.getSourceLocation ());
return ret;
@@ -838,7 +846,7 @@ private CSSMediaQuery _createMediaQuery (@Nonnull final CSSNode aNode)
if ("only".equalsIgnoreCase (sMediaModifier))
eModifier = EModifier.ONLY;
else
- s_aLogger.error ("Unsupported media modifier '" + sMediaModifier + "' found!");
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported media modifier '" + sMediaModifier + "' found!");
}
++nStartIndex;
}
@@ -853,11 +861,11 @@ private CSSMediaQuery _createMediaQuery (@Nonnull final CSSNode aNode)
{
sMedium = aNextChild.getText ();
if (ECSSMedium.getFromNameOrNull (sMedium) == null)
- s_aLogger.warn ("CSS " +
- m_eVersion.getVersionString () +
- " media query uses unknown medium '" +
- sMedium +
- "'");
+ m_aErrorHandler.onCSSInterpretationWarning ("CSS " +
+ m_eVersion.getVersionString () +
+ " media query uses unknown medium '" +
+ sMedium +
+ "'");
++nStartIndex;
}
}
@@ -871,7 +879,8 @@ private CSSMediaQuery _createMediaQuery (@Nonnull final CSSNode aNode)
ret.addMediaExpression (_createMediaExpr (aChildNode));
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported media query child: " + ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported media query child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -890,7 +899,7 @@ private CSSMediaExpression _createMediaExpr (@Nonnull final CSSNode aNode)
ECSSNodeType.getNodeName (aFeatureNode, m_eVersion));
final String sFeature = aFeatureNode.getText ();
if (ECSSMediaExpressionFeature.getFromNameOrNull (sFeature) == null)
- s_aLogger.warn ("Media expression uses unknown feature '" + sFeature + "'");
+ m_aErrorHandler.onCSSInterpretationWarning ("Media expression uses unknown feature '" + sFeature + "'");
CSSMediaExpression ret;
if (nChildCount == 1)
@@ -925,7 +934,8 @@ private CSSFontFaceRule _createFontFaceRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported font-face rule child: " + ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported font-face rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -981,7 +991,8 @@ private CSSKeyframesRule _createKeyframesRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported keyframes rule child: " + ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported keyframes rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
++nIndex;
}
@@ -1008,7 +1019,8 @@ private CSSViewportRule _createViewportRule (@Nonnull final CSSNode aNode)
}
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported viewport rule child: " + ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported viewport rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -1095,13 +1107,14 @@ private ICSSSupportsConditionMember _createSupportsConditionMemberRecursive (@No
return ret;
}
- s_aLogger.error ("Unsupported supportsConditionInParents child: " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported supportsConditionInParents child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
return null;
}
if (!ECSSNodeType.isErrorNode (aNode, m_eVersion))
- s_aLogger.error ("Unsupported supports-condition child: " + ECSSNodeType.getNodeName (aNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported supports-condition child: " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion));
return null;
}
@@ -1150,8 +1163,8 @@ private CSSSupportsRule _createSupportsRule (@Nonnull final CSSNode aNode)
ret.addRule (_createSupportsRule (aChildNode));
else
if (!ECSSNodeType.isErrorNode (aChildNode, m_eVersion))
- s_aLogger.error ("Unsupported supports-rule child: " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported supports-rule child: " +
+ ECSSNodeType.getNodeName (aChildNode, m_eVersion));
}
return ret;
}
@@ -1233,10 +1246,11 @@ public CascadingStyleSheet createCascadingStyleSheetFromNode (@Nonnull final CSS
ret.addRule (_createUnknownRule (aChildNode));
}
else
- s_aLogger.error ("Unsupported child of " +
- ECSSNodeType.getNodeName (aNode, m_eVersion) +
- ": " +
- ECSSNodeType.getNodeName (aChildNode, m_eVersion));
+ m_aErrorHandler.onCSSInterpretationError ("Unsupported child of " +
+ ECSSNodeType.getNodeName (aNode, m_eVersion) +
+ ": " +
+ ECSSNodeType.getNodeName (aChildNode,
+ m_eVersion));
}
return ret;
}
diff --git a/ph-css/src/main/java/com/helger/css/parser/AbstractParserCSS.java b/ph-css/src/main/java/com/helger/css/parser/AbstractParserCSS.java
index 2425dd7a..788796d2 100644
--- a/ph-css/src/main/java/com/helger/css/parser/AbstractParserCSS.java
+++ b/ph-css/src/main/java/com/helger/css/parser/AbstractParserCSS.java
@@ -37,35 +37,57 @@ public abstract class AbstractParserCSS
protected ICSSParseErrorHandler m_aCustomErrorHandler;
protected boolean m_bBrowserCompliantMode = false;
+ /**
+ * Set a custom error handler to use.
+ *
+ * @param aCustomErrorHandler
+ * The custom error handler to use. May be null
.
+ */
public final void setCustomErrorHandler (@Nullable final ICSSParseErrorHandler aCustomErrorHandler)
{
m_aCustomErrorHandler = aCustomErrorHandler;
}
+ /**
+ * @return The custom error handler to be used for this parser. May be
+ * null
.
+ */
@Nullable
public final ICSSParseErrorHandler getCustomErrorHandler ()
{
return m_aCustomErrorHandler;
}
+ /**
+ * Enable or disable browser compliant mode.
+ *
+ * @param bBrowserCompliantMode
+ * true
to enable browser compliant mode,
+ * false
to disable it.
+ */
public final void setBrowserCompliantMode (final boolean bBrowserCompliantMode)
{
m_bBrowserCompliantMode = bBrowserCompliantMode;
}
+ /**
+ * @return true
if browser compliant mode is active,
+ * false
if not. By default browser compliant mode is
+ * disabled.
+ */
public final boolean isBrowserCompliantMode ()
{
return m_bBrowserCompliantMode;
}
// Used when NODE_SCOPE_HOOK is true - for debugging only
- // Package scope to avoid warning when NODE_SCOPE_HOOK is false
public void jjtreeOpenNodeScope (final Node aNode)
{
if (s_aLogger.isDebugEnabled ())
s_aLogger.debug ("Opening scope for " + aNode.toString ());
}
+ // Used when NODE_SCOPE_HOOK is true - for debugging only
public void jjtreeCloseNodeScope (final Node aNode)
{
if (s_aLogger.isDebugEnabled ())
diff --git a/ph-css/src/main/java/com/helger/css/propertyvalue/CSSValue.java b/ph-css/src/main/java/com/helger/css/propertyvalue/CSSValue.java
index b63e02cb..1bf16e04 100644
--- a/ph-css/src/main/java/com/helger/css/propertyvalue/CSSValue.java
+++ b/ph-css/src/main/java/com/helger/css/propertyvalue/CSSValue.java
@@ -47,7 +47,35 @@
@NotThreadSafe
public class CSSValue implements ICSSValue
{
+ public static final boolean DEFAULT_CONSISTENCY_CHECKS_ENABLED = true;
+
private static final Logger s_aLogger = LoggerFactory.getLogger (CSSValue.class);
+ private static boolean s_bConsistencyChecksEnabled = DEFAULT_CONSISTENCY_CHECKS_ENABLED;
+
+ /**
+ * @return true
if consistency checks are enabled (by default),
+ * false
if not.
+ * @since 5.0.2
+ */
+ public static boolean areConsistencyChecksEnabled ()
+ {
+ return s_bConsistencyChecksEnabled;
+ }
+
+ /**
+ * Enable or disable consistency checks. By default the consistency checks are
+ * enabled (for backwards compatibility) but if performance is a real matter,
+ * you may want to disable them globally.
+ *
+ * @param bEnabled
+ * true
to enable them, false
to disable
+ * them.
+ * @since 5.0.2
+ */
+ public static void setConsistencyChecksEnabled (final boolean bEnabled)
+ {
+ s_bConsistencyChecksEnabled = bEnabled;
+ }
private ICSSProperty m_aProperty;
private String m_sValue;
@@ -142,18 +170,22 @@ public String getValue ()
public CSSValue setValue (@Nonnull final String sValue)
{
ValueEnforcer.notNull (sValue, "Value");
- if (!m_aProperty.isValidValue (sValue))
- s_aLogger.warn ("CSS: the value '" +
- sValue +
- "' is not valid for property '" +
- m_aProperty.getPropertyName () +
- "'");
- if (sValue.contains (CCSS.IMPORTANT_SUFFIX))
- s_aLogger.warn ("CSS: the value '" +
- sValue +
- "' should not contain the '" +
- CCSS.IMPORTANT_SUFFIX +
- "' string! Use 'setImportant' method instead.");
+
+ if (areConsistencyChecksEnabled ())
+ {
+ if (!m_aProperty.isValidValue (sValue))
+ s_aLogger.warn ("CSS: the value '" +
+ sValue +
+ "' is not valid for property '" +
+ m_aProperty.getPropertyName () +
+ "'");
+ if (sValue.contains (CCSS.IMPORTANT_SUFFIX))
+ s_aLogger.warn ("CSS: the value '" +
+ sValue +
+ "' should not contain the '" +
+ CCSS.IMPORTANT_SUFFIX +
+ "' string! Use 'setImportant' method instead.");
+ }
m_sValue = sValue.trim ();
return this;
}
diff --git a/ph-css/src/main/java/com/helger/css/reader/CSSReader.java b/ph-css/src/main/java/com/helger/css/reader/CSSReader.java
index 3511c048..0fe0820e 100644
--- a/ph-css/src/main/java/com/helger/css/reader/CSSReader.java
+++ b/ph-css/src/main/java/com/helger/css/reader/CSSReader.java
@@ -63,7 +63,9 @@
import com.helger.css.parser.ParserCSS30TokenManager;
import com.helger.css.parser.ParserCSSCharsetDetector;
import com.helger.css.parser.ParserCSSCharsetDetectorTokenManager;
+import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
import com.helger.css.reader.errorhandler.ICSSParseErrorHandler;
+import com.helger.css.reader.errorhandler.LoggingCSSInterpretErrorHandler;
import com.helger.css.reader.errorhandler.ThrowingCSSParseErrorHandler;
/**
@@ -88,6 +90,9 @@ public final class CSSReader
@GuardedBy ("s_aRWLock")
private static ICSSParseExceptionCallback s_aDefaultParseExceptionHandler = new LoggingCSSParseExceptionCallback ();
+ @GuardedBy ("s_aRWLock")
+ private static ICSSInterpretErrorHandler s_aDefaultInterpretErrorHandler = new LoggingCSSInterpretErrorHandler ();
+
@PresentForCodeCoverage
private static final CSSReader s_aInstance = new CSSReader ();
@@ -144,6 +149,32 @@ public static void setDefaultParseExceptionHandler (@Nonnull final ICSSParseExce
s_aRWLock.writeLocked ( () -> s_aDefaultParseExceptionHandler = aDefaultParseExceptionHandler);
}
+ /**
+ * @return The default interpret error handler to handle interpretation errors
+ * in successfully parsed CSS. Never null
.
+ * @since 5.0.2
+ */
+ @Nonnull
+ public static ICSSInterpretErrorHandler getDefaultInterpretErrorHandler ()
+ {
+ return s_aRWLock.readLocked ( () -> s_aDefaultInterpretErrorHandler);
+ }
+
+ /**
+ * Set the default interpret error handler to handle interpretation errors in
+ * successfully parsed CSS.
+ *
+ * @param aDefaultErrorHandler
+ * The default error handler to be used. May not be null
.
+ * @since 5.0.2
+ */
+ public static void setDefaultInterpretErrorHandler (@Nonnull final ICSSInterpretErrorHandler aDefaultErrorHandler)
+ {
+ ValueEnforcer.notNull (aDefaultErrorHandler, "DefaultErrorHandler");
+
+ s_aRWLock.writeLocked ( () -> s_aDefaultInterpretErrorHandler = aDefaultErrorHandler);
+ }
+
/**
* Main reading of the CSS
*
@@ -1112,29 +1143,34 @@ public static CascadingStyleSheet readFromStream (@Nonnull final IHasInputStream
aCharStream.setTabSize (aSettings.getTabSize ());
// Use the default CSS parse error handler if none is provided
- ICSSParseErrorHandler aRealErrorHandler = aSettings.getCustomErrorHandler ();
- if (aRealErrorHandler == null)
- aRealErrorHandler = getDefaultParseErrorHandler ();
+ ICSSParseErrorHandler aRealParseErrorHandler = aSettings.getCustomErrorHandler ();
+ if (aRealParseErrorHandler == null)
+ aRealParseErrorHandler = getDefaultParseErrorHandler ();
// Use the default CSS exception handler if none is provided
- ICSSParseExceptionCallback aRealExceptionHandler = aSettings.getCustomExceptionHandler ();
- if (aRealExceptionHandler == null)
- aRealExceptionHandler = getDefaultParseExceptionHandler ();
+ ICSSParseExceptionCallback aRealParseExceptionHandler = aSettings.getCustomExceptionHandler ();
+ if (aRealParseExceptionHandler == null)
+ aRealParseExceptionHandler = getDefaultParseExceptionHandler ();
final boolean bBrowserCompliantMode = aSettings.isBrowserCompliantMode ();
final CSSNode aNode = _readStyleSheet (aCharStream,
eVersion,
- aRealErrorHandler,
- aRealExceptionHandler,
+ aRealParseErrorHandler,
+ aRealParseExceptionHandler,
bBrowserCompliantMode);
- // Failed to interpret content as CSS?
+ // Failed to parse content as CSS?
if (aNode == null)
return null;
+ // Get the interpret error handler
+ ICSSInterpretErrorHandler aRealInterpretErrorHandler = aSettings.getInterpretErrorHandler ();
+ if (aRealInterpretErrorHandler == null)
+ aRealInterpretErrorHandler = getDefaultInterpretErrorHandler ();
+
// Convert the AST to a domain object
- return CSSHandler.readCascadingStyleSheetFromNode (eVersion, aNode);
+ return CSSHandler.readCascadingStyleSheetFromNode (eVersion, aNode, aRealInterpretErrorHandler);
}
finally
{
@@ -1214,29 +1250,34 @@ public static CascadingStyleSheet readFromReader (@Nonnull final IHasReader aRP,
aCharStream.setTabSize (aSettings.getTabSize ());
// Use the default CSS parse error handler if none is provided
- ICSSParseErrorHandler aRealErrorHandler = aSettings.getCustomErrorHandler ();
- if (aRealErrorHandler == null)
- aRealErrorHandler = getDefaultParseErrorHandler ();
+ ICSSParseErrorHandler aRealParseErrorHandler = aSettings.getCustomErrorHandler ();
+ if (aRealParseErrorHandler == null)
+ aRealParseErrorHandler = getDefaultParseErrorHandler ();
// Use the default CSS exception handler if none is provided
- ICSSParseExceptionCallback aRealExceptionHandler = aSettings.getCustomExceptionHandler ();
- if (aRealExceptionHandler == null)
- aRealExceptionHandler = getDefaultParseExceptionHandler ();
+ ICSSParseExceptionCallback aRealParseExceptionHandler = aSettings.getCustomExceptionHandler ();
+ if (aRealParseExceptionHandler == null)
+ aRealParseExceptionHandler = getDefaultParseExceptionHandler ();
final boolean bBrowserCompliantMode = aSettings.isBrowserCompliantMode ();
final CSSNode aNode = _readStyleSheet (aCharStream,
eVersion,
- aRealErrorHandler,
- aRealExceptionHandler,
+ aRealParseErrorHandler,
+ aRealParseExceptionHandler,
bBrowserCompliantMode);
- // Failed to interpret content as CSS?
+ // Failed to parse content as CSS?
if (aNode == null)
return null;
+ // Get the interpret error handler
+ ICSSInterpretErrorHandler aRealInterpretErrorHandler = aSettings.getInterpretErrorHandler ();
+ if (aRealInterpretErrorHandler == null)
+ aRealInterpretErrorHandler = getDefaultInterpretErrorHandler ();
+
// Convert the AST to a domain object
- return CSSHandler.readCascadingStyleSheetFromNode (eVersion, aNode);
+ return CSSHandler.readCascadingStyleSheetFromNode (eVersion, aNode, aRealInterpretErrorHandler);
}
finally
{
diff --git a/ph-css/src/main/java/com/helger/css/reader/CSSReaderDeclarationList.java b/ph-css/src/main/java/com/helger/css/reader/CSSReaderDeclarationList.java
index 3b358ee5..55b4ed51 100644
--- a/ph-css/src/main/java/com/helger/css/reader/CSSReaderDeclarationList.java
+++ b/ph-css/src/main/java/com/helger/css/reader/CSSReaderDeclarationList.java
@@ -50,7 +50,9 @@
import com.helger.css.parser.ParseException;
import com.helger.css.parser.ParserCSS30;
import com.helger.css.parser.ParserCSS30TokenManager;
+import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
import com.helger.css.reader.errorhandler.ICSSParseErrorHandler;
+import com.helger.css.reader.errorhandler.LoggingCSSInterpretErrorHandler;
import com.helger.css.reader.errorhandler.ThrowingCSSParseErrorHandler;
/**
@@ -74,6 +76,9 @@ public final class CSSReaderDeclarationList
@GuardedBy ("s_aRWLock")
private static ICSSParseExceptionCallback s_aDefaultParseExceptionHandler = new LoggingCSSParseExceptionCallback ();
+ @GuardedBy ("s_aRWLock")
+ private static ICSSInterpretErrorHandler s_aDefaultInterpretErrorHandler = new LoggingCSSInterpretErrorHandler ();
+
@PresentForCodeCoverage
private static final CSSReaderDeclarationList s_aInstance = new CSSReaderDeclarationList ();
@@ -102,9 +107,7 @@ public static ICSSParseErrorHandler getDefaultParseErrorHandler ()
*/
public static void setDefaultParseErrorHandler (@Nullable final ICSSParseErrorHandler aDefaultParseErrorHandler)
{
- s_aRWLock.writeLocked ( () -> {
- s_aDefaultParseErrorHandler = aDefaultParseErrorHandler;
- });
+ s_aRWLock.writeLocked ( () -> s_aDefaultParseErrorHandler = aDefaultParseErrorHandler);
}
/**
@@ -131,9 +134,33 @@ public static void setDefaultParseExceptionHandler (@Nonnull final ICSSParseExce
{
ValueEnforcer.notNull (aDefaultParseExceptionHandler, "DefaultParseExceptionHandler");
- s_aRWLock.writeLocked ( () -> {
- s_aDefaultParseExceptionHandler = aDefaultParseExceptionHandler;
- });
+ s_aRWLock.writeLocked ( () -> s_aDefaultParseExceptionHandler = aDefaultParseExceptionHandler);
+ }
+
+ /**
+ * @return The default interpret error handler to handle interpretation errors
+ * in successfully parsed CSS. Never null
.
+ * @since 5.0.2
+ */
+ @Nonnull
+ public static ICSSInterpretErrorHandler getDefaultInterpretErrorHandler ()
+ {
+ return s_aRWLock.readLocked ( () -> s_aDefaultInterpretErrorHandler);
+ }
+
+ /**
+ * Set the default interpret error handler to handle interpretation errors in
+ * successfully parsed CSS.
+ *
+ * @param aDefaultErrorHandler
+ * The default error handler to be used. May not be null
.
+ * @since 5.0.2
+ */
+ public static void setDefaultInterpretErrorHandler (@Nonnull final ICSSInterpretErrorHandler aDefaultErrorHandler)
+ {
+ ValueEnforcer.notNull (aDefaultErrorHandler, "DefaultErrorHandler");
+
+ s_aRWLock.writeLocked ( () -> s_aDefaultInterpretErrorHandler = aDefaultErrorHandler);
}
/**
@@ -739,23 +766,31 @@ public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reade
final CSSCharStream aCharStream = new CSSCharStream (aReader);
// Use the default CSS parse error handler if none is provided
- ICSSParseErrorHandler aRealErrorHandler = aSettings.getCustomErrorHandler ();
- if (aRealErrorHandler == null)
- aRealErrorHandler = getDefaultParseErrorHandler ();
+ ICSSParseErrorHandler aRealParseErrorHandler = aSettings.getCustomErrorHandler ();
+ if (aRealParseErrorHandler == null)
+ aRealParseErrorHandler = getDefaultParseErrorHandler ();
// Use the default CSS exception handler if none is provided
- ICSSParseExceptionCallback aRealExceptionHandler = aSettings.getCustomExceptionHandler ();
- if (aRealExceptionHandler == null)
- aRealExceptionHandler = getDefaultParseExceptionHandler ();
+ ICSSParseExceptionCallback aRealParseExceptionHandler = aSettings.getCustomExceptionHandler ();
+ if (aRealParseExceptionHandler == null)
+ aRealParseExceptionHandler = getDefaultParseExceptionHandler ();
- final CSSNode aNode = _readStyleDeclaration (aCharStream, eVersion, aRealErrorHandler, aRealExceptionHandler);
+ final CSSNode aNode = _readStyleDeclaration (aCharStream,
+ eVersion,
+ aRealParseErrorHandler,
+ aRealParseExceptionHandler);
- // Failed to interpret content as CSS?
+ // Failed to parse content as CSS?
if (aNode == null)
return null;
+ // Get the interpret error handler
+ ICSSInterpretErrorHandler aRealInterpretErrorHandler = aSettings.getInterpretErrorHandler ();
+ if (aRealInterpretErrorHandler == null)
+ aRealInterpretErrorHandler = getDefaultInterpretErrorHandler ();
+
// Convert the AST to a domain object
- return CSSHandler.readDeclarationListFromNode (eVersion, aNode);
+ return CSSHandler.readDeclarationListFromNode (eVersion, aNode, aRealInterpretErrorHandler);
}
finally
{
diff --git a/ph-css/src/main/java/com/helger/css/reader/CSSReaderSettings.java b/ph-css/src/main/java/com/helger/css/reader/CSSReaderSettings.java
index 1e5e571b..c3a5f5cc 100644
--- a/ph-css/src/main/java/com/helger/css/reader/CSSReaderSettings.java
+++ b/ph-css/src/main/java/com/helger/css/reader/CSSReaderSettings.java
@@ -29,6 +29,7 @@
import com.helger.commons.string.ToStringGenerator;
import com.helger.css.ECSSVersion;
import com.helger.css.handler.ICSSParseExceptionCallback;
+import com.helger.css.reader.errorhandler.ICSSInterpretErrorHandler;
import com.helger.css.reader.errorhandler.ICSSParseErrorHandler;
/**
@@ -50,6 +51,7 @@ public class CSSReaderSettings implements ICloneable
private ICSSParseExceptionCallback m_aCustomExceptionHandler;
private boolean m_bBrowserCompliantMode = DEFAULT_BROWSER_COMPLIANT_MODE;
private int m_nTabSize = DEFAULT_TAB_SIZE;
+ private ICSSInterpretErrorHandler m_aInterpretErrorHandler;
public CSSReaderSettings ()
{}
@@ -63,6 +65,7 @@ public CSSReaderSettings (@Nonnull final CSSReaderSettings aOther)
m_aCustomExceptionHandler = aOther.m_aCustomExceptionHandler;
m_bBrowserCompliantMode = aOther.m_bBrowserCompliantMode;
m_nTabSize = aOther.m_nTabSize;
+ m_aInterpretErrorHandler = aOther.m_aInterpretErrorHandler;
}
/**
@@ -226,6 +229,35 @@ public CSSReaderSettings setTabSize (@Nonnegative final int nTabSize)
return this;
}
+ /**
+ * @return The special error handler to be used to interpret a successfully
+ * parsed CSS. May be null
. If this is null
+ * the default error handler from {@link CSSReader} is used.
+ * @since 5.0.2
+ */
+ @Nullable
+ public ICSSInterpretErrorHandler getInterpretErrorHandler ()
+ {
+ return m_aInterpretErrorHandler;
+ }
+
+ /**
+ * Set a special interpret error handler for handling errors in successfully
+ * parsed CSS.
+ *
+ * @param aInterpretErrorHandler
+ * The special error handler to be used. May be null
to
+ * indicate to use the default error handler from {@link CSSReader}.
+ * @return this for chaining
+ * @since 5.0.2
+ */
+ @Nonnull
+ public CSSReaderSettings setInterpretErrorHandler (@Nullable final ICSSInterpretErrorHandler aInterpretErrorHandler)
+ {
+ m_aInterpretErrorHandler = aInterpretErrorHandler;
+ return this;
+ }
+
@Nonnull
public CSSReaderSettings getClone ()
{
@@ -241,6 +273,7 @@ public String toString ()
.append ("CustomExceptionHandler", m_aCustomExceptionHandler)
.append ("BrowserCompliantMode", m_bBrowserCompliantMode)
.append ("TabSize", m_nTabSize)
+ .append ("InterpretErrorHandler", m_aInterpretErrorHandler)
.toString ();
}
}
diff --git a/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSInterpretErrorHandler.java b/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSInterpretErrorHandler.java
new file mode 100644
index 00000000..57ecdd7e
--- /dev/null
+++ b/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSInterpretErrorHandler.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (C) 2014-2016 Philip Helger (www.helger.com)
+ * philip[at]helger[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.helger.css.reader.errorhandler;
+
+import javax.annotation.Nonnull;
+
+import com.helger.commons.annotation.Nonempty;
+import com.helger.commons.string.ToStringGenerator;
+
+/**
+ * An implementation of {@link ICSSInterpretErrorHandler} that does nothing.
+ *
+ * @author Philip Helger
+ * @since 5.0.2
+ */
+public class DoNothingCSSInterpretErrorHandler implements ICSSInterpretErrorHandler
+{
+ public DoNothingCSSInterpretErrorHandler ()
+ {}
+
+ public void onCSSInterpretationWarning (@Nonnull @Nonempty final String sMessage)
+ {
+ /* really do nothing :) */
+ }
+
+ public void onCSSInterpretationError (@Nonnull @Nonempty final String sMessage)
+ {
+ /* really do nothing :) */
+ }
+
+ @Override
+ public String toString ()
+ {
+ return new ToStringGenerator (this).toString ();
+ }
+}
diff --git a/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSParseErrorHandler.java b/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSParseErrorHandler.java
index 4176d76a..9242bb34 100644
--- a/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSParseErrorHandler.java
+++ b/ph-css/src/main/java/com/helger/css/reader/errorhandler/DoNothingCSSParseErrorHandler.java
@@ -38,21 +38,21 @@ public DoNothingCSSParseErrorHandler ()
public void onCSSParseError (@Nonnull final ParseException aParseEx,
@Nullable final Token aLastSkippedToken) throws ParseException
{
- /* empty */
+ /* really do nothing :) */
}
public void onCSSUnexpectedRule (@Nonnull final Token aCurrentToken,
@Nonnull @Nonempty final String sRule,
@Nonnull @Nonempty final String sMsg) throws ParseException
{
- /* empty */
+ /* really do nothing :) */
}
public void onCSSBrowserCompliantSkip (@Nullable final ParseException ex,
@Nonnull final Token aFromToken,
@Nonnull final Token aToToken) throws ParseException
{
- /* empty */
+ /* really do nothing :) */
}
@Override
diff --git a/ph-css/src/main/java/com/helger/css/reader/errorhandler/ICSSInterpretErrorHandler.java b/ph-css/src/main/java/com/helger/css/reader/errorhandler/ICSSInterpretErrorHandler.java
new file mode 100644
index 00000000..6efc6496
--- /dev/null
+++ b/ph-css/src/main/java/com/helger/css/reader/errorhandler/ICSSInterpretErrorHandler.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (C) 2014-2016 Philip Helger (www.helger.com)
+ * philip[at]helger[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.helger.css.reader.errorhandler;
+
+import javax.annotation.Nonnull;
+
+import com.helger.commons.annotation.Nonempty;
+
+/**
+ * Special CSS error handler that is invoked during interpretation of a parsed
+ * CSS.
+ *
+ * @author Philip Helger
+ * @since 5.0.2
+ */
+public interface ICSSInterpretErrorHandler
+{
+ /**
+ * Called when an interpretation error or warning occurs.
+ *
+ * @param sMessage
+ * The message text of the error.
+ */
+ void onCSSInterpretationWarning (@Nonnull @Nonempty final String sMessage);
+
+ /**
+ * Called when an interpretation error occurs.
+ *
+ * @param sMessage
+ * The message text of the error.
+ */
+ void onCSSInterpretationError (@Nonnull @Nonempty final String sMessage);
+}
diff --git a/ph-css/src/main/java/com/helger/css/reader/errorhandler/LoggingCSSInterpretErrorHandler.java b/ph-css/src/main/java/com/helger/css/reader/errorhandler/LoggingCSSInterpretErrorHandler.java
new file mode 100644
index 00000000..e75c56f3
--- /dev/null
+++ b/ph-css/src/main/java/com/helger/css/reader/errorhandler/LoggingCSSInterpretErrorHandler.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2014-2016 Philip Helger (www.helger.com)
+ * philip[at]helger[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.helger.css.reader.errorhandler;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.helger.commons.annotation.Nonempty;
+import com.helger.commons.string.ToStringGenerator;
+
+/**
+ * A logging implementation of {@link ICSSInterpretErrorHandler}. So in case a
+ * warning or an error occurs, the details are logged to an SLF4J logger.
+ *
+ * @author Philip Helger
+ * @since 5.0.2
+ */
+@Immutable
+public class LoggingCSSInterpretErrorHandler implements ICSSInterpretErrorHandler
+{
+ private static final Logger s_aLogger = LoggerFactory.getLogger (LoggingCSSInterpretErrorHandler.class);
+
+ /**
+ * Default constructor.
+ */
+ public LoggingCSSInterpretErrorHandler ()
+ {}
+
+ public void onCSSInterpretationWarning (@Nonnull @Nonempty final String sMessage)
+ {
+ s_aLogger.warn (sMessage);
+ }
+
+ public void onCSSInterpretationError (@Nonnull @Nonempty final String sMessage)
+ {
+ s_aLogger.error (sMessage);
+ }
+
+ @Override
+ public String toString ()
+ {
+ return new ToStringGenerator (this).toString ();
+ }
+}
diff --git a/ph-css/src/test/java/com/helger/css/parser/ParserCSS30Test.java b/ph-css/src/test/java/com/helger/css/parser/ParserCSS30Test.java
index 93034f4e..f21f13b3 100644
--- a/ph-css/src/test/java/com/helger/css/parser/ParserCSS30Test.java
+++ b/ph-css/src/test/java/com/helger/css/parser/ParserCSS30Test.java
@@ -27,6 +27,7 @@
import com.helger.css.decl.CascadingStyleSheet;
import com.helger.css.decl.ICSSTopLevelRule;
import com.helger.css.handler.CSSHandler;
+import com.helger.css.reader.CSSReader;
/**
* Test class for class {@link ParserCSS30}.
@@ -56,7 +57,9 @@ public void test2 () throws ParseException
final CSSNode aNode = aParser.styleSheet ();
assertNotNull (aNode);
- final CascadingStyleSheet aCSS = CSSHandler.readCascadingStyleSheetFromNode (ECSSVersion.CSS30, aNode);
+ final CascadingStyleSheet aCSS = CSSHandler.readCascadingStyleSheetFromNode (ECSSVersion.CSS30,
+ aNode,
+ CSSReader.getDefaultInterpretErrorHandler ());
assertNotNull (aCSS);
for (final ICSSTopLevelRule aTopLevelRule : aCSS.getAllFontFaceRules ())
diff --git a/ph-css/src/test/java/com/helger/css/supplementary/issues/Issue33Test.java b/ph-css/src/test/java/com/helger/css/supplementary/issues/Issue33Test.java
index 07fdf197..d32c8ea9 100644
--- a/ph-css/src/test/java/com/helger/css/supplementary/issues/Issue33Test.java
+++ b/ph-css/src/test/java/com/helger/css/supplementary/issues/Issue33Test.java
@@ -16,30 +16,40 @@
*/
package com.helger.css.supplementary.issues;
+import static org.junit.Assert.assertEquals;
+
import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.helger.css.ECSSVersion;
import com.helger.css.decl.CascadingStyleSheet;
import com.helger.css.reader.CSSReader;
import com.helger.css.reader.CSSReaderSettings;
+import com.helger.css.reader.errorhandler.DoNothingCSSInterpretErrorHandler;
import com.helger.css.writer.CSSWriter;
import com.helger.css.writer.CSSWriterSettings;
/**
- * Test for issue 26: https://github.com/phax/ph-css/issues/33
+ * Test for issue 33: https://github.com/phax/ph-css/issues/33
*
* @author Philip Helger
*/
public final class Issue33Test
{
+ private static final Logger s_aLogger = LoggerFactory.getLogger (Issue33Test.class);
+
@Test
public void testIssue ()
{
+ // No log message may be issued in this test!
+
final String css = "@media \\0screen\\,screen\\9 {.test {margin-left: 0px}}";
final CSSReaderSettings aSettings = new CSSReaderSettings ().setCSSVersion (ECSSVersion.LATEST)
- .setBrowserCompliantMode (true);
+ .setBrowserCompliantMode (true)
+ .setInterpretErrorHandler (new DoNothingCSSInterpretErrorHandler ());
final CascadingStyleSheet cascadingStyleSheet = CSSReader.readFromStringStream (css, aSettings);
final CSSWriter writer = new CSSWriter (new CSSWriterSettings (ECSSVersion.LATEST, true));
- System.out.println (writer.getCSSAsString (cascadingStyleSheet));
+ assertEquals ("@media \\0screen\\,screen\\9 {.test{margin-left:0}}", writer.getCSSAsString (cascadingStyleSheet));
}
}