001/*
002 * Copyright 2006-2013 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.batch.core;
018
019import java.io.Serializable;
020
021import org.springframework.util.ClassUtils;
022
023/**
024 * Batch Domain Entity class. Any class that should be uniquely identifiable
025 * from another should subclass from Entity. More information on this pattern
026 * and the difference between Entities and Value Objects can be found in Domain
027 * Driven Design by Eric Evans.
028 *
029 * @author Lucas Ward
030 * @author Dave Syer
031 *
032 */
033@SuppressWarnings("serial")
034public class Entity implements Serializable {
035
036        private Long id;
037
038        private volatile Integer version;
039
040        public Entity() {
041                super();
042        }
043
044        public Entity(Long id) {
045                super();
046
047                //Commented out because StepExecutions are still created in a disconnected
048                //manner.  The Repository should create them, then this can be uncommented.
049                //Assert.notNull(id, "Entity id must not be null.");
050                this.id = id;
051        }
052
053        public Long getId() {
054                return id;
055        }
056
057        public void setId(Long id) {
058                this.id = id;
059        }
060
061        /**
062         * @return the version
063         */
064        public Integer getVersion() {
065                return version;
066        }
067
068        /**
069         * Public setter for the version needed only by repository methods.
070         * @param version the version to set
071         */
072        public void setVersion(Integer version) {
073                this.version = version;
074        }
075
076        /**
077         * Increment the version number
078         */
079        public void incrementVersion() {
080                if (version == null) {
081                        version = 0;
082                } else {
083                        version = version + 1;
084                }
085        }
086
087        @Override
088        public String toString() {
089                return String.format("%s: id=%d, version=%d", ClassUtils.getShortName(getClass()), id, version);
090        }
091
092        /**
093         * Attempt to establish identity based on id if both exist. If either id
094         * does not exist use Object.equals().
095         *
096         * @see java.lang.Object#equals(java.lang.Object)
097         */
098        @Override
099        public boolean equals(Object other) {
100                if (other == this) {
101                        return true;
102                }
103                if (other == null) {
104                        return false;
105                }
106                if (!(other instanceof Entity)) {
107                        return false;
108                }
109                Entity entity = (Entity) other;
110                if (id == null || entity.getId() == null) {
111                        return false;
112                }
113                return id.equals(entity.getId());
114        }
115
116        /**
117         * Use ID if it exists to establish hash code, otherwise fall back to
118         * Object.hashCode(). Based on the same information as equals, so if that
119         * changes, this will. N.B. this follows the contract of Object.hashCode(),
120         * but will cause problems for anyone adding an unsaved {@link Entity} to a
121         * Set because Set.contains() will almost certainly return false for the
122         * {@link Entity} after it is saved. Spring Batch does not store any of its
123         * entities in Sets as a matter of course, so internally this is consistent.
124         * Clients should not be exposed to unsaved entities.
125         *
126         * @see java.lang.Object#hashCode()
127         */
128        @Override
129        public int hashCode() {
130                if (id == null) {
131                        return super.hashCode();
132                }
133                return 39 + 87 * id.hashCode();
134        }
135
136}