/*
 * #%L
 * fujion
 * %%
 * Copyright (C) 2008 - 2018 Regenstrief Institute, Inc.
 * %%
 * 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.
 * 
 * #L%
 */
package org.fujion.page;

import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fujion.common.AbstractCache;
import org.fujion.common.MiscUtil;
import org.fujion.common.StrUtil;
import org.fujion.core.WebUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.context.ServletContextAware;

/**
 * A cache of all compiled page definitions. If a requested page is not in the cache, it will be
 * automatically compiled and added to the cache.
 */
public class PageDefinitionCache extends AbstractCache<String, PageDefinition> implements ServletContextAware, ApplicationListener<ContextRefreshedEvent> {
    
    private static PageDefinitionCache instance = new PageDefinitionCache();
    
    private static Log log = LogFactory.getLog(PageDefinitionCache.class);
    
    private Set<String> precompiled = new LinkedHashSet<>();
    
    private ServletContext servletContext;
    
    public static PageDefinitionCache getInstance() {
        return instance;
    }
    
    private PageDefinitionCache() {
    }
    
    private String normalizeKey(String key) {
        try {
            return WebUtil.getResource(key, servletContext).getURL().toString();
        } catch (IOException e) {
            throw MiscUtil.toUnchecked(e);
        }
    }
    
    public void setPrecompiled(String fsps) {
        setPrecompiled(StrUtil.toList(fsps, ","));
    }
    
    public void setPrecompiled(Collection<String> fsps) {
        precompiled.addAll(fsps);
    }
    
    @Override
    public PageDefinition get(String key) {
        return super.get(normalizeKey(key));
    }
    
    @Override
    public boolean isCached(String key) {
        return super.isCached(normalizeKey(key));
    }
    
    @Override
    protected PageDefinition fetch(String url) {
        try {
            return PageParser.getInstance().parse(url);
        } catch (Exception e) {
            throw MiscUtil.toUnchecked(e);
        }
    }
    
    /**
     * Process FSPs marked for pre-compilation.
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (precompiled != null) {
            Set<String> fsps = precompiled;
            precompiled = null;
            
            for (String url : fsps) {
                url = url.trim();
                
                if (!"fsp".equals(FilenameUtils.getExtension(url))) {
                    url += ".fsp";
                }
                
                try {
                    if (log.isInfoEnabled()) {
                        log.info("Precompiling " + url);
                    }
                    
                    get(url);
                } catch (Exception e) {
                    if (log.isWarnEnabled())
                        log.warn("Error precompiling " + url, e);
                }
            }
        }
        
    }
    
    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
    
}

@@ -262,18 +262,17 @@
 se at%0A *
- 
 %0A
+
  *      
@@ -316,17 +316,16 @@
 E-2.0%0A *
- 
 %0A * Unle
@@ -640,17 +640,16 @@
 ense.%0A *
- 
 %0A * #L%25%0A
@@ -1590,21 +1590,17 @@
 vent%3E %7B%0A
-    
 %0A
+
     priv
@@ -1664,29 +1664,25 @@
 ionCache();%0A
-    
 %0A
+
     private 
@@ -1744,21 +1744,17 @@
 class);%0A
-    
 %0A
+
     priv
@@ -1806,21 +1806,17 @@
 et%3C%3E();%0A
-    
 %0A
+
     priv
@@ -1850,21 +1850,17 @@
 ontext;%0A
-    
 %0A
+
     publ
@@ -1932,29 +1932,25 @@
 ance;%0A    %7D%0A
-    
 %0A
+
     private 
@@ -1975,29 +1975,25 @@
 e() %7B%0A    %7D%0A
-    
 %0A
+
     private 
@@ -2210,29 +2210,25 @@
     %7D%0A    %7D%0A
-    
 %0A
+
     public v
@@ -2314,29 +2314,25 @@
 ,%22));%0A    %7D%0A
-    
 %0A
+
     public v
@@ -2409,37 +2409,33 @@
 ll(fsps);%0A    %7D%0A
-    
 %0A
+
     @Override%0A  
@@ -2519,37 +2519,33 @@
 ey(key));%0A    %7D%0A
-    
 %0A
+
     @Override%0A  
@@ -2636,29 +2636,25 @@
 ey));%0A    %7D%0A
-    
 %0A
+
     @Overrid
@@ -2861,29 +2861,25 @@
     %7D%0A    %7D%0A
-    
 %0A
+
     /**%0A    
@@ -3121,29 +3121,17 @@
 = null;%0A
-            
 %0A
+
         
@@ -3190,24 +3190,25 @@
 url.trim();%0A
+%0A
             
@@ -3203,32 +3203,101 @@
                 
+if (url.isEmpty()) %7B%0A                    continue;%0A                %7D%0A
 %0A               
@@ -3404,33 +3404,17 @@
       %7D%0A
-                
 %0A
+
         
@@ -3557,29 +3557,9 @@
   %7D%0A
-                    
 %0A
+
     
@@ -3668,16 +3668,18 @@
 abled())
+ %7B
 %0A       
@@ -3733,24 +3733,46 @@
  + url, e);%0A
+                    %7D%0A
             
@@ -3805,28 +3805,16 @@
   %7D%0A
-        
 %0A
+
     %7D%0A
-    
 %0A
+
     
@@ -3942,15 +3942,11 @@
 ;%0A    %7D%0A
-    
 %0A%7D%0A

Fix FSP precompilation error.