001    package org.apache.ojb.broker.util.sequence;
002    
003    /* Copyright 2003-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import org.apache.commons.lang.SystemUtils;
019    import org.apache.ojb.broker.PersistenceBroker;
020    import org.apache.ojb.broker.PersistenceBrokerException;
021    import org.apache.ojb.broker.metadata.JdbcTypesHelper;
022    import org.apache.ojb.broker.util.logging.LoggerFactory;
023    import org.apache.ojb.broker.accesslayer.ResultSetAndStatement;
024    import org.apache.ojb.broker.metadata.FieldDescriptor;
025    import org.apache.ojb.broker.metadata.JdbcType;
026    import org.apache.ojb.broker.query.Query;
027    
028    import java.sql.SQLException;
029    
030    
031    /**
032     * An Implementation Class that will retrieve a valid new value
033     * for a PK field that is of type 'uniqueidentifier'. Since values
034     * for these types are generated through a 'newid()' call to
035     * MSSQL Server, this class is only valid for MSSQL Server 7.0 and up.
036     * <br/>
037     * This SequenceManager can be used for any classes that have their PK
038     * defined as a 'uniqueidetifier'
039     *
040     * @author <a href="mailto:aclute825@hotmail.com">Andrew Clute</a>
041     * @version $Id: SequenceManagerMSSQLGuidImpl.java,v 1.1 2007-08-24 22:17:29 ewestfal Exp $
042     */
043    public class SequenceManagerMSSQLGuidImpl extends AbstractSequenceManager
044    {
045        private static final JdbcType JDBC_TYPE_VARCHAR = JdbcTypesHelper.getJdbcTypeByName("varchar");
046        /**
047         * Constructor used by
048         * {@link org.apache.ojb.broker.util.sequence.SequenceManagerFactory}
049         *
050         * @param broker  PB instance to perform the
051         * id generation.
052         */
053        public SequenceManagerMSSQLGuidImpl(PersistenceBroker broker)
054        {
055            super(broker);
056        }
057    
058        public Object getUniqueValue(FieldDescriptor field) throws SequenceManagerException
059        {
060            // only works for VARCHAR fields
061            if(!field.getJdbcType().equals(JDBC_TYPE_VARCHAR))
062            {
063                throw new SequenceManagerException("This implementation only works with fields defined" +
064                        " as VARCHAR, but given field was " + (field != null ? field.getJdbcType() : null));
065            }
066            Object result = getUniqueString(field);
067            // perform a sql to java conversion here, so that clients do
068            // not see any db specific values
069            result = field.getFieldConversion().sqlToJava(result);
070            return result;
071        }
072    
073        /**
074         * returns a unique String for given field.
075         * the returned uid is unique accross all tables.
076         */
077        protected String getUniqueString(FieldDescriptor field) throws SequenceManagerException
078        {
079            ResultSetAndStatement rsStmt = null;
080            String returnValue = null;
081            try
082            {
083                rsStmt = getBrokerForClass().serviceJdbcAccess().executeSQL(
084                        "select newid()", field.getClassDescriptor(), Query.NOT_SCROLLABLE);
085                if (rsStmt.m_rs.next())
086                {
087                    returnValue = rsStmt.m_rs.getString(1);
088                }
089                else
090                {
091                    LoggerFactory.getDefaultLogger().error(this.getClass()
092                            + ": Can't lookup new oid for field " + field);
093                }
094            }
095            catch (PersistenceBrokerException e)
096            {
097                throw new SequenceManagerException(e);
098            }
099            catch (SQLException e)
100            {
101                throw new SequenceManagerException(e);
102            }
103    
104            finally
105            {
106                // close the used resources
107                if (rsStmt != null) rsStmt.close();
108            }
109            return returnValue;
110        }
111    
112        /**
113         * Returns a new unique int for the given Class and fieldname.
114         */
115        protected int getUniqueId(FieldDescriptor field) throws SequenceManagerException
116        {
117            throw new SequenceManagerException(
118                    SystemUtils.LINE_SEPARATOR +
119                    "Failure attempting to retrieve a Guid for a field that is an int -- field should be returned as a VARCHAR");
120        }
121    
122        /**
123         * Returns a new unique int for the given Class and fieldname.
124         */
125        protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException
126        {
127            throw new SequenceManagerException(
128                    SystemUtils.LINE_SEPARATOR +
129                    "Failure attempting to retrieve a Guid for a field that is a long -- field should be returned as a VARCHAR");
130        }
131    
132        // TODO: never used? remove?
133    //    /**
134    //     * returns a unique Object for class clazz and field fieldName.
135    //     * the returned Object is unique accross all tables in the extent of clazz.
136    //     */
137    //    protected Object getUniqueObject(FieldDescriptor field) throws SequenceManagerException
138    //    {
139    //        return getUniqueString(field);
140    //    }
141    }
142