LocationPK.java
/*
* Copyright 2005-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openwms.common.location;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.validation.constraints.Size;
import org.springframework.util.Assert;
import java.io.Serializable;
/**
* A LocationPK, is a value type and is used as an unique natural key for {@link Location} entities.
*
* @author Heiko Scherrer
* @see Location
*/
@Embeddable
public class LocationPK implements Serializable {
public static final short KEY_LENGTH = 4;
public static final short NUMBER_OF_KEYS = 5;
/**
* Returns the complete length of all keys. Currently, all keys have the same length, therefore it is the 5 times the length of a single
* key (KEY_LENGTH). But since this can change the actual length is encapsulated within this method.
*/
public static final short PK_LENGTH = NUMBER_OF_KEYS * KEY_LENGTH;
/** Expresses the area the {@link Location} belongs to. */
@Column(name = "C_AREA", nullable = false, length = KEY_LENGTH)
@Size(max = KEY_LENGTH)
private String area;
/** Expresses the aisle the {@link Location} belongs to. */
@Column(name = "C_AISLE", nullable = false, length = KEY_LENGTH)
@Size(max = KEY_LENGTH)
private String aisle;
/** Expresses the x-dimension the {@link Location} belongs to. */
@Column(name = "C_X", nullable = false, length = KEY_LENGTH)
@Size(max = KEY_LENGTH)
private String x;
/** Expresses the y-dimension the {@link Location} belongs to. */
@Column(name = "C_Y", nullable = false, length = KEY_LENGTH)
@Size(max = KEY_LENGTH)
private String y;
/** Expresses the z-dimension the {@link Location} belongs to. */
@Column(name = "C_Z", nullable = false, length = KEY_LENGTH)
@Size(max = KEY_LENGTH)
private String z;
/*~ ----------------------------- constructors ------------------- */
/** Dear JPA ... */
protected LocationPK() { }
/**
* Create a new LocationPK with all required fields.
*
* @param area Area where the {@link Location} belongs to
* @param aisle Aisle where the {@link Location} belongs to
* @param x Dimension x where the {@link Location} belongs to
* @param y Dimension y where the {@link Location} belongs to
* @param z Dimension z where the {@link Location} belongs to
*/
public static LocationPK of(String area, String aisle, String x, String y, String z) {
return new LocationPK(area, aisle, x, y, z);
}
/**
* Weak constructor to create a new LocationPK with a couple of keys only.
*
* @param keys The array of keys, currently expected to be 5
* @throws IllegalArgumentException if the number of keys does not match {@link LocationPK#NUMBER_OF_KEYS}
*/
private LocationPK(String... keys) {
if (keys == null || keys.length != NUMBER_OF_KEYS) {
throw new IllegalArgumentException(
"Number of key fields to create a LocationPK does not match the defined number of keys. Expected: " + NUMBER_OF_KEYS);
}
this.area = keys[0];
this.aisle = keys[1];
this.x = keys[2];
this.y = keys[3];
this.z = keys[4];
}
/**
* Create a {@link LocationPK} from the given String.
*
* @param s The String, not {@literal null}
* @return An instance
*/
public static LocationPK fromString(String s) {
Assert.hasText(s, "Location String must not be null");
return new LocationPK(s.split("/"));
}
/**
* Checks whether the given {@code locationPK} String is in valid format.
*
* @param locationPk The String to verify
* @return {@literal true} if valid
*/
public static boolean isValid(String locationPk) {
return locationPk != null && locationPk.split("/").length == NUMBER_OF_KEYS;
}
/*~ ----------------------------- methods ------------------- */
/**
* Get the area region.
*
* @return The area
*/
public String getArea() {
return this.area;
}
/**
* Get the aisle region.
*
* @return The aisle
*/
public String getAisle() {
return this.aisle;
}
/**
* Get the x-dimension.
*
* @return The x-dimension
*/
public String getX() {
return this.x;
}
/**
* Get the y-dimension.
*
* @return The y-dimension
*/
public String getY() {
return this.y;
}
/**
* Get the z-dimension.
*
* @return The z-dimension
*/
public String getZ() {
return this.z;
}
/**
* {@inheritDoc}
*
* @see Object#equals(Object)
*/
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof LocationPK other)) {
return false;
}
return this.y.equals(other.y) && this.x.equals(other.x) && this.area.equals(other.area)
&& this.z.equals(other.z) && this.aisle.equals(other.aisle);
}
/**
* {@inheritDoc}
*
* @see Object#hashCode()
*/
@Override
public int hashCode() {
return this.y.hashCode() ^ this.x.hashCode() ^ this.area.hashCode() ^ this.z.hashCode() ^ this.aisle.hashCode();
}
/**
* Return a String like AREA/AISLE/X/Y/Z.
*
* @return String
* @see Object#toString()
*/
@Override
public String toString() {
return this.area + "/" + this.aisle + "/" + this.x + "/" + this.y + "/" + this.z;
}
}