/**
 * Title:
 * @version:    $Id: AbstractRecordController.java,v 1.1 2004/11/15 13:47:50 rob Exp $
 * Copyright:   Copyright (C) 2003 Ian Ibbotson
 * @author:     Ian Ibbotson
 * Company:
 * Description:
 */

package com.k_int.AdminApp.gui.RecordView;

import java.util.ArrayList;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;
import java.beans.*;
import java.awt.*;
import java.net.URL;
import com.k_int.AdminApp.config.*;
import net.sf.hibernate.*;
import com.k_int.AdminApp.gui.AdminControllerComponent;
import com.k_int.AdminApp.gui.ControllerOwner;
import com.k_int.AdminApp.gui.ExplorerView.AdminController;
import com.k_int.AdminApp.gui.OneToMany;
import java.util.logging.*;


public abstract class AbstractRecordController implements AdminControllerComponent, ControllerOwner
{
    private static Logger cat = Logger.getLogger("com.k_int.AdminApp.gui.RecordView.AbstractRecordCOntroller");
    public Object source_record;
    protected Vector models = new Vector();
    protected ConfigHolder config;
    protected Session session;
    protected boolean session_owner=false;
    protected Component record_panel;
    protected String name;
    protected ControllerOwner controller_owner;
    protected AdminController top;
    protected boolean is_closeable = true;
    protected boolean is_editable = true;
    protected boolean abandoned;
    protected OneToMany parent;
    protected ArrayList validators = new ArrayList();

    public AbstractRecordController(ConfigHolder config, 
                                  Session session, 
                                  String name,
                                  ControllerOwner controller_owner,
                                  AdminController top,
                                  boolean is_closeable)
    {
        this.config = config;
        this.session = session;
        this.name = name;
        this.controller_owner = controller_owner;
        this.top = top;
        this.is_closeable = is_closeable;
    }

  public AbstractRecordController(ConfigHolder config, 
                                  String repository_id, 
                                  String name,
                                  ControllerOwner controller_owner,
                                  AdminController top,
                                  boolean is_closeable) throws net.sf.hibernate.HibernateException 
  {
    this.config = config;
    this.session = config.getSessionFactory(repository_id).openSession();
    this.session_owner = true;
    this.name = name;
    this.controller_owner = controller_owner;
    this.top = top;
    this.is_closeable = is_closeable;
  }


    public void recordChanged(Object record, boolean editable)
    {
        cat.fine("AbstractRecordController Record changed - record is "+record+", source_record is "+source_record);     
        source_record = record;
        is_editable = editable;

        // We maintain a vector of all models attached to this layout, and how they relate to their
        // sources... Here, we need to walk through all models, and call the appropriate fire changed method
        for ( Enumeration e = models.elements(); e.hasMoreElements(); )
        {            
            ((RecordModelListener)e.nextElement()).recordChanged(record, editable);
        }
    }
  
    public void registerRecordModelListener(RecordModelListener listener)
    {
        cat.finest("AbstractRecordCOntroller register listener....."+listener);
        models.add(listener);
        listener.setController(this);
    }
    
    
    public void registerValidator(Validator validator)
    {
        validators.add(validator);
    }
    

  // 
  public abstract java.awt.Component getView();

    public Object getComponentId()
    {
        return new Long(this.hashCode());
    }

    public String getName()
    {
        return name;
    }

  // protected Component getRecordPanel(String view_id)
  public void selectTemplate(String view_id)
  {
    models.clear();
    source_record=null;
    
    try
    {
      // Use the config object to resolve the layout_id into a resource
      String resource = config.lookupViewResource(view_id);
      URL view_definition = ClassLoader.getSystemResource(resource);
      XMLDecoder d = new XMLDecoder( new BufferedInputStream( view_definition.openStream() ), this );
      record_panel = (Component) d.readObject();
      
      if(name==null)
      {
          String panel_name = record_panel.getName();
        if(panel_name!=null)
            name=panel_name;
      }
      d.close();
    }
    catch ( Exception e )
    {
      e.printStackTrace();
    }
  }

  protected void finalize()
  {
    cat.finest("finalize.. check session is released");
    if ( ( session_owner ) && ( session != null ) )
    {
      try
      {
        session.close();
        session = null;
      }
      catch ( Exception e )
      {
        e.printStackTrace();
      }
    }
  }

  public void close()
  {
    cat.finest("AbstractRecordController::close");

    if ( session_owner )
    {
      try
      {
        cat.finest("SessionOwner... close the database session");
        session.close();
        session = null;
      }
      catch ( Exception e )
      {
        e.printStackTrace();
      }
    }

    // If we are owned by some intermediate component, notify our owner.
    if ( controller_owner != null )
    {
        cat.finest("Controller owner is not null");
      if(abandoned)
      {
          cat.finest("abandoned, parent is "+parent);
          if(parent!=null)
          {
              cat.finest("Removing "+source_record+" from "+parent);
            parent.removeGenericChildObject(source_record);
          }        
      }
      else
      {
        controller_owner.componentCloseNotification(this);
        
      }
      //controller_owner.componentCloseNotification(this);
    }

    top.componentCloseNotification(this);
  }

  public boolean isCloseable()
  {
    return is_closeable;
  }

  public void setIsCloseable(boolean is_closeable)
  {
    this.is_closeable = is_closeable;
  }

  public Object getSourceRecord()
  {
    return source_record;
  }

  public AdminController getRootController()
  {
    return top;
  }

  public ConfigHolder getConfig()
  {
    return config;
  }

  public Session getSession()
  {
    return session;
  }

  public abstract void componentCloseNotification(AdminControllerComponent component);

 
  public void synchronizeFormAndModel()
  {
    cat.finest("synchronizeFormAndModel()");
                                                                                                                                        
    for ( Enumeration e = models.elements(); e.hasMoreElements(); )
    {
      RecordModelListener rml = (RecordModelListener)e.nextElement();
      rml.synchronizeViewToModel();
    }
  }

  protected void refresh()
  {
      cat.finest("AbstractRecordController:: Refresh called");
      recordChanged(source_record, is_editable);
  }
}
