All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.helger.css.reader.CSSReaderDeclarationList Maven / Gradle / Ivy

There is a newer version: 7.0.4
Show newest version
/**
 * 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;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.WillClose;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.Immutable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.PresentForCodeCoverage;
import com.helger.commons.concurrent.SimpleReadWriteLock;
import com.helger.commons.io.IHasInputStream;
import com.helger.commons.io.resource.FileSystemResource;
import com.helger.commons.io.resource.IReadableResource;
import com.helger.commons.io.stream.NonBlockingStringReader;
import com.helger.commons.io.stream.StreamHelper;
import com.helger.css.ECSSVersion;
import com.helger.css.decl.CSSDeclarationList;
import com.helger.css.handler.CSSHandler;
import com.helger.css.handler.DoNothingCSSParseExceptionCallback;
import com.helger.css.handler.ICSSParseExceptionCallback;
import com.helger.css.handler.LoggingCSSParseExceptionCallback;
import com.helger.css.parser.CSSCharStream;
import com.helger.css.parser.CSSNode;
import com.helger.css.parser.CharStream;
import com.helger.css.parser.ParseException;
import com.helger.css.parser.ParserCSS30;
import com.helger.css.parser.ParserCSS30TokenManager;
import com.helger.css.reader.errorhandler.ICSSParseErrorHandler;
import com.helger.css.reader.errorhandler.ThrowingCSSParseErrorHandler;

/**
 * This is the central user class for reading and parsing partial CSS from
 * different sources. This class reads CSS style declarations as used in HTML
 * <style> attributes only.
 *
 * @author Philip Helger
 */
@Immutable
public final class CSSReaderDeclarationList
{
  private static final Logger s_aLogger = LoggerFactory.getLogger (CSSReaderDeclarationList.class);
  private static final SimpleReadWriteLock s_aRWLock = new SimpleReadWriteLock ();

  // Use the ThrowingCSSParseErrorHandler for maximum backward compatibility
  @GuardedBy ("s_aRWLock")
  private static ICSSParseErrorHandler s_aDefaultParseErrorHandler = new ThrowingCSSParseErrorHandler ();

  // Use the LoggingCSSParseExceptionHandler for maximum backward compatibility
  @GuardedBy ("s_aRWLock")
  private static ICSSParseExceptionCallback s_aDefaultParseExceptionHandler = new LoggingCSSParseExceptionCallback ();

  @PresentForCodeCoverage
  private static final CSSReaderDeclarationList s_aInstance = new CSSReaderDeclarationList ();

  private CSSReaderDeclarationList ()
  {}

  /**
   * @return The default CSS parse error handler. May be null. For
   *         backwards compatibility reasons this is be default an instance of
   *         {@link ThrowingCSSParseErrorHandler}.
   * @since 3.7.4
   */
  @Nullable
  public static ICSSParseErrorHandler getDefaultParseErrorHandler ()
  {
    return s_aRWLock.readLocked ( () -> s_aDefaultParseErrorHandler);
  }

  /**
   * Set the default CSS parse error handler (for recoverable errors).
   *
   * @param aDefaultParseErrorHandler
   *        The new default error handler to be used. May be null
   *        to indicate that no special error handler should be used.
   * @since 3.7.4
   */
  public static void setDefaultParseErrorHandler (@Nullable final ICSSParseErrorHandler aDefaultParseErrorHandler)
  {
    s_aRWLock.writeLocked ( () -> {
      s_aDefaultParseErrorHandler = aDefaultParseErrorHandler;
    });
  }

  /**
   * @return The default CSS parse exception handler. May not be
   *         null. For backwards compatibility reasons this is be
   *         default an instance of {@link LoggingCSSParseExceptionCallback}.
   * @since 3.7.4
   */
  @Nonnull
  public static ICSSParseExceptionCallback getDefaultParseExceptionHandler ()
  {
    return s_aRWLock.readLocked ( () -> s_aDefaultParseExceptionHandler);
  }

  /**
   * Set the default CSS parse exception handler (for unrecoverable errors).
   *
   * @param aDefaultParseExceptionHandler
   *        The new default exception handler to be used. May not be
   *        null.
   * @since 3.7.4
   */
  public static void setDefaultParseExceptionHandler (@Nonnull final ICSSParseExceptionCallback aDefaultParseExceptionHandler)
  {
    ValueEnforcer.notNull (aDefaultParseExceptionHandler, "DefaultParseExceptionHandler");

    s_aRWLock.writeLocked ( () -> {
      s_aDefaultParseExceptionHandler = aDefaultParseExceptionHandler;
    });
  }

  /**
   * Main reading of the CSS
   *
   * @param aCharStream
   *        The stream to read from. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        A custom handler for recoverable errors. May be null.
   * @param aCustomExceptionHandler
   *        A custom handler for unrecoverable errors. May not be
   *        null.
   * @return null if parsing failed with an unrecoverable error
   *         (and no throwing exception handler is used), or null
   *         if a recoverable error occurred and no
   *         {@link com.helger.css.reader.errorhandler.ThrowingCSSParseErrorHandler}
   *         was used or non-null if parsing succeeded.
   */
  @Nullable
  private static CSSNode _readStyleDeclaration (@Nonnull final CharStream aCharStream,
                                                @Nonnull final ECSSVersion eVersion,
                                                @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                @Nonnull final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    switch (eVersion)
    {
      case CSS21:
      case CSS30:
      {
        final ParserCSS30TokenManager aTokenHdl = new ParserCSS30TokenManager (aCharStream);
        final ParserCSS30 aParser = new ParserCSS30 (aTokenHdl);
        aParser.setCustomErrorHandler (aCustomErrorHandler);
        try
        {
          // Main parsing
          return aParser.styleDeclarationList ();
        }
        catch (final ParseException ex)
        {
          // Unrecoverable error
          aCustomExceptionHandler.onException (ex);
          return null;
        }
      }
      default:
        throw new IllegalArgumentException ("Unsupported CSS version " + eVersion);
    }
  }

  /**
   * Check if the passed CSS file can be parsed without error
   *
   * @param aFile
   *        The file to be parsed. May not be null.
   * @param aCharset
   *        The charset to be used for reading the CSS file. May not be
   *        null.
   * @param eVersion
   *        The CSS version to be used for scanning. May not be
   *        null.
   * @return true if the file can be parsed without error,
   *         false if not
   */
  public static boolean isValidCSS (@Nonnull final File aFile,
                                    @Nonnull final Charset aCharset,
                                    @Nonnull final ECSSVersion eVersion)
  {
    return isValidCSS (new FileSystemResource (aFile), aCharset, eVersion);
  }

  /**
   * Check if the passed CSS resource can be parsed without error
   *
   * @param aRes
   *        The resource to be parsed. May not be null.
   * @param aCharset
   *        The charset to be used for reading the CSS file. May not be
   *        null.
   * @param eVersion
   *        The CSS version to be used for scanning. May not be
   *        null.
   * @return true if the file can be parsed without error,
   *         false if not
   */
  public static boolean isValidCSS (@Nonnull final IReadableResource aRes,
                                    @Nonnull final Charset aCharset,
                                    @Nonnull final ECSSVersion eVersion)
  {
    ValueEnforcer.notNull (aRes, "Resource");
    ValueEnforcer.notNull (aCharset, "Charset");
    ValueEnforcer.notNull (eVersion, "Version");

    final Reader aReader = aRes.getReader (aCharset);
    if (aReader == null)
    {
      s_aLogger.warn ("Failed to open CSS reader " + aRes);
      return false;
    }
    return isValidCSS (aReader, eVersion);
  }

  /**
   * Check if the passed input stream can be resembled to valid CSS content.
   * This is accomplished by fully parsing the CSS file each time the method is
   * called. This is similar to calling
   * {@link #readFromStream(IHasInputStream,Charset, ECSSVersion)} and checking
   * for a non-null result.
   *
   * @param aIS
   *        The input stream to use. Is automatically closed. May not be
   *        null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return true if the CSS is valid according to the version,
   *         false if not
   */
  public static boolean isValidCSS (@Nonnull @WillClose final InputStream aIS,
                                    @Nonnull final Charset aCharset,
                                    @Nonnull final ECSSVersion eVersion)
  {
    ValueEnforcer.notNull (aIS, "InputStream");
    ValueEnforcer.notNull (aCharset, "Charset");

    return isValidCSS (StreamHelper.createReader (aIS, aCharset), eVersion);
  }

  /**
   * Check if the passed String can be resembled to valid CSS content. This is
   * accomplished by fully parsing the CSS file each time the method is called.
   * This is similar to calling {@link #readFromString(String, ECSSVersion)} and
   * checking for a non-null result.
   *
   * @param sCSS
   *        The CSS string to scan. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return true if the CSS is valid according to the version,
   *         false if not
   */
  public static boolean isValidCSS (@Nonnull final String sCSS, @Nonnull final ECSSVersion eVersion)
  {
    ValueEnforcer.notNull (sCSS, "CSS");

    return isValidCSS (new NonBlockingStringReader (sCSS), eVersion);
  }

  /**
   * Check if the passed reader can be resembled to valid CSS content. This is
   * accomplished by fully parsing the CSS each time the method is called. This
   * is similar to calling
   * {@link #readFromStream(IHasInputStream, Charset, ECSSVersion)} and checking
   * for a non-null result.
   *
   * @param aReader
   *        The reader to use. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return true if the CSS is valid according to the version,
   *         false if not
   */
  public static boolean isValidCSS (@Nonnull @WillClose final Reader aReader, @Nonnull final ECSSVersion eVersion)
  {
    ValueEnforcer.notNull (aReader, "Reader");
    ValueEnforcer.notNull (eVersion, "Version");

    try
    {
      final CSSCharStream aCharStream = new CSSCharStream (aReader);
      final CSSNode aNode = _readStyleDeclaration (aCharStream,
                                                   eVersion,
                                                   getDefaultParseErrorHandler (),
                                                   new DoNothingCSSParseExceptionCallback ());
      return aNode != null;
    }
    finally
    {
      StreamHelper.close (aReader);
    }
  }

  @Nullable
  public static CSSDeclarationList readFromString (@Nonnull final String sCSS, @Nonnull final ECSSVersion eVersion)
  {
    return readFromReader (new NonBlockingStringReader (sCSS), new CSSReaderSettings ().setCSSVersion (eVersion));
  }

  @Nullable
  public static CSSDeclarationList readFromString (@Nonnull final String sCSS,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler)
  {
    return readFromReader (new NonBlockingStringReader (sCSS),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler));
  }

  @Nullable
  public static CSSDeclarationList readFromString (@Nonnull final String sCSS,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (new NonBlockingStringReader (sCSS),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  @Nullable
  public static CSSDeclarationList readFromString (@Nonnull final String sCSS,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (new NonBlockingStringReader (sCSS),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  @Nullable
  public static CSSDeclarationList readFromFile (@Nonnull final File aFile,
                                                 @Nonnull final Charset aCharset,
                                                 @Nonnull final ECSSVersion eVersion)
  {
    return readFromReader (new FileSystemResource (aFile).getReader (aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion));
  }

  @Nullable
  public static CSSDeclarationList readFromFile (@Nonnull final File aFile,
                                                 @Nonnull final Charset aCharset,
                                                 @Nonnull final ECSSVersion eVersion,
                                                 @Nullable final ICSSParseErrorHandler aCustomErrorHandler)
  {
    return readFromReader (new FileSystemResource (aFile).getReader (aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler));
  }

  @Nullable
  public static CSSDeclarationList readFromFile (@Nonnull final File aFile,
                                                 @Nonnull final Charset aCharset,
                                                 @Nonnull final ECSSVersion eVersion,
                                                 @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (new FileSystemResource (aFile).getReader (aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  @Nullable
  public static CSSDeclarationList readFromFile (@Nonnull final File aFile,
                                                 @Nonnull final Charset aCharset,
                                                 @Nonnull final ECSSVersion eVersion,
                                                 @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                 @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (new FileSystemResource (aFile).getReader (aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link IHasInputStream}.
   *
   * @param aISP
   *        The input stream provider to use. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull final IHasInputStream aISP,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion)
  {
    return readFromStream (aISP, aCharset, eVersion, null, null);
  }

  /**
   * Read the CSS from the passed {@link IHasInputStream}.
   *
   * @param aISP
   *        The input stream provider to use. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull final IHasInputStream aISP,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler)
  {
    return readFromStream (aISP, aCharset, eVersion, aCustomErrorHandler, null);
  }

  /**
   * Read the CSS from the passed {@link IHasInputStream}.
   *
   * @param aISP
   *        The input stream provider to use. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull final IHasInputStream aISP,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromStream (aISP, aCharset, eVersion, null, aCustomExceptionHandler);
  }

  /**
   * Read the CSS from the passed {@link IHasInputStream}.
   *
   * @param aISP
   *        The input stream provider to use. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull final IHasInputStream aISP,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    ValueEnforcer.notNull (aISP, "InputStreamProvider");

    final InputStream aIS = aISP.getInputStream ();
    if (aIS == null)
      return null;
    return readFromReader (StreamHelper.createReader (aIS, aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link InputStream}.
   *
   * @param aIS
   *        The input stream to use. Will be closed automatically after reading
   *        - independent of success or error. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   * @since 3.7.4
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull @WillClose final InputStream aIS,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion)
  {
    return readFromReader (StreamHelper.createReader (aIS, aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion));
  }

  /**
   * Read the CSS from the passed {@link InputStream}.
   *
   * @param aIS
   *        The input stream to use. Will be closed automatically after reading
   *        - independent of success or error. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   * @since 3.7.4
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull @WillClose final InputStream aIS,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler)
  {
    return readFromReader (StreamHelper.createReader (aIS, aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler));
  }

  /**
   * Read the CSS from the passed {@link InputStream}.
   *
   * @param aIS
   *        The input stream to use. Will be closed automatically after reading
   *        - independent of success or error. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   * @since 3.7.4
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull @WillClose final InputStream aIS,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (StreamHelper.createReader (aIS, aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link InputStream}.
   *
   * @param aIS
   *        The input stream to use. Will be closed automatically after reading
   *        - independent of success or error. May not be null.
   * @param aCharset
   *        The charset to be used. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   * @since 3.7.4
   */
  @Nullable
  public static CSSDeclarationList readFromStream (@Nonnull @WillClose final InputStream aIS,
                                                   @Nonnull final Charset aCharset,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    ValueEnforcer.notNull (aIS, "InputStream");

    return readFromReader (StreamHelper.createReader (aIS, aCharset),
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link Reader}.
   *
   * @param aReader
   *        The reader to use. Will be closed automatically after reading -
   *        independent of success or error. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reader aReader,
                                                   @Nonnull final ECSSVersion eVersion)
  {
    return readFromReader (aReader, new CSSReaderSettings ().setCSSVersion (eVersion));
  }

  /**
   * Read the CSS from the passed {@link Reader}.
   *
   * @param aReader
   *        The reader to use. Will be closed automatically after reading -
   *        independent of success or error. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reader aReader,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler)
  {
    return readFromReader (aReader,
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler));
  }

  /**
   * Read the CSS from the passed {@link Reader}.
   *
   * @param aReader
   *        The reader to use. Will be closed automatically after reading -
   *        independent of success or error. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reader aReader,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (aReader,
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link Reader}.
   *
   * @param aReader
   *        The reader to use. Will be closed automatically after reading -
   *        independent of success or error. May not be null.
   * @param eVersion
   *        The CSS version to use. May not be null.
   * @param aCustomErrorHandler
   *        An optional custom error handler that can be used to collect the
   *        recoverable parsing errors. May be null.
   * @param aCustomExceptionHandler
   *        An optional custom exception handler that can be used to collect the
   *        unrecoverable parsing errors. May be null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   */
  @Nullable
  public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reader aReader,
                                                   @Nonnull final ECSSVersion eVersion,
                                                   @Nullable final ICSSParseErrorHandler aCustomErrorHandler,
                                                   @Nullable final ICSSParseExceptionCallback aCustomExceptionHandler)
  {
    return readFromReader (aReader,
                           new CSSReaderSettings ().setCSSVersion (eVersion)
                                                   .setCustomErrorHandler (aCustomErrorHandler)
                                                   .setCustomExceptionHandler (aCustomExceptionHandler));
  }

  /**
   * Read the CSS from the passed {@link Reader}.
   *
   * @param aReader
   *        The reader to use. Will be closed automatically after reading -
   *        independent of success or error. May not be null.
   * @param aSettings
   *        The settings to be used for reading the CSS. May not be
   *        null.
   * @return null if reading failed, the CSS declarations
   *         otherwise.
   * @since 3.8.2
   */
  @Nullable
  public static CSSDeclarationList readFromReader (@Nonnull @WillClose final Reader aReader,
                                                   @Nonnull final CSSReaderSettings aSettings)
  {
    ValueEnforcer.notNull (aReader, "Reader");
    ValueEnforcer.notNull (aSettings, "Settings");

    final ECSSVersion eVersion = aSettings.getCSSVersion ();
    try
    {
      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 ();

      // Use the default CSS exception handler if none is provided
      ICSSParseExceptionCallback aRealExceptionHandler = aSettings.getCustomExceptionHandler ();
      if (aRealExceptionHandler == null)
        aRealExceptionHandler = getDefaultParseExceptionHandler ();

      final CSSNode aNode = _readStyleDeclaration (aCharStream, eVersion, aRealErrorHandler, aRealExceptionHandler);

      // Failed to interpret content as CSS?
      if (aNode == null)
        return null;

      // Convert the AST to a domain object
      return CSSHandler.readDeclarationListFromNode (eVersion, aNode);
    }
    finally
    {
      StreamHelper.close (aReader);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy