/*
 * This software is distributed under following license based on modified BSD
 * style license.
 * ----------------------------------------------------------------------
 * 
 * Copyright 2003 The Nimbus Project. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer. 
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE NIMBUS PROJECT ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 * NO EVENT SHALL THE NIMBUS PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of the Nimbus Project.
 */
package jp.ossc.nimbus.service.journal.editor;

import java.util.*;
import javax.servlet.http.Cookie;

import jp.ossc.nimbus.service.journal.EditorFinder;

/**
 * JournalHttpServletResponseWrapperオブジェクトをMapフォーマットするエディタ。<p>
 * 
 * @author M.Takata
 */
public class JournalHttpServletResponseWrapperMapJournalEditorService
 extends ServletResponseMapJournalEditorService
 implements JournalHttpServletResponseWrapperMapJournalEditorServiceMBean{
    
    private static final long serialVersionUID = -5062156173243815339L;
    
    private String[] secretHeaders;
    protected Set<String> secretHeaderSet;
    private String[] enabledHeaders;
    protected Set<String> enabledHeaderSet;
    private String[] disabledHeaders;
    protected Set<String> disabledHeaderSet;
    private String[] secretCookies;
    protected Set<String> secretCookieSet;
    private String[] enabledCookies;
    protected Set<String> enabledCookieSet;
    private String[] disabledCookies;
    protected Set<String> disabledCookieSet;
    
    @Override
    public void setSecretHeaders(String[] names){
        secretHeaders = names;
    }
    
    @Override
    public String[] getSecretHeaders(){
        return secretHeaders;
    }
    
    @Override
    public void setEnabledHeaders(String[] names){
        enabledHeaders = names;
    }
    
    @Override
    public String[] getEnabledHeaders(){
        return enabledHeaders;
    }
    
    @Override
    public void setDisabledHeaders(String[] names){
        disabledHeaders = names;
    }
    
    @Override
    public String[] getDisabledHeaders(){
        return disabledHeaders;
    }
    
    @Override
    public void setSecretCookies(String[] names){
        secretCookies = names;
    }
    
    @Override
    public String[] getSecretCookies(){
        return secretCookies;
    }
    
    @Override
    public void setEnabledCookies(String[] names){
        enabledCookies = names;
    }
    
    @Override
    public String[] getEnabledCookies(){
        return enabledCookies;
    }
    
    @Override
    public void setDisabledCookies(String[] names){
        disabledCookies = names;
    }
    
    @Override
    public String[] getDisabledCookies(){
        return disabledCookies;
    }
    
    @Override
    public void createService() throws Exception{
        super.createService();
        secretHeaderSet = new HashSet<String>();
        enabledHeaderSet = new HashSet<String>();
        disabledHeaderSet = new HashSet<String>();
        secretCookieSet = new HashSet<String>();
        enabledCookieSet = new HashSet<String>();
        disabledCookieSet = new HashSet<String>();
    }
    
    @Override
    public void startService() throws Exception{
        super.startService();
        if(secretHeaders != null){
            for(int i = 0; i < secretHeaders.length; i++){
                secretHeaderSet.add(secretHeaders[i]);
            }
        }
        if(enabledHeaders != null){
            for(int i = 0; i < enabledHeaders.length; i++){
                enabledHeaderSet.add(enabledHeaders[i]);
            }
        }
        if(disabledHeaders != null){
            for(int i = 0; i < disabledHeaders.length; i++){
                disabledHeaderSet.add(disabledHeaders[i]);
            }
        }
        if(secretCookies != null){
            for(int i = 0; i < secretCookies.length; i++){
                secretCookieSet.add(secretCookies[i]);
            }
        }
        if(enabledCookies != null){
            for(int i = 0; i < enabledCookies.length; i++){
                enabledCookieSet.add(enabledCookies[i]);
            }
        }
        if(disabledCookies != null){
            for(int i = 0; i < disabledCookies.length; i++){
                disabledCookieSet.add(disabledCookies[i]);
            }
        }
    }
    
    @Override
    public void stopService() throws Exception{
        super.stopService();
        secretHeaderSet.clear();
        enabledHeaderSet.clear();
        disabledHeaderSet.clear();
        secretCookieSet.clear();
        disabledCookieSet.clear();
    }
    
    @Override
    public void destroyService() throws Exception{
        super.destroyService();
        secretHeaderSet = null;
        enabledHeaderSet = null;
        disabledHeaderSet = null;
        secretCookieSet = null;
        enabledCookieSet = null;
        disabledCookieSet = null;
    }
    
    /**
     * ジャーナルとして与えられたHttpServletRequest型の情報をジャーナルとして出力するMap情報に変換する。<br>
     * 
     * @param finder 適切なJournalEditorを提供するEditorFinder
     * @param key ジャーナルのキー情報
     * @param value ジャーナル情報
     * @return ジャーナルとして出力するMap情報
     */
    @Override
    protected Map<String, Object> toMap(EditorFinder finder, String key, Object value){
        final Map<String, Object> result = super.toMap(finder, key, value);
        
        final JournalHttpServletResponseWrapper response
             = (JournalHttpServletResponseWrapper)value;
        
        makeContentLengthFormat(finder, key, response, result);
        makeContentFormat(finder, key, response, result);
        makeHeadersFormat(finder, key, response, result);
        makeCookiesFormat(finder, key, response, result);
        makeStatusFormat(finder, key, response, result);
        makeStatusMessageFormat(finder, key, response, result);
        makeIsSentErrorFormat(finder, key, response, result);
        makeRedirectLocationFormat(finder, key, response, result);
        
        return result;
    }
    
    protected Map<String, Object> makeContentLengthFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, CONTENT_LENGTH_KEY, new Integer(response.getContentLength()));
        return map;
    }
    
    protected Map<String, Object> makeContentFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, CONTENT_KEY, response.getContent());
        return map;
    }
    
    protected Map<String, Object> makeHeadersFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        if(!isOutputMapKey(HTTP_HEADER_KEY)){
            return map;
        }
        if(isSecretMapKey(HTTP_HEADER_KEY)){
            putMap(map, HTTP_HEADER_KEY, null);
            return map;
        }
        final Iterator<String> headerNames = response.getHeaderNames();
        if(!headerNames.hasNext()){
            return map;
        }
        final Map<String, Object> subMap = new LinkedHashMap<String, Object>();
        while(headerNames.hasNext()){
            final String name = (String)headerNames.next();
            if(!disabledHeaderSet.isEmpty()
                 && disabledHeaderSet.contains(name)){
                continue;
            }
            if(!enabledHeaderSet.isEmpty()
                 && !enabledHeaderSet.contains(name)){
                continue;
            }
            if(secretHeaderSet.contains(name)){
                subMap.put(name, null);
            }else{
                subMap.put(
                    name,
                    makeObjectFormat(finder, key, response.getHeaders(name))
                );
            }
        }
        putMap(map, HTTP_HEADER_KEY, makeObjectFormat(finder, key, subMap));
        return map;
    }
    
    protected Map<String, Object> makeCookiesFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        if(!isOutputMapKey(COOKIE_KEY)){
            return map;
        }
        if(isSecretMapKey(COOKIE_KEY)){
            putMap(map, COOKIE_KEY, null);
            return map;
        }
        final Cookie[] cookies = response.getCookies();
        if(cookies == null || cookies.length == 0){
            return map;
        }
        final Map<String, Object> subMap = new LinkedHashMap<String, Object>();
        for(int i = 0; i < cookies.length; i++){
            final String name = (String)cookies[i].getName();
            if(!disabledCookieSet.isEmpty()
                 && disabledCookieSet.contains(name)){
                continue;
            }
            if(!enabledCookieSet.isEmpty()
                 && !enabledCookieSet.contains(name)){
                continue;
            }
            if(secretCookieSet.contains(name)){
                subMap.put(name, null);
            }else{
                subMap.put(
                    name,
                    makeObjectFormat(finder, key, cookies[i].getValue())
                );
            }
        }
        putMap(map, COOKIE_KEY, makeObjectFormat(finder, key, subMap));
        return map;
    }
    
    protected Map<String, Object> makeStatusFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, STATUS_KEY, new Integer(response.getStatus()));
        return map;
    }
    
    protected Map<String, Object> makeStatusMessageFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, STATUS_MESSAGE_KEY, response.getStatusMessage());
        return map;
    }
    
    protected Map<String, Object> makeIsSentErrorFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, IS_SENT_ERROR_KEY, Boolean.valueOf(response.isSentError()));
        return map;
    }
    
    protected Map<String, Object> makeRedirectLocationFormat(
        EditorFinder finder,
        String key,
        JournalHttpServletResponseWrapper response,
        Map<String, Object> map
    ){
        putMap(map, REDIRECT_LOCATION_KEY, response.getRedirectLocation());
        return map;
    }
}
