Package com.connect_group.thymesheet.impl

Source Code of com.connect_group.thymesheet.impl.ThymesheetPreprocessor

/*
* =============================================================================
*
*   Copyright (c) 2013, Connect Group (http://www.connect-group.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.connect_group.thymesheet.impl;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.SequenceInputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.thymeleaf.Configuration;
import org.thymeleaf.dom.Document;
import org.w3c.css.sac.InputSource;
import org.w3c.dom.css.CSSRuleList;
import org.w3c.dom.css.CSSStyleRule;
import org.w3c.dom.css.CSSStyleSheet;

import com.connect_group.thymesheet.ServletContextURLFactory;
import com.connect_group.thymesheet.ThymesheetLocator;
import com.connect_group.thymesheet.ThymesheetParserPostProcessor;
import com.connect_group.thymesheet.ThymesheetProcessorException;
import com.connect_group.thymesheet.css.selectors.NodeSelectorException;
import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.SACParserCSS3;

public class ThymesheetPreprocessor {
  private final ServletContextURLFactory urlFactory;
  private final ThymesheetLocator thymesheetLocator;
  private final Set<ThymesheetParserPostProcessor> postProcessors;
 
  public ThymesheetPreprocessor() {
    super();
    urlFactory = null;
    thymesheetLocator = null;
    this.postProcessors = Collections.emptySet();
  }
 
  public ThymesheetPreprocessor(ServletContextURLFactory urlFactory, ThymesheetLocator thymesheetLocator, Set<ThymesheetParserPostProcessor> postProcessors) {
    super();
    this.urlFactory = urlFactory;
    this.thymesheetLocator = thymesheetLocator;
   
      if(postProcessors==null) {
        this.postProcessors = Collections.emptySet();
      } else {
        this.postProcessors = postProcessors;
      }

  }
 
 
 
  public void preProcess(String documentName, Document document) throws IOException {
    List<String> filePaths = thymesheetLocator.getThymesheetPaths(document);
    InputStream thymesheetInputStream = getInputStream(filePaths);
    AttributeRuleList attributeRules = getRuleList(thymesheetInputStream);
    ElementRuleList elementRules=extractDOMModifications(attributeRules);
   
    try {
      attributeRules.applyTo(document);
      elementRules.applyTo(document);
    } catch (NodeSelectorException e) {
      throw new IOException("Invalid CSS Selector", e);
    }
    thymesheetLocator.removeThymesheetLinks(document);
    postProcess(documentName, document);
  }
 
  private void postProcess(String documentName, Document document) throws ThymesheetProcessorException {
    try {
      for(ThymesheetParserPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcess(documentName, document);
      }
    } catch(Exception ex) {
      throw new ThymesheetProcessorException("Failed to postprocess document.", ex);
    }
  }

  private ElementRuleList extractDOMModifications(List<CSSStyleRule> ruleList) {
    ElementRuleList modifierRules = new ElementRuleList();
   
    Iterator<CSSStyleRule> it = ruleList.iterator();
    while(it.hasNext()) {
      CSSStyleRule rule = it.next();
     
      PseudoClass pseudoModifier = getDOMModifier(rule.getSelectorText());
      if(pseudoModifier!=null) {
        ElementRule modifierRule = ElementRuleFactory.createElementRule(pseudoModifier, CSSUtil.asMap(rule.getStyle()));
        modifierRules.add(modifierRule);
        it.remove();
      }
    }
   
    return modifierRules;
  }

  protected PseudoClass getDOMModifier(String selectorText) {
   
    PseudoClass pseudoClass = PseudoClass.lastPseudoClassFromSelector(selectorText);
    if(ElementRuleFactory.isDOMModifierPsuedoElement(pseudoClass.getName())) {
      return pseudoClass;
    }
    return null;
  }
 
  AttributeRuleList getRuleList(InputStream stream) throws IOException {
    InputSource source = new InputSource(new InputStreamReader(stream));
        CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
        CSSStyleSheet stylesheet = parser.parseStyleSheet(source, null, null);
        CSSRuleList ruleList = stylesheet.getCssRules();
       
        return new AttributeRuleList(ruleList);
  }

  protected InputStream getInputStream(List<String> filePaths) throws IOException {
    List<InputStream> opened = new ArrayList<InputStream>(filePaths.size());
   
    try {
      openFiles(filePaths, opened);
    } catch (IOException ex) {
      closeInputStreams(opened);
      throw ex;
    }
   
    InputStream is = new SequenceInputStream(Collections.enumeration(opened));
    return is;
  }
 
  private void closeInputStreams(Collection<InputStream> opened) {
    for(InputStream is : opened) {
      try {
        is.close();
      } catch(IOException ix) {}
    }
  }
 
  protected void openFiles(List<String> filePaths, List<InputStream> opened) throws FileNotFoundException {
    for(String filePath : filePaths) {
      InputStream stream;
      if(isClassPath(filePath)) {
        stream = getClass().getResourceAsStream(fixClassPath(filePath));
      } else {
        try {
          stream = getFileFromWebapp(filePath);
        } catch (MalformedURLException e) {
          throw new FileNotFoundException("Unable to open " + filePath + " - " + e.getMessage());
        } catch (IOException e) {
          throw new FileNotFoundException("Unable to open " + filePath + " - " + e.getMessage());
        }

      }
     
     
     
      if(stream==null) {
        throw new FileNotFoundException("Thymesheet file \""+filePath+"\" not found.");
      }
     
      opened.add(stream);
    }
  }

  private String fixClassPath(String filePath) {
    return filePath.replace("classpath:", "");
  }

  private boolean isClassPath(String filePath) {
    return urlFactory == null || filePath.startsWith("classpath:");
  }
 
  private InputStream getFileFromWebapp(String filepath) throws IOException {
    URL thymesheetUrl = urlFactory.getURL(filepath);
    if(thymesheetUrl==null) {
      throw new FileNotFoundException("File \"" + filepath + "\" not found.");
    }
    return  thymesheetUrl.openStream();
  }


}
TOP

Related Classes of com.connect_group.thymesheet.impl.ThymesheetPreprocessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.