package com.gammastream.validity;
//javadoc *.java -author -package com.gammastream.validity -d api
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Enumeration;
import com.webobjects.appserver.xml.WOXMLCoder;
import com.webobjects.appserver.xml.WOXMLCoding;
import com.webobjects.appserver.xml.WOXMLDecoder;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOModel;
import com.webobjects.eoaccess.EOModelGroup;
import com.webobjects.eocontrol.EOEnterpriseObject;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSLog;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSPathUtilities;
/**
* GSVModel used for the mapping validation rules to an entities' attributes.<BR>
* The structure is very similar to Apple's EOModel.
*
* @author GammaStream Technologies, Inc.
*/
public final class GSVModel implements WOXMLCoding {
/******************************** STATIC ********************************/
/**
* The name of the GSVModel file included in the '.eomodeld' wrapper.<BR>
* Currently the full name is: 'Validity.model'
*/
public static final String MODEL_NAME = "Validity";
/**
* The extension of the GSVModel file included in the '.eomodeld' wrapper.<BR>
* Currently the full name is: 'Validity.model'
*/
public static final String MODEL_EXTENSION = "model";
/******************************** INSTANCE ********************************/
//persistant model attributes
private NSMutableArray _entities = null;
private String _eomodelPath = null;
private String _eomodelName = null;
private boolean inited = false;
//helper for mapping the GSVModel to an EOModel
private EOModelGroup _eomodelGroup = null;
/**
* Creates a new GSVModel using the path to an '.eomodeld' file.<BR>
* <BR>
* Example of creating a GSVModel for the Movies example which ships with WebObjects.<BR>
* <BR>
* <blockquote>
* <code>
* EOModel eoModel = EOModelGroup.defaultGroup().modelNamed("Moview");<BR>
* GSVModel model = new GSVModel(eoModel.path());<BR>
* </code>
* </blockquote>
*
* @param path Path to an '.eomodeld' file.
* @exception java.lang.IllegalArgumentException Thrown if valid '.eomodeld' file does not exist at the specified path.
*/
public GSVModel(String path) throws IllegalArgumentException {
if(this.validateEOModelForPath(path)){
_entities = new NSMutableArray();
_eomodelPath = path;
_eomodelName = NSPathUtilities.stringByDeletingPathExtension(NSPathUtilities.lastPathComponent(_eomodelPath));
_eomodelGroup = new EOModelGroup();
_eomodelGroup.addModelWithPath(_eomodelPath);
//this.saveModel();
} else {
throw new IllegalArgumentException("Could not find a valid EOModel at: " + path);
}
}
/**
* Determines that there is indeed a file located at the given path.
*
* @return <code>true</code> if an '.eomodeld' file is located at the given path; otherwise, we return <code>false</code>.
* @param path Path to the desired '.eomodeld' file.
*
*/
public boolean validateEOModelForPath(String path){
try {
File f = new File(path);
return f.exists();
} catch(Exception e){
return false;
}
}
/**
* Saves the GSVModel to inside the '.eomodeld' file wrapper.
*
* @return <code>true</code> if save is successful; otherwise, returns <code>false</code>.
*/
public boolean saveModel(){
String codedString = WOXMLCoder.coder().encodeRootObjectForKey(this, "Model");
String fullFileName = NSPathUtilities.stringByAppendingPathExtension(GSVModel.MODEL_NAME, GSVModel.MODEL_EXTENSION);
String xmlPath = NSPathUtilities.stringByAppendingPathComponent(_eomodelPath, fullFileName);
try {
File configurationFile = new File(xmlPath);
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(configurationFile), "UTF-8");
osw.write(codedString);
osw.close();
NSLog.out.appendln("did save model to file");
return true;
} catch(IOException e) {
NSLog.out.appendln(e);
return false;
}
}
/**
* Returns the EOModelGroup that is being used to query information from the EOModel.
*
* @return EOModelGroup for the EOModel.
*/
public EOModelGroup eomodelGroup(){
return _eomodelGroup;
}
/**
* Returns the EOModel Name for the associated GSVModel.
*
* @return Name of the EOModel
*/
public String eomodelName(){
return _eomodelName;
}
/**
* Returns the path of the '.eomodeld' file.
*
* @return Path of the EOModel File.
* @see #setEomodelPath
*/
public String eomodelPath(){
return _eomodelPath;
}
/**
* Set the path of the EOModel file.
*
* @param path Path of the EOModel File.
* @see #eomodelPath
*/
public void setEomodelPath(String path){
_eomodelPath = path;
}
/**
* Returns the NSArray of GSVEntity Objects.
*
* @return NSArray of GSVEntity Objects.
* @see #addEntity
* @see #removeEntity
*/
public NSArray entities(){
return _entities;
}
/**
* Adds a GSVEntity object to this GSVModel. The GSVEntity must not already exsit.<BR>
* If it does, IllegalArgumentException is thrown.
*
* @param newEntity GSVEntity object
* @exception java.lang.IllegalArgumentException GSVEnitity already exsits.
* @see #entities
* @see #removeEntity
*/
public void addEntity(GSVEntity newEntity) throws IllegalArgumentException{
GSVEntity currentEntity = null;
for(int i=0;i<_entities.count();i++){
currentEntity = (GSVEntity)_entities.objectAtIndex(i);
if(currentEntity.name().equals(newEntity.name())){
throw new IllegalArgumentException("Entity for name '"+newEntity.name()+"' already exsits in model named "+this.eomodelName());
}
}
_entities.addObject(newEntity);
}
/**
* Removes a GSVEntity object from this GSVModel.
*
* @param oldEntity GSVEntity object to remove.
* @see #entities
* @see #addEntity
*/
public void removeEntity(GSVEntity oldEntity){
_entities.removeObject(oldEntity);
}
/**
* Returns the GSVEntity object associated with the provided EOEnterpriseObject.
*
* @param object EOEnterpriseObject
* @return GSVEntity if the EOEnterpriseObject has an GSVEntity Null if not.
* @see #entityNamed
*/
public GSVEntity entityForObject(Object object){
if(object instanceof EOEnterpriseObject){
GSVEntity currentEntity = null;
for(int i=0;i<_entities.count();i++){
currentEntity = (GSVEntity)_entities.objectAtIndex(i);
if(currentEntity.name().equals(((EOEnterpriseObject)object).entityName()))
return currentEntity;
}
}
return null;
}
/**
* Returns the GSVEntity object for the provided entity name.
*
* @param name name of entity
* @return GSVEntity if an GSVEntity is named name, <code>null</code> if it could not be found.
* @see #entityForObject
*/
public GSVEntity entityNamed(String name){
GSVEntity currentEntity = null;
for(int i=0;i<_entities.count();i++){
currentEntity = (GSVEntity)_entities.objectAtIndex(i);
if(currentEntity.name().equals(name))
return currentEntity;
}
return null;
}
/**
* Returns an NSArray containing the GSVEntity names.
*
* @return NSArray names of GSVEntities.
*/
public NSArray entityNames(){
NSMutableArray names = new NSMutableArray();
GSVEntity currentEntity = null;
for(int i=0;i<_entities.count();i++){
currentEntity = (GSVEntity)_entities.objectAtIndex(i);
names.addObject(currentEntity.name());
}
return names;
}
/**
* Internal method for saving paths
*/
public void savePath(String s){
_eomodelPath = s;
_eomodelGroup.addModelWithPath(_eomodelPath);
this.saveModel();
}
/******************************** WOXMLCoding Impl ********************************/
/**
* WOXMLCoding Impl
*
* @param coder WOXMLCoder
*
* @see #GSVModel
*/
public void encodeWithWOXMLCoder(WOXMLCoder coder) {
coder.encodeObjectForKey(_entities.immutableClone(), "Entities");
coder.encodeObjectForKey(_eomodelName, "EOModelName");
coder.encodeObjectForKey(_eomodelPath, "EOModelPath");
}
/**
* WOXMLCoding Impl
*
* @param decoder WOXMLDecoder
*
* @see #encodeWithWOXMLCoder
*/
public GSVModel(WOXMLDecoder decoder) {
_entities = new NSMutableArray((NSArray)decoder.decodeObjectForKey("Entities"));
_eomodelName = (String)decoder.decodeObjectForKey("EOModelName");
//We changed "Name" to "EOModelName", so for backward compatibility, if "EOModelName"
//doesn't exist, we have to check for "Name"
if( _eomodelName == null ){
_eomodelName = (String)decoder.decodeObjectForKey("Name");
}
_eomodelGroup = new EOModelGroup();
_eomodelPath = (String)decoder.decodeObjectForKey("EOModelPath");
}
/**
* WOXMLCoding Impl
*/
public Class classForCoder() {
try{
return Class.forName("com.gammastream.validity.GSVModel");
} catch (ClassNotFoundException e) {
return null;
}
}
public void init(EOModel eomodel) {
if (!inited) {
inited = true;
for (Enumeration e = entities().immutableClone().objectEnumerator(); e.hasMoreElements();) {
GSVEntity entity = (GSVEntity)e.nextElement();
String name = entity.name();
EOEntity eoentity = eomodel.entityNamed(name);
//NSLog.debug.appendln("checking gsventity"+entity.name());
if ( eoentity == null) {
removeEntity(entity);
//NSLog.debug.appendln("removed obsolete gsventity"+entity.name());
} else {
entity.init(this, eoentity);
}
}
}
}
}