/*
  Copyright (C) 2006 Helge Hess

  This file is part of JOPE.

  JOPE is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.

  JOPE is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with JOPE; see the file COPYING.  If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
*/

package org.opengroupware.jope.eoaccess;

import java.util.HashMap;
import java.util.Map;

import org.opengroupware.jope.foundation.NSObject;

/*
 * EOCustomObject
 * 
 * Abstract superclass for EO's.
 * 
 * TODO: document
 */
// TODO: mark abstract
public class EOCustomObject extends NSObject
  implements EOEnterpriseObject
{

  /* initialization */
  
  public void awakeFromFetch(EODatabase _db) {
  }
  public void awakeFromInsertion(EODatabase _db) {
  }
  
  /* snapshot management */
  
  public boolean updateFromSnapshot(Map<String, Object> _snap) {
    if (_snap == null)
      return false;
    
    for (String key: _snap.keySet())
      this.takeStoredValueForKey(_snap.get(key), key);
    
    return true;
  }

  public Map<String, Object> snapshot() {
    // TODO: do something ;-) I suppose retrieve a snapshot from the database
    //       context?
    return null;
  }
  
  public Map<String, Object> changesFromSnapshot(Map<String, Object> _snap) {
    if (_snap == null)
      return null;
    
    Map<String, Object> changes = null;
    for (String key: _snap.keySet()) {
      Object snapValue = _snap.get(key);
      Object value     = this.valueForKey(key);
      
      if (value == snapValue) /* still the same */
        continue;
      
      if (value != null && value.equals(snapValue)) /* still the same */
        continue;
      
      if (changes == null) changes = new HashMap<String, Object>(4);
      changes.put(key, value); // Note: null is allowed in HashMaps!
    }
    
    return changes;
  }
  
  public void reapplyChangesFromDictionary(Map<String, Object> _snap) {
    // TODO: this should have different behaviour?
    this.takeValuesFromDictionary(_snap);
  }
  
  /* accessor management */
  
  public void willRead() {
  }
  public void willChange() {
  }
  
  /* EOValidation */

  public Exception validateForSave() {
    // TODO: send EOClassDescription validateObjectForSave
    // TODO: iterate over properties and send them validateValueForKey
    return null; /* everything is awesome */
  }
  
  public Exception validateForInsert() {
    return this.validateForSave();
  }
  public Exception validateForDelete() {
    return this.validateForSave();
  }
  public Exception validateForUpdate() {
    return this.validateForSave();
  }
  
  /* EOKeyValueCoding */
  
  public void takeStoredValueForKey(Object _value, String _key) {
    this.takeValueForKey(_value, _key);
  }
  public Object storedValueForKey(String _key) {
    return this.valueForKey(_key);
  }

  public void takeValuesFromDictionaryWithMapping
    (Map<String, Object> _vals, Map<String, String> _extNameToPropName)
  {
    if (_vals == null)
      return;
    if (_extNameToPropName == null) {
      this.takeValuesFromDictionary(_vals);
      return;
    }
    
    /* Note: we leave out 'null' values */
    for (String propName: _extNameToPropName.keySet()) {
      String keyName = _extNameToPropName.get(propName);
      this.takeValueForKey(_vals.get(propName), keyName);
    }
  }
  
  public Map<String, Object> valuesForKeysWithMapping
    (Map<String, String> _extNameToPropName)
  {
    if (_extNameToPropName == null)
      return null;
    
    Map<String, Object> vals = new HashMap<String, Object>(16);
    
    /* Note: we leave out 'null' values */
    for (String propName: _extNameToPropName.keySet()) {
      String keyName = _extNameToPropName.get(propName);
      Object value   = this.valueForKey(keyName);
      if (value != null) vals.put(propName, value);
    }
    
    return vals;
  }
  
  /* description */
  
  public void appendAttributesToDescription(StringBuffer _d) {
    super.appendAttributesToDescription(_d);
  }
}
