/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.common.entities;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.hibernate.NonUniqueResultException;
import javax.validation.constraints.AssertTrue;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import org.libreplan.business.common.BaseEntity;
import org.libreplan.business.common.IntegrationEntity;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.IEntitySequenceDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
/**
* Sequence for {@link IntegrationEntity} codes.
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public class EntitySequence extends BaseEntity {
public static final Integer MIN_NUMBER_OF_DIGITS = 2;
public static final Integer MAX_NUMBER_OF_DIGITS = 9;
public static final String CODE_SEPARATOR_CHILDREN = "-";
public static EntitySequence create(String prefix, EntityNameEnum entityName) {
return create(new EntitySequence(prefix, entityName));
}
public static EntitySequence create(String prefix, EntityNameEnum entityName, Integer digits) {
return create(new EntitySequence(prefix, entityName, digits));
}
/**
* Constructor for hibernate. Do not use!
*/
public EntitySequence() {
}
public EntitySequence(String prefix, EntityNameEnum entityName) {
this.prefix = prefix;
this.entityName = entityName;
}
public EntitySequence(String prefix, EntityNameEnum entityName, Integer digits) {
this.prefix = prefix;
this.entityName = entityName;
this.setNumberOfDigits(digits);
}
private String prefix;
private EntityNameEnum entityName;
private Integer lastValue = 0;
private Integer numberOfDigits = 4;
private Boolean active = false;
public void setPrefix(String prefix) throws IllegalArgumentException {
if (isAlreadyInUse()) {
throw new IllegalArgumentException("You cannot modifiy this entity sequence, it is already in use");
}
this.prefix = prefix;
}
@NotEmpty(message = "prefix not specified")
public String getPrefix() {
if (prefix != null) {
prefix = prefix.trim();
}
return prefix;
}
@NotNull(message = "last value not specified")
public Integer getLastValue() {
return lastValue;
}
@AssertTrue(message = "Prefix cannot contain whitespaces")
public boolean isPrefixWithoutWhiteSpacesConstraint() {
if ((prefix == null) || (prefix.isEmpty())) {
return false;
}
return !prefix.contains(" ");
}
public void setActive(Boolean active) {
this.active = active;
}
public Boolean isActive() {
return active;
}
public void setNumberOfDigits(Integer numberOfDigits) throws IllegalArgumentException {
if (isAlreadyInUse()) {
throw new IllegalArgumentException("You cannot modifiy this entity sequence, it is already in use");
}
if ( (numberOfDigits != null)
&& (numberOfDigits >= MIN_NUMBER_OF_DIGITS)
&& (numberOfDigits <= MAX_NUMBER_OF_DIGITS) ) {
this.numberOfDigits = numberOfDigits;
} else {
throw new IllegalArgumentException(
"number of digits must be between " + MIN_NUMBER_OF_DIGITS + " and " + MAX_NUMBER_OF_DIGITS);
}
}
@NotNull(message = "number of digits not specified")
public Integer getNumberOfDigits() {
return numberOfDigits;
}
@AssertTrue(message = "number of digits out of range")
public boolean isNumberOfDigitsInRangeConstraint() {
return (numberOfDigits != null)
&& (numberOfDigits >= MIN_NUMBER_OF_DIGITS)
&& (numberOfDigits <= MAX_NUMBER_OF_DIGITS);
}
@AssertTrue(message = "format sequence code invalid. It must not contain '_'")
public boolean isWithoutLowBarConstraint() {
if ((prefix == null) || (prefix.isEmpty())) {
return false;
}
if ((entityName != null) && (entityName.canContainLowBar())) {
return true;
} else {
if (prefix.contains("_")) {
return false;
}
return true;
}
}
public static String formatValue(int numberOfDigits, int value) {
String format = "";
for (int i = 0; i < numberOfDigits; i++) {
format += "0";
}
NumberFormat numberFormat = new DecimalFormat(format);
return numberFormat.format(value);
}
public boolean isAlreadyInUse() {
return lastValue > 0;
}
public String getCode() {
return prefix + formatValue(numberOfDigits, lastValue);
}
public void incrementLastValue() {
lastValue++;
}
@NotNull(message = "entity name not specified")
public EntityNameEnum getEntityName() {
return entityName;
}
public void setEntityName(EntityNameEnum entityName) {
this.entityName = entityName;
}
@AssertTrue(message = "Only one sequence per entity can be active at the same time.")
public boolean isOnlyOneSequenceForEachEntityIsActiveConstraint() {
if (!isActive()) {
return true;
}
IEntitySequenceDAO entitySequenceDAO = Registry.getEntitySequenceDAO();
if (isNewObject()) {
return !entitySequenceDAO.existOtherActiveSequenceByEntityNameForNewObject(this);
} else {
try {
return entitySequenceDAO.getActiveEntitySequence(this.entityName).getId().equals(getId());
} catch (NonUniqueResultException e) {
return false;
} catch (InstanceNotFoundException e) {
return true;
}
}
}
}