/* * ==================================================================== * * 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 + "]"; } }