package org.pss;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import ognl.*;
public abstract class PSSServlet extends HttpServlet implements SingleThreadModel{
 private MarkupWriter markupWriter= new MarkupWriter(this.getClass(),this);
 
 
  protected void doPost(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException{
   markupWriter.setReqRespContext(req, resp,getServletContext());
    render(req, resp,null);
    PrintWriter pw=resp.getWriter();
    pw.print(markupWriter.refreshMarkupsAsString());
    pw.flush();
  }
  
  protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException{
   markupWriter.setReqRespContext(req, resp,getServletContext());
   render(req, resp,null);
    PrintWriter pw=resp.getWriter();
    pw.print(markupWriter.refreshMarkupsAsString());
    pw.flush();
  }
 
 protected void loadFieldsFromSession(javax.servlet.http.HttpServletRequest req){
  try {
   PSSSession thisObjSession=(PSSSession)req.getSession().getAttribute(this.getClass().getName());
   Hashtable table=thisObjSession.getSessionMap();
   Set keys=table.keySet();
   for(String key: keys){
    Object val=table.get(key);
    try {
     Ognl.setValue(key, this,val);
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 protected String refreshMarkup(){
  return markupWriter.refreshMarkupsAsString();
 }
 
 public  MarkupWriter getMarkupWriter(){
  return markupWriter;
 }
 
 protected abstract void render(HttpServletRequest req, HttpServletResponse resp, Object obj) throws javax.servlet.ServletException, java.io.IOException;
 
 
}
package org.pss;
import java.util.*;
import java.io.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import ognl.*;
public class MarkupWriter {
 Class clss=null;
 Object servletObj=null;
 HttpServletRequest req=null;
 HttpServletResponse resp=null;
 
 public void setReqRespContext(HttpServletRequest request,HttpServletResponse response,ServletContext ctx){
  req=request;
  resp=response;
  //context=ctx;
 }
 
 boolean populateInitialMarkupCalled=false;
 public boolean skipEvaluationOfMarkup=false;
 
 
 HashMap chunkMap= new HashMap();
 HashMap owcidMap= new HashMap();
 HashMap pwcidMap= new HashMap();
 TreeMap populatedChunkMap= new TreeMap();
 HashMap populatedOwcidMap= new HashMap();
 HashMap populatedPwcidMap= new HashMap();
 
 public MarkupWriter(Class clas){
  System.out.println("here 2 -- "+clas.getName());
  clss=clas;
 }
 public MarkupWriter(Class clas, Object obj){
  System.out.println("here 3-- "+clas.getName()+":"+obj);
  clss=clas;
  servletObj=obj;
 }
 public MarkupWriter(Class clas, Object obj,HttpServletRequest request, HttpServletResponse response){
  System.out.println("here 3-- "+clas.getName()+":"+obj);
  clss=clas;
  servletObj=obj;
  req=request;
  resp=response;
 }
 
 public MarkupWriter(){
  super();
  System.out.println("here 1-- ");
 }
 
 public HashMap getChunkMap(){
  return chunkMap;
 }
 public TreeMap getPopulatedChunkMap(){
  return populatedChunkMap;
 }
 /**
  * refresh entire populated markup (after recursively travelling nested components)
  */
 public String refreshMarkupsAsString(){
  if(!populateInitialMarkupCalled){
   populateInitialMarkup();
   populateInitialMarkupCalled=true;
  }
  if(!skipEvaluationOfMarkup){
   evaluatePwcidMarkup();
   evaluateOwcidMarkup();
  }
  Collection chunkVals=populatedChunkMap.values();
  StringBuffer sb= new StringBuffer("");
  for(String str: chunkVals){
   sb.append(str);
  }
  return sb.toString();
 }
 
 private void evaluatePwcidMarkup(){
  Set pwcidKeys=pwcidMap.keySet();
  for(Integer key: pwcidKeys){
   String val=pwcidMap.get(key);
   String populatedVal="";
   try {
    populatedVal= Ognl.getValue(val, servletObj).toString();
   } catch (OgnlException e) {
    e.printStackTrace();
   }
   populatedChunkMap.put(key, populatedVal);
   populatedPwcidMap.put(key, populatedVal);
  }
 }
 
 /**
  * owcid has format :. 
  * expr evaluates to servletObj and  evaluates to argument.
  * This recursively travels internal components. 
  */
 private void evaluateOwcidMarkup(){ // this method could have been combined with evaluatePwcidMarkup
  Set owcidKeys=owcidMap.keySet();
  for(Integer key: owcidKeys){
   String val=owcidMap.get(key);
   String prefixExpr=val.substring(0,val.indexOf(":"));
   String suffixExpr2=val.substring(val.indexOf(":")+1);
   Object populatedPrefixVal=null;
   Object populatedSuffixVal2=null;
   String resultVal="";
   try {
    populatedPrefixVal=Ognl.getValue(prefixExpr, servletObj);
    try {
     populatedSuffixVal2=Ognl.getValue(suffixExpr2, servletObj);
    } catch (Exception e) {
     e.printStackTrace();
    }
    if(populatedPrefixVal instanceof PSSServlet){
     PSSServlet servlet=((PSSServlet)populatedPrefixVal);
     servlet.render(req, resp, populatedSuffixVal2);
     resultVal=servlet.refreshMarkup();
    }
    if(populatedPrefixVal instanceof PSSComponent){
     PSSComponent servlet=((PSSComponent)populatedPrefixVal);
     servlet.render(req, resp, populatedSuffixVal2);
     resultVal=servlet.refreshMarkup();
    }
   } catch (Exception e) {
    e.printStackTrace();
   }
   populatedChunkMap.put(key, resultVal);
   populatedOwcidMap.put(key, resultVal);
  }
 }
 public boolean populateInitialMarkup(){
  try{
   populateInitialMarkupCalled=true;
   String fileName="/"+clss.getName().replace(".", "/")+".html";
   System.out.println("clss.getName()="+fileName);
   String fileStr=readFile(fileName);
   ArrayList chunks=getChunks(fileStr);
   int i=0;
   for(String st:chunks){
    i++;
    if(st.startsWith("${owcid:")){
     populatedChunkMap.put(i,st);
     chunkMap.put(i,st);
     owcidMap.put(i,st.substring(8).trim());
    }
    else if(st.startsWith("${pwcid:")){
     populatedChunkMap.put(i,st);
     chunkMap.put(i,st);
     pwcidMap.put(i,st.substring(8).trim());
    }else{
     populatedChunkMap.put(i,st);
     chunkMap.put(i,st);
    }
   }
  }catch(Exception e){
   e.printStackTrace();
  }
  
  return true;
 }
 
 
 private String readFile(String fileName){
  try{
   System.out.println(this.getClass().getResource(fileName));
   
   Reader is=new InputStreamReader(this.getClass().getResourceAsStream(fileName));
   
   char[] barr= new char[4096];
   int i=0;
   StringBuffer sb= new StringBuffer("");
   while((i=is.read(barr))>=0)
    sb.append(barr,0,i);
   return sb.toString();
  }catch(Exception e){
   e.printStackTrace();
  }
  return null;
 }
 /**
  * chunks - a concept I read in book- "tapestry in action"
  */
 private ArrayList getChunks(String str){
  int currIdx=0,endIndx=0,_endIndxP=0,_endIndxO=0,prevIdx=0;
  ArrayList alist=new ArrayList();
  while(true){
   _endIndxP=str.indexOf("${pwcid:",currIdx);
   _endIndxO=str.indexOf("${owcid:",currIdx);
   if(_endIndxP<0 && _endIndxO<0){
    alist.add(str.substring(currIdx));
    break;   //over 
   }else if((_endIndxO<0 || _endIndxP<_endIndxO) && _endIndxP>= currIdx){
    endIndx=_endIndxP;
   }else if((_endIndxP<0 || _endIndxO<_endIndxP) && _endIndxO>= currIdx){
    endIndx=_endIndxO;
   }else {
    throw new RuntimeException("!ERROR: invalid condition "+endIndx);
   }
   
   int _tmpIdx=str.indexOf("}",endIndx);
   if(_tmpIdx>endIndx){
    alist.add(str.substring(currIdx,endIndx));
    alist.add(str.substring(endIndx,_tmpIdx));//pwcid/owcid
    currIdx=_tmpIdx+1;
   }else{//no closing braces
    throw new RuntimeException("No closing braces for ${pwcid/owcid: "+endIndx);
   }
   
  }
  return alist;
 }
}
package org.pss;
import java.util.*;
/**
 * contains one hashtable storing key value being ognl expression.
 * @author hari sujathan
 *
 */
public class PSSSession {
 private Hashtable sessionMap= new Hashtable();
 public Hashtable getSessionMap() {
  return sessionMap;
 }
 public void setSessionMap(Hashtable sessionMap) {
  this.sessionMap = sessionMap;
 }
}