/*
* ====================================================================
*
* The ObjectStyle Group Software License, Version 1.0
*
* Copyright (c) 2006 The ObjectStyle Group and individual authors of the
* software. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowlegement: "This product includes software
* developed by the ObjectStyle Group (http://objectstyle.org/)." Alternately,
* this acknowlegement may appear in the software itself, if and wherever such
* third-party acknowlegements normally appear.
*
* 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse or
* promote products derived from this software without prior written permission.
* For written permission, please contact andrus@objectstyle.org.
*
* 5. Products derived from this software may not be called "ObjectStyle" nor
* may "ObjectStyle" appear in their names without prior written permission of
* the ObjectStyle Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* OBJECTSTYLE GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many individuals on
* behalf of the ObjectStyle Group. For more information on the ObjectStyle
* Group, please see <http://objectstyle.org/>.
*
*/
package org.objectstyle.wolips.eomodeler.core.model;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectstyle.woenvironment.plist.PropertyListParserException;
import org.objectstyle.woenvironment.plist.WOLPropertyListSerialization;
import org.objectstyle.wolips.baseforplugins.util.ComparisonUtils;
import org.objectstyle.wolips.baseforplugins.util.StringUtils;
public class EOStoredProcedure extends UserInfoableEOModelObject<EOModel> implements ISortableEOModelObject {
public static final String NAME = "name";
public static final String EXTERNAL_NAME = "externalName";
public static final String ARGUMENT = "argument";
public static final String ARGUMENTS = "arguments";
private EOModel myModel;
private String myName;
private String myExternalName;
private List<EOArgument> myArguments;
private EOModelMap myStoredProcedureMap;
private boolean _storedProcedureDirty;
private EOLastModified _lastModified;
public EOStoredProcedure() {
myStoredProcedureMap = new EOModelMap();
myArguments = new LinkedList<EOArgument>();
_storedProcedureDirty = true;
}
public EOStoredProcedure(String _name) {
this();
myName = _name;
}
public void setStoredProcedureDirty(boolean storedProcedureDirty) {
_storedProcedureDirty = storedProcedureDirty;
}
public boolean isStoredProcedureDirty() {
return _storedProcedureDirty;
}
public void pasted() {
for (EOArgument argument : myArguments) {
argument.pasted();
}
}
public Set<EOModelReferenceFailure> getReferenceFailures() {
Set<EOModelReferenceFailure> referenceFailures = new HashSet<EOModelReferenceFailure>();
for (EOArgument argument : myArguments) {
referenceFailures.addAll(argument.getReferenceFailures());
}
if (myModel != null) {
for (EOEntity entity : myModel.getEntities()) {
if (entity.getDeleteProcedure() == this) {
referenceFailures.add(new EOStoredProcedureEntityReferenceFailure(entity, this, EOEntity.DELETE_PROCEDURE));
}
if (entity.getInsertProcedure() == this) {
referenceFailures.add(new EOStoredProcedureEntityReferenceFailure(entity, this, EOEntity.INSERT_PROCEDURE));
}
if (entity.getNextPrimaryKeyProcedure() == this) {
referenceFailures.add(new EOStoredProcedureEntityReferenceFailure(entity, this, EOEntity.NEXT_PRIMARY_KEY_PROCEDURE));
}
if (entity.getFetchWithPrimaryKeyProcedure() == this) {
referenceFailures.add(new EOStoredProcedureEntityReferenceFailure(entity, this, EOEntity.FETCH_WITH_PRIMARY_KEY_PROCEDURE));
}
if (entity.getFetchAllProcedure() == this) {
referenceFailures.add(new EOStoredProcedureEntityReferenceFailure(entity, this, EOEntity.FETCH_ALL_PROCEDURE));
}
for (EOFetchSpecification fetchSpec : entity.getFetchSpecs()) {
if (fetchSpec.getStoredProcedure() == this) {
referenceFailures.add(new EOStoredProcedureFetchSpecReferenceFailure(fetchSpec, this));
}
}
}
}
return referenceFailures;
}
public void _setModel(EOModel _model) {
myModel = _model;
}
public EOModel getModel() {
return myModel;
}
@SuppressWarnings("unused")
protected void _argumentChanged(EOArgument _argument, String _propertyName, Object _oldValue, Object _newValue) {
firePropertyChange(EOStoredProcedure.ARGUMENT, null, _argument);
}
protected void _propertyChanged(String _propertyName, Object _oldValue, Object _newValue) {
if (myModel != null) {
setStoredProcedureDirty(true);
myModel._storedProcedureChanged(this, _propertyName, _oldValue, _newValue);
}
}
// public int hashCode() {
// return ((myModel == null) ? 1 : myModel.hashCode()) * ((myName == null) ? super.hashCode() : myName.hashCode());
// }
//
// public boolean equals(Object _obj) {
// boolean equals = false;
// if (_obj instanceof EOStoredProcedure) {
// EOStoredProcedure storedProcedure = (EOStoredProcedure) _obj;
// equals = (storedProcedure == this) || (ComparisonUtils.equals(storedProcedure.myModel, myModel) && ComparisonUtils.equals(storedProcedure.myName, myName));
// }
// return equals;
// }
public void setName(String _name) throws DuplicateStoredProcedureNameException {
setName(_name, true);
}
public void setName(String _name, boolean _fireEvents) throws DuplicateStoredProcedureNameException {
if (myModel != null) {
myModel._checkForDuplicateStoredProcedureName(this, _name, null);
myModel._storedProcedureNameChanged(myName, _name);
}
String oldName = myName;
myName = _name;
if (_fireEvents) {
firePropertyChange(EOStoredProcedure.NAME, oldName, myName);
}
}
public String getName() {
return myName;
}
public String getExternalName() {
return myExternalName;
}
public void setExternalName(String _externalName) {
String oldExternalName = myExternalName;
myExternalName = _externalName;
firePropertyChange(EOStoredProcedure.EXTERNAL_NAME, oldExternalName, myExternalName);
}
public EOArgument getArgumentNamed(String _name) {
EOArgument matchingArgument = null;
Iterator<EOArgument> argumentsIter = myArguments.iterator();
while (matchingArgument == null && argumentsIter.hasNext()) {
EOArgument argument = argumentsIter.next();
if (ComparisonUtils.equals(argument.getName(), _name)) {
matchingArgument = argument;
}
}
return matchingArgument;
}
public String findUnusedArgumentName(String _newName) {
return _findUnusedName(_newName, "getArgumentNamed");
}
public void _checkForDuplicateArgumentName(EOArgument _argument, String _newName, Set<EOModelVerificationFailure> _failures) throws DuplicateNameException {
EOArgument existingArgument = getArgumentNamed(_newName);
if (existingArgument != null && existingArgument != _argument) {
if (_failures == null) {
throw new DuplicateArgumentNameException(_newName, this);
}
String unusedName = findUnusedArgumentName(_newName);
existingArgument.setName(unusedName, true);
_failures.add(new DuplicateArgumentFailure(this, _newName, unusedName));
}
}
public EOArgument addBlankArgument(String _name) throws DuplicateNameException {
EOArgument argument = new EOArgument(findUnusedArgumentName(_name));
argument.setAllowsNull(Boolean.TRUE, false);
addArgument(argument);
return argument;
}
public void addArgument(EOArgument _argument) throws DuplicateNameException {
addArgument(_argument, null, true);
}
public void addArgument(EOArgument _argument, Set<EOModelVerificationFailure> _failures, boolean _fireEvents) throws DuplicateNameException {
_argument._setStoredProcedure(this);
_checkForDuplicateArgumentName(_argument, _argument.getName(), _failures);
_argument.pasted();
List<EOArgument> oldArguments = null;
if (_fireEvents) {
oldArguments = myArguments;
List<EOArgument> newArguments = new LinkedList<EOArgument>();
newArguments.addAll(myArguments);
newArguments.add(_argument);
myArguments = newArguments;
firePropertyChange(EOStoredProcedure.ARGUMENTS, oldArguments, myArguments);
} else {
myArguments.add(_argument);
}
}
public void removeArgument(EOArgument _argument) {
List<EOArgument> oldArguments = myArguments;
List<EOArgument> newArguments = new LinkedList<EOArgument>();
newArguments.addAll(myArguments);
newArguments.remove(_argument);
myArguments = newArguments;
firePropertyChange(EOStoredProcedure.ARGUMENTS, oldArguments, newArguments);
_argument._setStoredProcedure(null);
}
public List<EOArgument> getArguments() {
return myArguments;
}
public List<EOArgument> getSortedArguments() {
return myArguments;
}
public void loadFromMap(EOModelMap _map, Set<EOModelVerificationFailure> _failures) throws EOModelException {
myStoredProcedureMap = _map;
myName = _map.getString("name", true);
myExternalName = _map.getString("externalName", true);
List<Map> argumentsList = _map.getList("arguments", false);
if (argumentsList != null) {
for (Map originalArgumentMap : argumentsList) {
EOModelMap argumentMap = new EOModelMap(originalArgumentMap);
EOArgument argument = new EOArgument();
argument.loadFromMap(argumentMap, _failures);
addArgument(argument, _failures, false);
}
}
loadUserInfo(_map);
}
public EOModelMap toMap() {
EOModelMap fetchSpecMap = myStoredProcedureMap.cloneModelMap();
fetchSpecMap.setString("name", myName, true);
fetchSpecMap.setString("externalName", myExternalName, true);
List<Map> arguments = new LinkedList<Map>();
for (EOArgument argument : myArguments) {
EOModelMap argumentMap = argument.toMap();
arguments.add(argumentMap);
}
fetchSpecMap.setList("arguments", arguments, true);
writeUserInfo(fetchSpecMap);
return fetchSpecMap;
}
public void checkLastModified(Set<EOLastModified> lastModified) {
if (_lastModified != null && _lastModified.hasBeenModified()) {
lastModified.add(_lastModified);
}
}
public void loadFromURL(URL storedProcedureURL, Set<EOModelVerificationFailure> failures) throws EOModelException {
try {
_lastModified = new EOLastModified(storedProcedureURL);
EOModelMap entityMap = new EOModelMap((Map) WOLPropertyListSerialization.propertyListFromURL(storedProcedureURL, new EOModelParserDataStructureFactory()));
loadFromMap(entityMap, failures);
setStoredProcedureDirty(false);
} catch (Throwable e) {
throw new EOModelException("Failed to load stored procedure from '" + storedProcedureURL + "'.", e);
}
}
public void saveToFile(File storedProcedureFile) throws PropertyListParserException, IOException {
EOModelMap storedProcedureMap = toMap();
WOLPropertyListSerialization.propertyListToFile("Entity Modeler v" + EOModel.CURRENT_VERSION, storedProcedureFile, storedProcedureMap);
setStoredProcedureDirty(false);
_lastModified = new EOLastModified(storedProcedureFile);
}
public void resolve(Set<EOModelVerificationFailure> _failures) {
for (EOArgument argument : myArguments) {
argument.resolve(_failures);
}
}
public void verify(Set<EOModelVerificationFailure> _failures) {
String name = getName();
if (name == null || name.trim().length() == 0) {
_failures.add(new EOModelVerificationFailure(myModel, this, "The stored procedure " + getName() + " has an empty name.", false));
} else {
if (name.indexOf(' ') != -1) {
_failures.add(new EOModelVerificationFailure(myModel, this, "The stored procedure " + getName() + "'s name has a space in it.", false));
}
if (!StringUtils.isUppercaseFirstLetter(myName)) {
_failures.add(new EOModelVerificationFailure(myModel, this, "The stored procedure " + getName() + "'s name is not capitalized, but should be.", true));
}
}
String externalName = getExternalName();
if (externalName == null || externalName.trim().length() == 0) {
_failures.add(new EOModelVerificationFailure(myModel, this, "The stored procedure " + getName() + " has an empty table name.", false));
} else if (externalName.indexOf(' ') != -1) {
_failures.add(new EOModelVerificationFailure(myModel, this, "The stored procedure " + getName() + "'s table name '" + externalName + "' has a space in it.", false));
}
for (EOArgument argument : myArguments) {
argument.verify(_failures);
}
}
public String getFullyQualifiedName() {
return ((myModel == null) ? "?" : myModel.getFullyQualifiedName()) + "/proc: " + getName();
}
@Override
public EOModelObject<EOModel> _cloneModelObject() {
try {
EOStoredProcedure storedProcedure = new EOStoredProcedure(myName);
storedProcedure.myName = myName;
storedProcedure.myExternalName = myExternalName;
for (EOArgument argument : getArguments()) {
if (getArgumentNamed(argument.getName()) == null) {
EOArgument clonedArgument = argument._cloneModelObject();
clonedArgument.setName(findUnusedArgumentName(clonedArgument.getName()));
storedProcedure.addArgument(clonedArgument);
}
}
_cloneUserInfoInto(storedProcedure);
return storedProcedure;
} catch (DuplicateNameException e) {
throw new RuntimeException("A duplicate name was found during a clone, which should never happen.", e);
}
}
@Override
public Class<EOModel> _getModelParentType() {
return EOModel.class;
}
public EOModel _getModelParent() {
return getModel();
}
public void _removeFromModelParent(Set<EOModelVerificationFailure> failures) {
getModel().removeStoredProcedure(this);
}
public void _addToModelParent(EOModel modelParent, boolean findUniqueName, Set<EOModelVerificationFailure> failures) throws EOModelException {
if (findUniqueName) {
setName(modelParent.findUnusedStoredProcedureName(getName()));
}
modelParent.addStoredProcedure(this);
}
public String toString() {
return "[EOStoredProcedure: name = " + myName + "; arguments = " + myArguments + "]";
}
}