Commit 18524efc authored by Matija Obreza's avatar Matija Obreza
Browse files

Trim all Strings to null before persisting or updating an entity

parent accd8c1e
......@@ -45,6 +45,7 @@ import org.genesys.catalog.annotations.PublishValidation;
import org.genesys.catalog.model.traits.Descriptor;
import org.genesys.catalog.service.PublishValidationInterface;
import org.genesys.common.model.Partner;
import org.genesys.common.model.SelfCleaning;
import org.genesys.filerepository.model.RepositoryFile;
import com.fasterxml.jackson.annotation.JsonIgnore;
......@@ -61,7 +62,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
@Cacheable
@Table(name = "dataset")
@Audited
public class Dataset extends UuidModel implements Publishable, PublishValidationInterface, AclAwareModel {
public class Dataset extends UuidModel implements Publishable, SelfCleaning, PublishValidationInterface, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -4601980446454791177L;
......@@ -175,6 +176,8 @@ public class Dataset extends UuidModel implements Publishable, PublishValidation
if (descriptors != null) {
this.descriptorCount = descriptors.size();
}
trimStringsToNull();
}
/**
......
......@@ -32,6 +32,8 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
......@@ -43,6 +45,7 @@ import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.catalog.model.vocab.ControlledVocabulary;
import org.genesys.catalog.model.vocab.VocabularyTerm;
import org.genesys.common.model.Partner;
import org.genesys.common.model.SelfCleaning;
import org.springframework.dao.DataIntegrityViolationException;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
......@@ -60,7 +63,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@Table(name = "descriptor")
@Audited
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
public class Descriptor extends UuidModel implements Publishable, Copyable<Descriptor>, AclAwareModel {
public class Descriptor extends UuidModel implements SelfCleaning, Publishable, Copyable<Descriptor>, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 7307818236681549484L;
......@@ -212,6 +215,15 @@ public class Descriptor extends UuidModel implements Publishable, Copyable<Descr
*/
public Descriptor() {
}
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Instantiates a new descriptor.
......
......@@ -28,6 +28,8 @@ import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OrderColumn;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import org.genesys.blocks.auditlog.annotations.Audited;
......@@ -35,6 +37,7 @@ import org.genesys.blocks.model.Publishable;
import org.genesys.blocks.model.UuidModel;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.common.model.Partner;
import org.genesys.common.model.SelfCleaning;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
......@@ -49,7 +52,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@Audited
@Cacheable
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
public class DescriptorList extends UuidModel implements Publishable, AclAwareModel {
public class DescriptorList extends UuidModel implements Publishable, SelfCleaning, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 4873500390485739013L;
......@@ -98,6 +101,15 @@ public class DescriptorList extends UuidModel implements Publishable, AclAwareMo
@Column(name = "crop", length = 100, nullable = true)
private String crop;
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Gets the publisher.
*
......
......@@ -27,12 +27,15 @@ import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderColumn;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.UniqueConstraint;
import org.genesys.blocks.model.Publishable;
import org.genesys.blocks.model.UuidModel;
import org.genesys.blocks.security.model.AclAwareModel;
import org.genesys.common.model.Partner;
import org.genesys.common.model.SelfCleaning;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
......@@ -48,7 +51,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators;
*/
@Entity
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
public class ControlledVocabulary extends UuidModel implements Publishable, AclAwareModel {
public class ControlledVocabulary extends UuidModel implements Publishable, SelfCleaning, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 7307818236681549484L;
......@@ -100,7 +103,16 @@ public class ControlledVocabulary extends UuidModel implements Publishable, AclA
@ManyToOne(cascade = {}, optional = false)
@JoinColumn(name = "partnerId", updatable = false)
private Partner owner;
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Gets the owner.
*
......
......@@ -20,9 +20,12 @@ import java.text.MessageFormat;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import org.genesys.blocks.model.BasicModel;
import org.genesys.common.model.SelfCleaning;
/**
* A single vocabulary term, belonging to a {@link ControlledVocabulary}.
......@@ -39,7 +42,7 @@ import org.genesys.blocks.model.BasicModel;
*/
@Entity
@Table(name = "Term")
public class VocabularyTerm extends BasicModel {
public class VocabularyTerm extends BasicModel implements SelfCleaning {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 6568957772654494563L;
......@@ -60,6 +63,15 @@ public class VocabularyTerm extends BasicModel {
@Lob
private String description;
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Gets the code.
*
......
......@@ -18,6 +18,8 @@ package org.genesys.common.model;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import org.genesys.blocks.auditlog.annotations.Audited;
......@@ -31,56 +33,65 @@ import org.genesys.blocks.security.model.AclAwareModel;
@Cacheable
@Table(name = "crop")
@Audited
public class Crop extends UuidModel implements AclAwareModel {
public class Crop extends UuidModel implements SelfCleaning, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -7077656710175508039L;
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -7077656710175508039L;
/**
* crop code
*/
@Column(length = 50, nullable = false)
private String code;
/**
* crop code
*/
@Column(length = 50, nullable = false)
private String code;
/**
* title in English
*/
@Column(length = 255, nullable = false)
private String title;
/**
* title in English
*/
@Column(length = 255, nullable = false)
private String title;
/**
* Gets the code.
*
* @return the code of crop.
*/
public String getCode() {
return code;
}
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Sets the code.
*
* @param code of crop
*/
public void setCode(final String code) {
this.code = code;
}
/**
* Gets the code.
*
* @return the code of crop.
*/
public String getCode() {
return code;
}
/**
* Gets the title.
*
* @return the title of crop
*/
public String getTitle() {
return title;
}
/**
* Sets the code.
*
* @param code of crop
*/
public void setCode(final String code) {
this.code = code;
}
/**
* Sets the title.
*
* @param title of crop
*/
public void setTitle(final String title) {
this.title = title;
}
/**
* Gets the title.
*
* @return the title of crop
*/
public String getTitle() {
return title;
}
/**
* Sets the title.
*
* @param title of crop
*/
public void setTitle(final String title) {
this.title = title;
}
}
......@@ -30,6 +30,8 @@ import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.OneToMany;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
......@@ -52,7 +54,7 @@ import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@Cacheable
@Table(name = "partner")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "uuid")
public class Partner extends UuidModel implements AclAwareModel {
public class Partner extends UuidModel implements SelfCleaning, AclAwareModel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 7972197553356837382L;
......@@ -98,6 +100,15 @@ public class Partner extends UuidModel implements AclAwareModel {
@OneToMany(cascade = { CascadeType.REMOVE }, orphanRemoval = true, mappedBy = "owner", fetch = FetchType.LAZY)
private List<DescriptorList> descriptorList;
/**
* Pre-persist, pre-update
*/
@PrePersist
@PreUpdate
private void preupdate() {
trimStringsToNull();
}
/**
* Instantiates a new partner.
*/
......@@ -236,7 +247,7 @@ public class Partner extends UuidModel implements AclAwareModel {
public Set<String> getCountryCodes() {
return countryCodes;
}
/**
* Sets the country codes.
*
......@@ -245,7 +256,7 @@ public class Partner extends UuidModel implements AclAwareModel {
public void setCountryCodes(Set<String> countryCodes) {
this.countryCodes = countryCodes;
}
/**
* Gets the descriptors.
*
......
/*
* Copyright 2018 Global Crop Diversity Trust
*
* 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.genesys.common.model;
import java.lang.reflect.Modifier;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldFilter;
/**
* Automatically trims all strings down to null on persist or merge.
*
* @author Matija Obreza
*/
public interface SelfCleaning {
default void trimStringsToNull() {
// System.err.println("Self-cleanup of " + this);
ReflectionUtils.doWithFields(this.getClass(), field -> {
if (Modifier.isPrivate(field.getModifiers()) || Modifier.isProtected(field.getModifiers()) || Modifier.isPublic(field.getModifiers())) {
ReflectionUtils.makeAccessible(field);
// System.err.println(field + " is made accessible, modifiers = " +
// field.getModifiers());
}
final String srcValue = (String) field.get(this);
if (srcValue != null) {
field.set(this, StringUtils.trimToNull(srcValue));
// System.err.println(field + " cleaned");
}
}, STRING_FIELDS);
}
/**
* FieldFilter that matches all non-static, non-final, strings
* fields.
*/
public static final FieldFilter STRING_FIELDS = field -> {
// is string, not static or final
return field.getType().equals(String.class) && !(Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers()));
};
}
......@@ -318,12 +318,12 @@ public class ControlledVocabularyTest extends CatalogServiceTest {
vocab1.setOwner(partner);
vocab1.setTerms(Lists.newArrayList(
/*@formatter:off*/
VocabularyTerm.fromData("a", ""),
VocabularyTerm.fromData("b", ""),
VocabularyTerm.fromData("c", ""),
VocabularyTerm.fromData("aa", ""),
VocabularyTerm.fromData("aaa", ""),
VocabularyTerm.fromData("ab", "")
VocabularyTerm.fromData("a", "a"),
VocabularyTerm.fromData("b", "b"),
VocabularyTerm.fromData("c", "c"),
VocabularyTerm.fromData("aa", "aa"),
VocabularyTerm.fromData("aaa", "aaa"),
VocabularyTerm.fromData("ab", "ab")
/*@formatter:on */
));
......@@ -345,12 +345,12 @@ public class ControlledVocabularyTest extends CatalogServiceTest {
vocab1.setOwner(partner);
vocab1.setTerms(Lists.newArrayList(
/*@formatter:off*/
VocabularyTerm.fromData("a", ""),
VocabularyTerm.fromData("b", ""),
VocabularyTerm.fromData("c", ""),
VocabularyTerm.fromData("aa", ""),
VocabularyTerm.fromData("aaa", ""),
VocabularyTerm.fromData("ab", "")
VocabularyTerm.fromData("a", "a"),
VocabularyTerm.fromData("b", "b"),
VocabularyTerm.fromData("c", "c"),
VocabularyTerm.fromData("aa", "aa"),
VocabularyTerm.fromData("aaa", "aaa"),
VocabularyTerm.fromData("ab", "ab")
/*@formatter:on */
));
......
......@@ -66,6 +66,20 @@ public class DatasetServiceTest extends AbstractDatasetServiceTest {
assertThat(input.getVersions().getCurrentVersion(), is(input));
}
@Test
public void testCreateDatasetSelfCleaning() {
Dataset input = buildAndSaveDataset(DATASET_TITLE_1 + " ", " " + DATASET_DESCRIPTION_1, partner, false);
assertThat(input, not(nullValue()));
assertThat(input.getTitle(), is(DATASET_TITLE_1));
assertThat(input.getDescription(), is(DATASET_DESCRIPTION_1));
input.setTitle(" \t " + DATASET_TITLE_2 + " \t");
input.setDescription(" \t " + DATASET_DESCRIPTION_2 + " \t ");
input = datasetService.updateDataset(input);
assertThat(input.getTitle(), is(DATASET_TITLE_2));
assertThat(input.getDescription(), is(DATASET_DESCRIPTION_2));
}
@Test
public void testCreateDatasetIsUnpublished() {
Dataset input = buildAndSaveDataset(DATASET_TITLE_1, DATASET_DESCRIPTION_1, partner, false);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment