/*
 *  Copyright 2015 the original author or authors. 
 *  @https://github.com/scouter-project/scouter
 *
 *  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 scouter.client.stack.base;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;

import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;

import scouter.client.Images;
import scouter.client.PerspectiveStackAnalyzer;
import scouter.client.stack.config.ParserConfig;
import scouter.client.stack.config.ParserConfigReader;
import scouter.client.stack.config.XMLReader;
import scouter.client.stack.data.StackAnalyzedInfo;
import scouter.client.stack.data.StackAnalyzedValue;
import scouter.client.stack.data.StackAnalyzedValueComp;
import scouter.client.stack.data.StackFileInfo;
import scouter.client.stack.data.StackParser;
import scouter.client.stack.data.UniqueStackValue;
import scouter.client.stack.utils.HtmlUtils;
import scouter.client.stack.utils.ResourceUtils;
import scouter.client.stack.utils.StringUtils;
import scouter.client.stack.utils.ValueObject;
import scouter.client.stack.views.StackAnalyzerView;

public class MainProcessor{
	static private MainProcessor m_mainProcessor = null;
	
	private StackAnalyzerView m_stackAnalyzerView = null;
	private Composite m_parentComposite = null;
	
    private boolean m_isExcludeStack = true;
    private boolean m_isRemoveLine = false;
    private boolean m_isInerPercent = false;
    private boolean m_isSortByFunction = false;
    private boolean m_isSimpleDumpTimeList = true;
    private boolean m_isDefaultConfiguration = false;
    private boolean m_isAnalyzeAllThreads = false;
    
	static {
		m_mainProcessor = new MainProcessor();
	}
	
	static public MainProcessor instance(){
		return m_mainProcessor;
	}

	public StackAnalyzerView getStackAnalyzerView() {
		return m_stackAnalyzerView;
	}
	
	public void setStackAnalyzerView(StackAnalyzerView stackAnalyzerView) {
		m_stackAnalyzerView = stackAnalyzerView;
	}
	
	public void setParentComposite(Composite parent){
		m_parentComposite = parent;
	}

	public Composite getParentComposite(){
		return m_parentComposite;
	}	
		
	public boolean isExcludeStack(){
		return m_isExcludeStack;
	}
	
	public void setExcludeStack(boolean value) {
		m_isExcludeStack = value;
	}
	
	public boolean isRemoveLine(){
		return m_isRemoveLine;
	}

	public void setRemoveLine(boolean value) {
		m_isRemoveLine = value;
	}
	
	public boolean isInerPercent(){
		return m_isInerPercent;
	}

	public void setInerPercent(boolean value) {
		m_isInerPercent = value;
	}
	
	public boolean isSortByFunction(){
		return m_isSortByFunction;
	}

	public void setSortByFunction(boolean value) {
		m_isSortByFunction = value;
	}
	
	public boolean isSimpleDumpTimeList(){
		return m_isSimpleDumpTimeList ;
	}

	public void setSimpleDumpTimeList(boolean value) {
		m_isSimpleDumpTimeList = value;
	}
	
	public boolean isDefaultConfiguration(){
		return m_isDefaultConfiguration;
	}

	public void setDefaultConfiguration(boolean value) {
		m_isDefaultConfiguration = value;
	}
	
	public boolean isAnalyzeAllThreads(){
		return m_isAnalyzeAllThreads;
	}
	
	public void setAnalyzeAllThread(boolean value){
		m_isAnalyzeAllThreads = value;
	}
	
	public void processMenu(String menuName){
        System.out.println("Selected:" + menuName);
        if ( menuName.substring(1, 3).equals(":\\") ) {
        //    openFiles(new File[] { new File(menuName) }, true);
        } else if ( "Open Stack Log".equals(menuName) ) {  	
            chooseStackFile();
        } else if ( "Open Analyzed Stack Log".equals(menuName) ) {
            openAnalyzedInfo();
        } else if ( "Close All".equals(menuName) ) {
            closeStackAllFileInfo();
        } else if ( "Select Parser Configuration".equals(menuName) ) {
            selectCurrentParserConfig();
        } else if ( "Manual Performance Tree(Ascending)".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.PERFORMANCE_TREE, true);
        } else if ( "Manual Performance Tree(Descending)".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.PERFORMANCE_TREE, false);
        } else if ( "Manual Service Call".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.SERVICE_CALL, true);
        } else if ( "Manual Thread Stack (max 20000 lines)".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.THREAD_STACK, true);
        } else if ( "Manual Stack Analyze(Include)".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.FILTER_ANALYZER, true);
        } else if ( "Manual Stack Analyze(Exclude)".equals(menuName) ) {
            createManualJob(FilterInputDialog.TASK.FILTER_ANALYZER, false);
            // Main Tree Popup menu
        } else if ( "Performance Tree".equals(menuName) ) {
            createMainPerformance();
        } else if ( "Close".equals(menuName) ) {
            closeStackFileInfo();
        } else if ( "Reanalyze".equals(menuName) ) {
            reanalyzeStackFileInfo();
        } else if ( "View Raw Index File".equals(menuName) ) {
            viewRawIndexFile();
            // Main Table Popup menu
        }  else if ( "Performance Tree(Ascending)".equals(menuName) ) {
            createAnalyzedPerformance(true);
        } else if ( "Performance Tree(Descending)".equals(menuName) ) {
            createAnalyzedPerformance(false);
        } else if ( "View Thread Stack (max 20000 lines)".equals(menuName)) {
            viewThreadStack();
        } else if ( "View Service Call".equals(menuName) ) {
            viewServiceCall();
        } else if ( "Filter Stack Analyze".equals(menuName) ) {
            analyzeFilterStack(null);
        } else if ( "Copy Function".equals(menuName) ) {
            copyFunctionName();
        }
    }

   private void chooseStackFile() {
       PreferenceManager prefManager = PreferenceManager.get();

       String fileName = ResourceUtils.selectFileDialog(m_parentComposite, "Stack Log File", new String [] {"Stack Log Files", "All Files"}, new String [] {"*.log;*.txt;*.gz;*.stack", "*.*"});

       if(fileName == null){
    	   return;
       }
    	
       File file = new File(fileName);
       prefManager.setSelectedPath(file.getParentFile());
       openFile(file, false);
   }

   private ParserConfig selectAdoptiveParserConfig(){
       PreferenceManager prefManager = PreferenceManager.get();
       String configFile = prefManager.getCurrentParserConfig();
       if(m_isDefaultConfiguration){
   		configFile = XMLReader.DEFAULT_XMLCONFIG;        	
       }
       
       if (configFile == null ) {
			MessageBox messageBox = new MessageBox(m_parentComposite.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.APPLICATION_MODAL);
			messageBox.setText("Check Setting selection");
			messageBox.setMessage("The configuration file is not selected.\r\nDo you want to use the default configuration?");
			int result = messageBox.open();
			if(result == SWT.YES){
				configFile = XMLReader.DEFAULT_XMLCONFIG;
			}else{
			        configFile = selectCurrentParserConfig();
			        if ( configFile == null ) {
			            throw new RuntimeException("Parser config file is not selected!");
			        }
			}
       }

       ParserConfigReader reader = new ParserConfigReader(configFile);
       return reader.read();	   
   }
   
   private void addProcessedStack(StackFileInfo stackFileInfo){
       if ( stackFileInfo == null ){
    	   return;
       }
       addMainTree(stackFileInfo);
       displayContent(null);	   
   }
   
   private void openContents( String contents) {
	   ParserConfig config = selectAdoptiveParserConfig();
       StackFileInfo stackFileInfo = processStackContents(contents, config, null, false, true);       
       addProcessedStack(stackFileInfo);	   
   }
   
   private void openFile( File file, boolean isRecent ) {
	   ParserConfig config = selectAdoptiveParserConfig();
       StackFileInfo stackFileInfo = processStackFile(file.getAbsolutePath(), config, null, isRecent, true);       
       addProcessedStack(stackFileInfo);
   }
   
	private void openAnalyzedInfo() {
		ArrayList<String> list = new ArrayList<String>();
		list.add(StackParser.INFO_EXTENSION);
		String filename = ResourceUtils.selectFileDialog(m_parentComposite, "Analyzed Info File", new String [] {"Stack Analyzed Files", "All Files"}, new String [] {"*.info", "*.*"});
		if ( filename == null )
			return;

		openAnalyzedFile(filename);
	} 

	private void openAnalyzedFile( String filename ) {
		StackFileInfo fileInfo = StackParser.loadAnalyzedInfo(filename);
		addProcessedStack(fileInfo);
	}
	
	private StackFileInfo processStackContents( String contents, ParserConfig config, String filter, boolean isRecent, boolean isInclude ) {
		StackFileInfo stackFileInfo = new StackFileInfo("Stacks");
		return processStackContents(contents, stackFileInfo, config, filter, isRecent, isInclude);
	}
	
	private StackFileInfo processStackFile( String stackFilename, ParserConfig config, String filter, boolean isRecent, boolean isInclude ) {
		StackFileInfo stackFileInfo = new StackFileInfo(stackFilename);
		return processStackFile(stackFileInfo, config, filter, isRecent, isInclude);
	}	
   
	private StackFileInfo postSTackFile(StackFileInfo stackFileInfo, ParserConfig config, String filter, boolean isRecent){
        if ( stackFileInfo.getTotalWorkingCount() <= 0 ) {
        	MessageBox messageBox = new MessageBox(m_parentComposite.getShell(), SWT.ICON_ERROR | SWT.YES | SWT.APPLICATION_MODAL);
        	messageBox.setText("File open error");
        	messageBox.setMessage(new StringBuilder(200).append("A working thread is not exists in ").append(stackFileInfo.getFilename()).append(". configure a ").append(config.getConfigFilename()).append(". ").toString());
        	messageBox.open();
            return null;
        }

        if ( !isRecent){
    	    PreferenceManager prefManager = PreferenceManager.get();
        	if(filter == null ) {
        		prefManager.addToStackFiles(stackFileInfo.getFilename());
        	}
        	prefManager.addToAnalyzedStackFiles(stackFileInfo.getFilename());
        }
        return stackFileInfo;
	}
	
	private StackFileInfo processStackContents(String contents, StackFileInfo stackFileInfo, ParserConfig config, String filter, boolean isRecent, boolean isInclude ) {	
	    try {
	        StackParser parser = StackParser.getParser(config, filter, isInclude);
	        parser.setStackContents(contents);
	        parser.analyze(stackFileInfo);
	        stackFileInfo = postSTackFile(stackFileInfo,config, filter, isRecent);
	    } catch ( RuntimeException ex ) {
	        StackParser.removeAllAnalyzedFile(stackFileInfo);
	        throw ex;
	    }
	    return stackFileInfo;
	}
	
	private StackFileInfo processStackFile( StackFileInfo stackFileInfo, ParserConfig config, String filter, boolean isRecent, boolean isInclude ) {	
	    try {
	        StackParser parser = StackParser.getParser(config, filter, isInclude);
	        parser.analyze(stackFileInfo);
	        stackFileInfo = postSTackFile(stackFileInfo,config, filter, isRecent);
	    } catch ( RuntimeException ex ) {
	        StackParser.removeAllAnalyzedFile(stackFileInfo);
	        throw ex;
	    }
	    return stackFileInfo;
	}

    private String selectCurrentParserConfig() {
    	String fileName = ResourceUtils.selectFileDialog(m_parentComposite, "XML Parser Configuration", new String [] {"XML config", "All Files"}, new String [] {"*.xml", "*.*"});
    	if(fileName != null){
    		PreferenceManager.get().setCurrentParserConfig(fileName);
    		displayContent(null);
    	}
    	return fileName;
    }
    
    public Browser getBrowser(){
    	if(m_stackAnalyzerView == null)
    		return null;
    	
    	return m_stackAnalyzerView.getBrowser();
    }
    
    
    public Tree getMainTree(){
    	if(m_stackAnalyzerView == null)
    		return null;
    	
    	return m_stackAnalyzerView.getMainTree();
    }
    
    public Table getTable(){
    	if(m_stackAnalyzerView == null)
    		return null;
    	
    	return m_stackAnalyzerView.getTable();
    }
    
    public void displayContent( String textHtml ) {
    	Browser browser = getBrowser();
        if ( textHtml != null ) {
        	browser.setText(textHtml);
        } else {
        	browser.setText(HtmlUtils.getDefaultBody());
        }
    }
    
    private void addMainTree( StackFileInfo stackFileInfo ) {
    	Tree tree = getMainTree();
    	TreeItem item = new TreeItem(tree, SWT.NONE);
    	item.setText(stackFileInfo.toTreeInfo());
    	item.setImage(Images.thread);
    	item.setData(stackFileInfo);
    	addMainTreeSubItem(item,stackFileInfo.getStackAnalyzedInfoList());
    	item.setExpanded(true);
    }
    
    private void addMainTreeSubItem(TreeItem parent, ArrayList<StackAnalyzedInfo> list){
    	TreeItem subItem;
    	for(StackAnalyzedInfo info : list){
    	   	subItem = new TreeItem(parent, SWT.NONE);
    	   	subItem.setText(info.toTreeInfo());	
    	   	subItem.setImage(Images.grid);
    	   	subItem.setData(info);
    	}    	
    }
        
    public void setTable(StackAnalyzedInfo stackAnalyzedInfo){
    	clearTable();
    	Table table = getTable();
    	if(stackAnalyzedInfo == null){
    		return;
    	}
    	ArrayList<StackAnalyzedValue> list = null;
        if ( m_isSortByFunction ) {
        	list = StackAnalyzedValueComp.sortClone(stackAnalyzedInfo.getAnalyzedList(), false);
        }else{
        	list = stackAnalyzedInfo.getAnalyzedList();
        }
        
        TableItem item;
    	for(StackAnalyzedValue value : list){
    		item = new TableItem(table, SWT.BORDER);
    		item.setText(value.toTableInfo());
    		if(value instanceof UniqueStackValue){
    			item.setData(((UniqueStackValue)value).getStack());
    		}
    	} 	
    }
    
    private void closeStackAllFileInfo() {
    	Tree tree = this.getMainTree();
        if ( tree != null ){
        	tree.clearAll(true);
        	tree.setItemCount(0);
        }
        
        clearTable();
        this.displayContent(null);
    }
    
    public void clearTable(){
    	Table table = getTable();
    	if(table != null){
	    	table.clearAll();
	    	table.setItemCount(0);
    	}
    }
    
    public TreeItem getSelectedItemFromMainTree(){
    	Tree tree = this.getMainTree();
    	if(tree == null){
    		return null;
    	}
    	
    	TreeItem [] items = tree.getSelection();
    	if(items == null || items.length == 0){
    		return null;
    	}
    	return items[0];
    }
    
    public Object getSelectedFromMainTree(){
    	TreeItem item = getSelectedItemFromMainTree();
    	if(item == null){
    		return null;
    	}
    	return item.getData();    	
    }
 
    public TreeItem getSelectedRootItemFromMainTree(){
    	Tree tree = this.getMainTree();
    	if(tree == null){
    		return null;
    	}
    	
    	TreeItem [] items = tree.getSelection();
    	if(items == null || items.length == 0){
    		return null;
    	}
    	
    	if(items[0].getData() instanceof StackAnalyzedInfo){
    		return items[0].getParentItem();
    	}
    	return items[0];
    }    
    
    public StackFileInfo getSelectedStackFileInfo() {
    	Object object =getSelectedFromMainTree();
        StackFileInfo stackFileInfo = null;

        if ( object instanceof StackAnalyzedInfo ) {
            stackFileInfo = ((StackAnalyzedInfo)object).getStackFileInfo();
        } else if ( object instanceof StackFileInfo ) {
            stackFileInfo = ((StackFileInfo)object);
        }

        return stackFileInfo;
    }    
    
    private void createMainPerformance() {
        StackFileInfo stackFileInfo = getSelectedStackFileInfo();
        if ( stackFileInfo != null ){
        	new PerformanceWindow(m_parentComposite.getShell(), stackFileInfo, null, m_isExcludeStack, true, m_isRemoveLine, m_isInerPercent);
        }
    }  
    
    private void viewRawIndexFile(){
    	Object object = getSelectedFromMainTree();
    	if(object == null){
    		return;
    	}  	
        if (!(object instanceof StackAnalyzedInfo)){
        	return;
        }
        StackAnalyzedInfo analyzedInfo = (StackAnalyzedInfo)object;
        if(analyzedInfo.getExtension().equals(StackParser.UNIQUE_EXT)){
        	return;
        }
        
    	StackFileInfo stackFileInfo = analyzedInfo.getStackFileInfo();
    	
    	System.out.println("StackFile:"+ stackFileInfo.toString());        	
    	System.out.println("File:"+ analyzedInfo.toString());
    	
        String analyzedFilename = StackParser.getAnaylzedFilename(stackFileInfo.getFilename(), analyzedInfo.getExtension());
        File file = new File(analyzedFilename);
        if ( !file.isFile() )
            return;

        BufferedReader reader = null;
        boolean isDetail = false;
        boolean isStart = false;
        try {
            reader = new BufferedReader(new FileReader(file));

            String line = null;
            int totalCount = 0;
            HashMap<String, Integer> map = new HashMap<String, Integer>();
            while ( (line = reader.readLine()) != null ) {
                line = line.trim();
                if(line.length() > 0){
                	isStart = true;
                }
                if(line.length() == 0){
	                if(isStart){
	                	isDetail = true;
	                }
                	continue;
                }
                if(isDetail){
                	totalCount++;
                	HtmlUtils.caculCounter(line, map);
                }                
            }
            
            ArrayList<ValueObject> list = HtmlUtils.sortCounter(map);   
            
            StringBuilder buffer = new StringBuilder(102400);
            buffer.append(HtmlUtils.getMainBodyStart());
            buffer.append(HtmlUtils.getCurrentConfigurationBody()).append("<br><br>");
            buffer.append("<b>[ ").append(stackFileInfo.getFilename()).append(" ]</b><BR>");
            buffer.append("<b>").append(analyzedInfo.toString()).append(" - ").append(analyzedFilename).append("</b><br><br>");

            buffer.append("<table border='1'><tr align='center'><th>Count</th><th>Percent</th><th>Class.method</th></tr>");
            int value;
            for(ValueObject valueObject : list){
            	value = valueObject.getValue();
            	buffer.append("<tr><td align='right'>").append(value).append("</td><td align='right'>").append((int)((100 * value)/totalCount)).append('%').append("</td>");
            	buffer.append("<td align='left'>").append(valueObject.getKey()).append("</td></tr>");
            }
            buffer.append("</table>");
            buffer.append(HtmlUtils.getMainBodyEnd());
            
            displayContent(buffer.toString());
        } catch ( Exception ex ) {
            throw new RuntimeException(ex);
        } finally {
            try {
                if ( reader != null )
                    reader.close();
            } catch ( Exception ex ) {
            }
        }
    }
    
    private void createManualJob( FilterInputDialog.TASK jobtype, boolean isAscending ) {
        try {
        	new FilterInputDialog(m_parentComposite.getShell(), isAscending, jobtype);
        } catch ( Exception e ) {
            throw new RuntimeException(e);
        }
    }
    
    private void createAnalyzedPerformance( boolean isAscending ) {
        createAnalyzedPerformance(getSelectedAnalyzedFunction(), isAscending);
    }

    public void createAnalyzedPerformance( String filter, boolean isAscending ) {
        if ( filter == null )
            return;

        StackFileInfo stackFileInfo = getSelectedStackFileInfo();
        if ( stackFileInfo != null ){
            new PerformanceWindow(m_parentComposite.getShell(), stackFileInfo, filter, m_isExcludeStack, isAscending, m_isRemoveLine, m_isInerPercent);
        }
    }   
    
    public void analyzeFilterStack( String inputFilter ) {
        analyzeFilterStack(inputFilter, true);
    }

    private String getSelectedAnalyzedFunction() {
    	Table table = getTable();
    	if(table == null){
    		return null;
    	}
    	TableItem [] items = table.getSelection();
    	if(items == null || items.length == 0){
    		return null;
    	}
    	
    	return items[0].getText(3);
    }
    
    public void analyzeFilterStack( String inputFilter, boolean isInclude ) {
        String filter = null;
        if ( inputFilter == null ) {
            filter = getSelectedAnalyzedFunction();
        } else {
            filter = inputFilter;
        }

        if ( filter == null )
            return;

        StackFileInfo stackFileInfo = getSelectedStackFileInfo();
        if ( stackFileInfo == null )
            return;

        ParserConfigReader reader = new ParserConfigReader(stackFileInfo.getParserConfig().getConfigFilename());
        ParserConfig config = reader.read();

        StackFileInfo filteredStackFileInfo = processStackFile(StackParser.getWorkingThreadFilename(stackFileInfo.getFilename()), config, filter, false, isInclude);
        addProcessedStack(filteredStackFileInfo);
    }
    
    private void viewThreadStack() {
        viewThreadStack(getSelectedAnalyzedFunction());
    }

    public void viewThreadStack( String filter ) {
        if ( filter == null )
            return;

        StackFileInfo stackFileInfo = getSelectedStackFileInfo();
        if ( stackFileInfo == null )
            return;

        String filename = StackParser.getWorkingThreadFilename(stackFileInfo.getFilename());
        int stackStartLine = stackFileInfo.getParserConfig().getStackStartLine();
        if ( filename != null && filter != null ) {
        	Browser broswer = getBrowser();
            if ( m_isExcludeStack )
            	broswer.setText(HtmlUtils.filterThreadStack(filename, filter, stackFileInfo.getParserConfig().getExcludeStack(), stackStartLine));
            else
            	broswer.setText(HtmlUtils.filterThreadStack(filename, filter, null, stackStartLine));
        }

    }

    private void viewServiceCall() {
        viewServiceCall(getSelectedAnalyzedFunction());
    }

    public void viewServiceCall( String filter ) {
        if ( filter == null )
            return;

        StackFileInfo stackFileInfo = getSelectedStackFileInfo();
        if ( stackFileInfo == null )
            return;

        String filename = StackParser.getWorkingThreadFilename(stackFileInfo.getFilename());
        int stackStartLine = stackFileInfo.getParserConfig().getStackStartLine();
        if ( filename != null && filter != null ) {
            getBrowser().setText(HtmlUtils.filterServiceCall(filename, filter, stackFileInfo.getParserConfig().getService(), stackStartLine));
        }
    }  
    
    private void copyFunctionName() {
        String filter = getSelectedAnalyzedFunction();
        if ( filter != null && filter.length() > 0 )
            StringUtils.setClipboard(filter);
    }  

    private void closeStackFileInfo() {
    	TreeItem item = getSelectedItemFromMainTree();
    	if(item == null){
    		return;
    	}
    	
    	if(item.getData() instanceof StackAnalyzedInfo){
    		item = item.getParentItem();
    	}
    	item.removeAll();
    	item.dispose();
    	
    	Table table = getTable();
    	table.clearAll();
    	table.setItemCount(0);
    	displayContent(null);
    }  
    
    private void reanalyzeStackFileInfo() {
    	TreeItem item = getSelectedRootItemFromMainTree();
    	if(item == null){
    		return;
    	}
    	
        StackFileInfo stackFileInfo = (StackFileInfo)item.getData();
        if ( stackFileInfo == null ){
            return;
        }

        try {
            ParserConfigReader reader = new ParserConfigReader(stackFileInfo.getParserConfig().getConfigFilename());
            ParserConfig config = reader.read();

            StackParser.removeAllAnalyzedFile(stackFileInfo);

            processStackFile(stackFileInfo, config, null, false, true);
        } catch ( RuntimeException ex ) {
            closeStackFileInfo();
            throw ex;
        }
        item.removeAll();
        item.setText(stackFileInfo.toTreeInfo());
        addMainTreeSubItem(item, stackFileInfo.getStackAnalyzedInfoList());
        item.setExpanded(true);
        
        clearTable();
    }
    
    public void openStackAnalyzer(){
    	IWorkbench workbench = PlatformUI.getWorkbench();
    	IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); 
    	try{ 
    		workbench.showPerspective(PerspectiveStackAnalyzer.ID, window);
    		window.getActivePage().showView(StackAnalyzerView.ID);
    	} catch (WorkbenchException e) { 
    		System.out.println("Unable to open Perspective: " + PerspectiveStackAnalyzer.ID); 
    	}    	
    }
  
    public void processStackFile(String fileName){
    	openStackAnalyzer();
    	File file = new File(fileName);
    	openFile(file, false);
    }

    public void processStackContents(String contents){
    	openStackAnalyzer();
    	openContents(contents);
    }    
}