Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: content property now uses setAutoGrowNestedPaths when setting ccontent #1510

Merged
merged 2 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,12 @@ public S unsetContent(S entity, PropertyPath propertyPath, UnsetContentParams pa
}

// reset content fields
property.setContentId(entity, null, new org.springframework.content.commons.mappingcontext.Condition() {
@Override
public boolean matches(TypeDescriptor descriptor) {
for (Annotation annotation : descriptor.getAnnotations()) {
if ("jakarta.persistence.Id".equals(
if (resource != null) {
property.setContentId(entity, null, new org.springframework.content.commons.mappingcontext.Condition() {
@Override
public boolean matches(TypeDescriptor descriptor) {
for (Annotation annotation : descriptor.getAnnotations()) {
if ("jakarta.persistence.Id".equals(
annotation.annotationType().getCanonicalName())
|| "org.springframework.data.annotation.Id"
.equals(annotation.annotationType()
Expand All @@ -509,7 +510,8 @@ public boolean matches(TypeDescriptor descriptor) {
}
});

property.setContentLength(entity, 0);
property.setContentLength(entity, 0);
}

return entity;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
package internal.org.springframework.content.azure.it;

import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.*;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import com.azure.storage.blob.specialized.BlockBlobClient;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import javax.sql.DataSource;

import com.azure.core.http.rest.PagedIterable;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.azure.storage.blob.models.BlobItem;
import com.github.paulcwarren.ginkgo4j.Ginkgo4jConfiguration;
import com.github.paulcwarren.ginkgo4j.Ginkgo4jRunner;
import jakarta.persistence.*;
import lombok.*;
import net.bytebuddy.utility.RandomString;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.junit.Assert;
Expand Down Expand Up @@ -51,19 +38,19 @@
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import com.azure.core.http.rest.PagedIterable;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.BlobServiceClientBuilder;
import com.azure.storage.blob.models.BlobItem;
import com.github.paulcwarren.ginkgo4j.Ginkgo4jConfiguration;
import com.github.paulcwarren.ginkgo4j.Ginkgo4jRunner;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.bytebuddy.utility.RandomString;
import static com.github.paulcwarren.ginkgo4j.Ginkgo4jDSL.*;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;

@RunWith(Ginkgo4jRunner.class)
@Ginkgo4jConfiguration(threads=1)
Expand All @@ -90,6 +77,9 @@ public class AzureStorageIT {
private TestEntityRepository repo;
private TestEntityStore store;

private EmbeddedRepository embeddedRepo;
private EmbeddedStore embeddedStore;

private String resourceLocation;

{
Expand All @@ -103,6 +93,9 @@ public class AzureStorageIT {
repo = context.getBean(TestEntityRepository.class);
store = context.getBean(TestEntityStore.class);

embeddedRepo = context.getBean(EmbeddedRepository.class);
embeddedStore = context.getBean(EmbeddedStore.class);

RandomString random = new RandomString(5);
resourceLocation = random.nextString();
});
Expand Down Expand Up @@ -521,6 +514,29 @@ public class AzureStorageIT {
// });
// });

Context("@Embedded content", () -> {
Context("given a entity with a null embedded content object", () -> {
It("should return null when content is fetched", () -> {
EntityWithEmbeddedContent entity = embeddedRepo.save(new EntityWithEmbeddedContent());
assertThat(embeddedStore.getContent(entity, PropertyPath.from("content")), is(nullValue()));
});

It("should be successful when content is set", () -> {
EntityWithEmbeddedContent entity = embeddedRepo.save(new EntityWithEmbeddedContent());
embeddedStore.setContent(entity, PropertyPath.from("content"), new ByteArrayInputStream("Hello Spring Content World!".getBytes()));
try (InputStream is = embeddedStore.getContent(entity, PropertyPath.from("content"))) {
assertThat(IOUtils.contentEquals(is, new ByteArrayInputStream("Hello Spring Content World!".getBytes())), is(true));
}
});

It("should return null when content is unset", () -> {
EntityWithEmbeddedContent entity = embeddedRepo.save(new EntityWithEmbeddedContent());
EntityWithEmbeddedContent expected = new EntityWithEmbeddedContent(entity.getId(), entity.getContent());
assertThat(embeddedStore.unsetContent(entity, PropertyPath.from("content")), is(expected));
int i = 0;
});
});
});
});
});
}
Expand Down Expand Up @@ -637,5 +653,33 @@ public interface SharedIdStore extends ContentStore<SharedIdContentIdEntity, Str
//
// public interface SharedSpringIdRepository extends JpaRepository<SharedSpringIdContentIdEntity, String> {}
// public interface SharedSpringIdStore extends ContentStore<SharedSpringIdContentIdEntity, String> {}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="entity_with_embedded")
public static class EntityWithEmbeddedContent {

@Id
private String id = UUID.randomUUID().toString();

@Embedded
private EmbeddedContent content;
}

@Embeddable
@NoArgsConstructor
@Data
public static class EmbeddedContent {

@ContentId
private String contentId;

@ContentLength
private Long contentLen;
}

public interface EmbeddedRepository extends JpaRepository<EntityWithEmbeddedContent, String> {}
public interface EmbeddedStore extends ContentStore<EntityWithEmbeddedContent, String> {}
}
// EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.NullValueInNestedPathException;
import org.springframework.core.convert.TypeDescriptor;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.Assert;

@Getter
@Setter
Expand All @@ -16,21 +18,26 @@ public class ContentProperty {

private String contentPropertyPath;
private String contentIdPropertyPath;
private TypeDescriptor contentIdType;
private String contentLengthPropertyPath;
private String mimeTypePropertyPath;
private String originalFileNamePropertyPath;

public Object getCustomProperty(Object entity, String propertyName) {
String customContentPropertyPath = contentPropertyPath + StringUtils.capitalize(propertyName);

BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyValue(customContentPropertyPath);
BeanWrapper wrapper = getBeanWrapperForRead(entity);
try {
return wrapper.getPropertyValue(customContentPropertyPath);
} catch (NullValueInNestedPathException nvinpe) {
return null;
}
}

public void setCustomProperty(Object entity, String propertyName, Object value) {
String customContentPropertyPath = contentPropertyPath + StringUtils.capitalize(propertyName);

BeanWrapper wrapper = new BeanWrapperImpl(entity);
BeanWrapper wrapper = getBeanWrapperForWrite(entity);
wrapper.setPropertyValue(customContentPropertyPath, value);
}

Expand All @@ -39,16 +46,20 @@ public Object getContentId(Object entity) {
return null;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyValue(contentIdPropertyPath);
BeanWrapper wrapper = getBeanWrapperForRead(entity);
try {
return wrapper.getPropertyValue(contentIdPropertyPath);
} catch (NullValueInNestedPathException nvinpe) {
return null;
}
}

public void setContentId(Object entity, Object value, Condition condition) {
if (contentIdPropertyPath == null) {
return;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
BeanWrapper wrapper = getBeanWrapperForWrite(entity);

if (condition != null) {
TypeDescriptor t = wrapper.getPropertyTypeDescriptor(contentIdPropertyPath);
Expand All @@ -61,29 +72,38 @@ public void setContentId(Object entity, Object value, Condition condition) {
}

public TypeDescriptor getContentIdType(Object entity) {
if (contentIdPropertyPath == null) {
return null;
}
Assert.notNull(this.contentIdType, "content id property type must be set");
return this.contentIdType;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyTypeDescriptor(contentIdPropertyPath);
public TypeDescriptor getContentIdType() {
Assert.notNull(this.contentIdType, "content id property type must be set");
return this.contentIdType;
}

public void setContentIdType(TypeDescriptor descriptor) {
this.contentIdType = descriptor;
}

public Object getContentLength(Object entity) {
if (contentLengthPropertyPath == null) {
return 0L;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyValue(contentLengthPropertyPath);
BeanWrapper wrapper = getBeanWrapperForRead(entity);
try {
return wrapper.getPropertyValue(contentLengthPropertyPath);
} catch (NullValueInNestedPathException nvinpe) {
return null;
}
}

public void setContentLength(Object entity, Object value) {
if (contentLengthPropertyPath == null) {
return;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
BeanWrapper wrapper = getBeanWrapperForWrite(entity);
wrapper.setPropertyValue(contentLengthPropertyPath, value);
}

Expand All @@ -92,16 +112,20 @@ public Object getMimeType(Object entity) {
return null;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyValue(mimeTypePropertyPath);
BeanWrapper wrapper = getBeanWrapperForRead(entity);
try {
return wrapper.getPropertyValue(mimeTypePropertyPath);
} catch (NullValueInNestedPathException nvinpe) {
return null;
}
}

public void setMimeType(Object entity, Object value) {
if (mimeTypePropertyPath == null) {
return;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
BeanWrapper wrapper = getBeanWrapperForWrite(entity);
wrapper.setPropertyValue(mimeTypePropertyPath, value);
}

Expand All @@ -110,7 +134,7 @@ public void setOriginalFileName(Object entity, Object value) {
return;
}

BeanWrapper wrapper = new BeanWrapperImpl(entity);
BeanWrapper wrapper = getBeanWrapperForWrite(entity);
wrapper.setPropertyValue(originalFileNamePropertyPath, value);
}

Expand All @@ -119,7 +143,22 @@ public Object getOriginalFileName(Object entity) {
return null;
}

BeanWrapper wrapper = getBeanWrapperForRead(entity);
try {
return wrapper.getPropertyValue(originalFileNamePropertyPath);
} catch (NullValueInNestedPathException nvinpe) {
return null;
}
}

private BeanWrapper getBeanWrapperForRead(Object entity) {
BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper;
}

private BeanWrapper getBeanWrapperForWrite(Object entity) {
BeanWrapper wrapper = new BeanWrapperImpl(entity);
return wrapper.getPropertyValue(originalFileNamePropertyPath);
wrapper.setAutoGrowNestedPaths(true);
return wrapper;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.springframework.content.commons.annotations.ContentLength;
import org.springframework.content.commons.annotations.MimeType;
import org.springframework.content.commons.annotations.OriginalFileName;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.util.StringUtils;

import lombok.Getter;
Expand Down Expand Up @@ -82,6 +83,7 @@ public boolean visitClassEnd(String path, Class<?> klazz) {
if (property.getContentIdPropertyPath() != null) {
contentProperty.setContentPropertyPath(property.getContentPropertyPath());
contentProperty.setContentIdPropertyPath(property.getContentIdPropertyPath());
contentProperty.setContentIdType(property.getContentIdType());
}
if (property.getContentLengthPropertyPath() != null) {
contentProperty.setContentLengthPropertyPath(property.getContentLengthPropertyPath());
Expand Down Expand Up @@ -122,6 +124,7 @@ public boolean visitField(String path, Class<?> klazz, Field f) {
}
updateContentProperty(property::setContentPropertyPath, fullyQualify(path, this.propertyName(f.getName()), this.getContentPropertySeparator()));
updateContentProperty(property::setContentIdPropertyPath, fullyQualify(path, f.getName(), this.getContentPropertySeparator()));
property.setContentIdType(TypeDescriptor.valueOf(f.getType()));
}
} else if (f.isAnnotationPresent(ContentLength.class)) {
LOGGER.trace(String.format("%s.%s is @ContentLength", f.getDeclaringClass().getCanonicalName(), f.getName()));
Expand Down
Loading