package net.sf.jasperreports.engine.fill;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRReportTemplate;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRTemplate;
import net.sf.jasperreports.engine.xml.JRXmlTemplateLoader;

public class JRFillReportTemplate implements JRReportTemplate {
  private final JRReportTemplate parent;
  
  private final JRBaseFiller filler;
  
  public JRFillReportTemplate(JRReportTemplate template, JRBaseFiller filler, JRFillObjectFactory factory) {
    factory.put(template, this);
    this.parent = template;
    this.filler = filler;
  }
  
  public JRExpression getSourceExpression() {
    return this.parent.getSourceExpression();
  }
  
  public JRTemplate evaluate() throws JRException {
    JRTemplate template;
    JRExpression sourceExpression = getSourceExpression();
    Object source = this.filler.evaluateExpression(sourceExpression, (byte)3);
    if (source == null) {
      template = null;
    } else {
      Class sourceType = sourceExpression.getValueClass();
      if (JRTemplate.class.isAssignableFrom(sourceType)) {
        template = (JRTemplate)source;
      } else {
        template = loadTemplate(source, sourceType, this.filler.fillContext);
      } 
    } 
    return template;
  }
  
  protected static JRTemplate loadTemplate(Object source, Class sourceType, JRFillContext fillContext) throws JRException {
    JRTemplate template;
    if (fillContext.hasLoadedTemplate(source)) {
      template = fillContext.getLoadedTemplate(source);
    } else {
      if (String.class.equals(sourceType)) {
        template = JRXmlTemplateLoader.load((String)source);
      } else if (File.class.isAssignableFrom(sourceType)) {
        template = JRXmlTemplateLoader.load((File)source);
      } else if (URL.class.isAssignableFrom(sourceType)) {
        template = JRXmlTemplateLoader.load((URL)source);
      } else if (InputStream.class.isAssignableFrom(sourceType)) {
        template = JRXmlTemplateLoader.load((InputStream)source);
      } else {
        throw new JRRuntimeException("Unknown template source class " + sourceType.getName());
      } 
      fillContext.registerLoadedTemplate(source, template);
    } 
    return template;
  }
}
