001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.jdbc.support.incrementer;
018
019import javax.sql.DataSource;
020
021import org.springframework.beans.factory.InitializingBean;
022import org.springframework.dao.DataAccessException;
023import org.springframework.util.Assert;
024
025/**
026 * Base implementation of {@link DataFieldMaxValueIncrementer} that delegates
027 * to a single {@link #getNextKey} template method that returns a {@code long}.
028 * Uses longs for String values, padding with zeroes if required.
029 *
030 * @author Dmitriy Kopylenko
031 * @author Juergen Hoeller
032 * @author Jean-Pierre Pawlak
033 * @author Juergen Hoeller
034 */
035public abstract class AbstractDataFieldMaxValueIncrementer implements DataFieldMaxValueIncrementer, InitializingBean {
036
037        private DataSource dataSource;
038
039        /** The name of the sequence/table containing the sequence */
040        private String incrementerName;
041
042        /** The length to which a string result should be pre-pended with zeroes */
043        protected int paddingLength = 0;
044
045
046        /**
047         * Default constructor for bean property style usage.
048         * @see #setDataSource
049         * @see #setIncrementerName
050         */
051        public AbstractDataFieldMaxValueIncrementer() {
052        }
053
054        /**
055         * Convenience constructor.
056         * @param dataSource the DataSource to use
057         * @param incrementerName the name of the sequence/table to use
058         */
059        public AbstractDataFieldMaxValueIncrementer(DataSource dataSource, String incrementerName) {
060                Assert.notNull(dataSource, "DataSource must not be null");
061                Assert.notNull(incrementerName, "Incrementer name must not be null");
062                this.dataSource = dataSource;
063                this.incrementerName = incrementerName;
064        }
065
066
067        /**
068         * Set the data source to retrieve the value from.
069         */
070        public void setDataSource(DataSource dataSource) {
071                this.dataSource = dataSource;
072        }
073
074        /**
075         * Return the data source to retrieve the value from.
076         */
077        public DataSource getDataSource() {
078                return this.dataSource;
079        }
080
081        /**
082         * Set the name of the sequence/table.
083         */
084        public void setIncrementerName(String incrementerName) {
085                this.incrementerName = incrementerName;
086        }
087
088        /**
089         * Return the name of the sequence/table.
090         */
091        public String getIncrementerName() {
092                return this.incrementerName;
093        }
094
095        /**
096         * Set the padding length, i.e. the length to which a string result
097         * should be pre-pended with zeroes.
098         */
099        public void setPaddingLength(int paddingLength) {
100                this.paddingLength = paddingLength;
101        }
102
103        /**
104         * Return the padding length for String values.
105         */
106        public int getPaddingLength() {
107                return this.paddingLength;
108        }
109
110        @Override
111        public void afterPropertiesSet() {
112                if (this.dataSource == null) {
113                        throw new IllegalArgumentException("Property 'dataSource' is required");
114                }
115                if (this.incrementerName == null) {
116                        throw new IllegalArgumentException("Property 'incrementerName' is required");
117                }
118        }
119
120
121        @Override
122        public int nextIntValue() throws DataAccessException {
123                return (int) getNextKey();
124        }
125
126        @Override
127        public long nextLongValue() throws DataAccessException {
128                return getNextKey();
129        }
130
131        @Override
132        public String nextStringValue() throws DataAccessException {
133                String s = Long.toString(getNextKey());
134                int len = s.length();
135                if (len < this.paddingLength) {
136                        StringBuilder sb = new StringBuilder(this.paddingLength);
137                        for (int i = 0; i < this.paddingLength - len; i++) {
138                                sb.append('0');
139                        }
140                        sb.append(s);
141                        s = sb.toString();
142                }
143                return s;
144        }
145
146
147        /**
148         * Determine the next key to use, as a long.
149         * @return the key to use as a long. It will eventually be converted later
150         * in another format by the public concrete methods of this class.
151         */
152        protected abstract long getNextKey();
153
154}