/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.itest.content; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.jdom.Document; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import com.enonic.cms.framework.xml.XMLDocumentFactory; import com.enonic.cms.core.content.ContentEntity; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.content.ContentService; import com.enonic.cms.core.content.ContentStatus; import com.enonic.cms.core.content.ContentVersionEntity; import com.enonic.cms.core.content.ContentVersionKey; import com.enonic.cms.core.content.RelatedContentEntity; import com.enonic.cms.core.content.command.CreateContentCommand; import com.enonic.cms.core.content.command.UpdateContentCommand; import com.enonic.cms.core.content.contentdata.custom.CustomContentData; import com.enonic.cms.core.content.contentdata.custom.contentkeybased.RelatedContentDataEntry; import com.enonic.cms.core.content.contentdata.custom.stringbased.TextDataEntry; import com.enonic.cms.core.content.contenttype.ContentHandlerName; import com.enonic.cms.core.content.contenttype.ContentTypeConfigBuilder; import com.enonic.cms.core.security.PortalSecurityHolder; import com.enonic.cms.core.security.user.User; import com.enonic.cms.core.security.user.UserType; import com.enonic.cms.itest.AbstractSpringTest; import com.enonic.cms.itest.util.DomainFactory; import com.enonic.cms.itest.util.DomainFixture; import com.enonic.cms.store.dao.ContentDao; import static org.junit.Assert.*; public class ContentServiceImpl_storeRelatedContentTest extends AbstractSpringTest { @Autowired protected ContentDao contentDao; @Autowired protected ContentService contentService; private DomainFactory factory; @Autowired private DomainFixture fixture; private ContentKey related1; private ContentKey related2; private ContentKey related3; @Before public void setUp() { factory = fixture.getFactory(); // setup needed common data for each test fixture.initSystemData(); fixture.createAndStoreUserAndUserGroup( "testuser", "testuser fullname", UserType.NORMAL, "testuserstore" ); //SecurityHolder.setUser( findUserByName( User.ANONYMOUS_UID ).getKey() ); PortalSecurityHolder.setAnonUser( fixture.findUserByName( User.ANONYMOUS_UID ).getKey() ); fixture.save( factory.createContentHandler( "Custom content", ContentHandlerName.CUSTOM.getHandlerClassShortName() ) ); fixture.flushAndClearHibernateSession(); // setup content type ContentTypeConfigBuilder ctyconf = new ContentTypeConfigBuilder( "MyRelatedTypes", "title" ); ctyconf.startBlock( "MyRelatedTypes" ); ctyconf.addInput( "title", "text", "contentdata/title", "Title", true ); ctyconf.addRelatedContentInput( "mySingleRelatedToBeUnmodified", "contentdata/mySingleRelatedToBeUnmodified", "My related1", false, false ); ctyconf.addRelatedContentInput( "mySingleRelatedToBeModified", "contentdata/mySingleRelatedToBeModified", "My related2", false, false ); ctyconf.endBlock(); Document configAsXmlBytes = XMLDocumentFactory.create( ctyconf.toString() ).getAsJDOMDocument(); fixture.save( factory.createContentType( "MyRelatedTypes", ContentHandlerName.CUSTOM.getHandlerClassShortName(), configAsXmlBytes ) ); fixture.flushAndClearHibernateSession(); fixture.save( factory.createUnit( "UnitForMyRelatedTypes", "en" ) ); fixture.save( factory.createCategory( "MyCategory", null, "MyRelatedTypes", "UnitForMyRelatedTypes", "testuser", "testuser" ) ); fixture.save( factory.createCategoryAccessForUser( "MyCategory", "testuser", "read, create, approve" ) ); fixture.flushAndClearHibernateSession(); // setup some content to relate to related1 = storeContentToRelatedTo( "related-1" ); related2 = storeContentToRelatedTo( "related-2" ); related3 = storeContentToRelatedTo( "related-3" ); fixture.flushAndClearHibernateSession(); } @Test public void create_new_content_version_retain_unmodified_related_content_after_modification_of_other_related_content_input() { // setup content to update CreateContentCommand createCommand = new CreateContentCommand(); createCommand.setLanguage( fixture.findLanguageByCode( "en" ).getKey() ); createCommand.setCategory( fixture.findCategoryByName( "MyCategory" ).getKey() ); createCommand.setCreator( fixture.findUserByName( "testuser" ).getKey() ); createCommand.setStatus( ContentStatus.APPROVED ); createCommand.setPriority( 0 ); createCommand.setContentName( "testcontent" ); CustomContentData contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new TextDataEntry( contentData.getInputConfig( "title" ), "Title 1" ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeUnmodified" ), related1 ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related2 ) ); createCommand.setContentData( contentData ); ContentKey createdContentKey = contentService.createContent( createCommand ); fixture.flushAndClearHibernateSession(); ContentVersionEntity firstVersion = fixture.findContentByKey( createdContentKey ).getMainVersion(); ContentVersionKey firstVersionKey = firstVersion.getKey(); // verify that created content has expected contentdata assertEquals( contentData, firstVersion.getContentData() ); // verify that created content has expected contentdata CustomContentData actualContentData = (CustomContentData) firstVersion.getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related2, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); // verify that setup content has expected related content List<ContentKey> expectedRelatedContent = ContentKey.convertToList( related1, related2 ); List<ContentKey> actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( firstVersionKey ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); fixture.flushAndClearHibernateSession(); // exercise UpdateContentCommand updateCommand = UpdateContentCommand.storeNewVersionEvenIfUnchanged( firstVersionKey ); updateCommand.setContentKey( fixture.findFirstContentVersionByTitle( "Title 1" ).getContent().getKey() ); updateCommand.setUpdateStrategy( UpdateContentCommand.UpdateStrategy.MODIFY ); updateCommand.setStatus( ContentStatus.DRAFT ); updateCommand.setModifier( fixture.findUserByName( "testuser" ).getKey() ); contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related3 ) ); updateCommand.setContentData( contentData ); ContentVersionKey targedVersion = contentService.updateContent( updateCommand ).getTargetedVersionKey(); // verify that updated content has expected contentdata ContentVersionEntity secondVersion = fixture.findContentVersionByKey( targedVersion ); actualContentData = (CustomContentData) secondVersion.getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related3, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); assertEquals( 2, fixture.countContentVersionsByTitle( "Title 1" ) ); fixture.flushAndClearHibernateSession(); // verify stored related content expectedRelatedContent = ContentKey.convertToList( related1, related3 ); actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( targedVersion ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); } @Test public void given_existing_content_with_related_content_and_the_related_content_does_not_exist_when_modifying_content_then_the_relation_in_contentdata_should_be_marked_as_deleted() { // setup content to update CreateContentCommand createCommand = new CreateContentCommand(); createCommand.setLanguage( fixture.findLanguageByCode( "en" ).getKey() ); createCommand.setCategory( fixture.findCategoryByName( "MyCategory" ).getKey() ); createCommand.setCreator( fixture.findUserByName( "testuser" ).getKey() ); createCommand.setStatus( ContentStatus.APPROVED ); createCommand.setPriority( 0 ); createCommand.setContentName( "testcontent" ); CustomContentData contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new TextDataEntry( contentData.getInputConfig( "title" ), "Title 1" ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeUnmodified" ), related1 ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related2 ) ); createCommand.setContentData( contentData ); ContentKey createdContentKey = contentService.createContent( createCommand ); fixture.flushAndClearHibernateSession(); ContentVersionEntity firstVersion = fixture.findContentByKey( createdContentKey ).getMainVersion(); ContentVersionKey firstVersionKey = firstVersion.getKey(); // verify that created content has expected contentdata assertEquals( contentData, firstVersion.getContentData() ); // verify that created content has expected contentdata CustomContentData actualContentData = (CustomContentData) firstVersion.getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related2, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); // verify that setup content has expected related content List<ContentKey> expectedRelatedContent = ContentKey.convertToList( related1, related2 ); List<ContentKey> actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( firstVersionKey ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); fixture.flushAndClearHibernateSession(); //////////////////////////////////// delete related //////////////////////////////////// final ContentEntity contentEntity = ContentEntity.class.cast( fixture.findContentByKey( related1 ) ); contentService.deleteContent( fixture.findUserByName( "testuser" ), contentEntity, null ); //////////////////////////////////////// update //////////////////////////////////////// // exercise UpdateContentCommand updateCommand = UpdateContentCommand.storeNewVersionEvenIfUnchanged( firstVersionKey ); updateCommand.setContentKey( fixture.findFirstContentVersionByTitle( "Title 1" ).getContent().getKey() ); updateCommand.setUpdateStrategy( UpdateContentCommand.UpdateStrategy.MODIFY ); updateCommand.setStatus( ContentStatus.DRAFT ); updateCommand.setModifier( fixture.findUserByName( "testuser" ).getKey() ); contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related3 ) ); updateCommand.setContentData( contentData ); ContentVersionKey targedVersion = contentService.updateContent( updateCommand ).getTargetedVersionKey(); // verify that updated content has expected contentdata ContentVersionEntity secondVersion = fixture.findContentVersionByKey( targedVersion ); actualContentData = (CustomContentData) secondVersion.getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related3, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); assertEquals( 2, fixture.countContentVersionsByTitle( "Title 1" ) ); fixture.flushAndClearHibernateSession(); // verify stored related content expectedRelatedContent = ContentKey.convertToList( related1, related3 ); actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( targedVersion ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); } @Test public void update_version_retain_unmodified_related_content_after_modification_of_other_related_content_input() { // setup content to update CreateContentCommand createCommand = new CreateContentCommand(); createCommand.setLanguage( fixture.findLanguageByCode( "en" ).getKey() ); createCommand.setCategory( fixture.findCategoryByName( "MyCategory" ).getKey() ); createCommand.setCreator( fixture.findUserByName( "testuser" ).getKey() ); createCommand.setStatus( ContentStatus.DRAFT ); createCommand.setContentName( "testcontent" ); createCommand.setPriority( 0 ); CustomContentData contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new TextDataEntry( contentData.getInputConfig( "title" ), "Title 1" ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeUnmodified" ), related1 ) ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related2 ) ); createCommand.setContentData( contentData ); ContentKey createdContentKey = contentService.createContent( createCommand ); ContentVersionEntity firstVersion = fixture.findContentByKey( createdContentKey ).getMainVersion(); assertEquals( contentData, firstVersion.getContentData() ); ContentVersionKey firstVersionKey = firstVersion.getKey(); // verify that created content has expected contentdata CustomContentData actualContentData = (CustomContentData) firstVersion.getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related2, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); // verify that setup content has expected related content List<ContentKey> expectedRelatedContent = ContentKey.convertToList( related1, related2 ); List<ContentKey> actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( firstVersionKey ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); fixture.flushAndClearHibernateSession(); // exercise UpdateContentCommand updateCommand = UpdateContentCommand.updateExistingVersion2( firstVersionKey ); updateCommand.setContentKey( fixture.findFirstContentVersionByTitle( "Title 1" ).getContent().getKey() ); updateCommand.setUpdateStrategy( UpdateContentCommand.UpdateStrategy.MODIFY ); updateCommand.setStatus( ContentStatus.DRAFT ); updateCommand.setModifier( fixture.findUserByName( "testuser" ).getKey() ); contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new RelatedContentDataEntry( contentData.getInputConfig( "mySingleRelatedToBeModified" ), related3 ) ); updateCommand.setContentData( contentData ); ContentVersionKey targedVersion = contentService.updateContent( updateCommand ).getTargetedVersionKey(); // verify that updated content has expected contentdata actualContentData = (CustomContentData) fixture.findContentVersionByKey( targedVersion ).getContentData(); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ); assertNotNull( actualContentData.getEntry( "mySingleRelatedToBeModified" ) ); assertEquals( related1, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeUnmodified" ) ).getContentKey() ); assertEquals( related3, ( (RelatedContentDataEntry) actualContentData.getEntry( "mySingleRelatedToBeModified" ) ).getContentKey() ); assertEquals( 1, fixture.countContentVersionsByTitle( "Title 1" ) ); fixture.flushAndClearHibernateSession(); // verify stored related content expectedRelatedContent = ContentKey.convertToList( related1, related3 ); actualRelatedContent = extractContentKeys( fixture.findRelatedContentsByContentVersionKey( targedVersion ) ); assertStoredRelatedContent( expectedRelatedContent, actualRelatedContent ); } private ContentKey storeContentToRelatedTo( String title ) { CreateContentCommand createCommand = new CreateContentCommand(); createCommand.setLanguage( fixture.findLanguageByCode( "en" ).getKey() ); createCommand.setCategory( fixture.findCategoryByName( "MyCategory" ).getKey() ); createCommand.setCreator( fixture.findUserByName( "testuser" ).getKey() ); createCommand.setStatus( ContentStatus.APPROVED ); createCommand.setPriority( 0 ); createCommand.setContentName( "testcontentrelated" ); CustomContentData contentData = new CustomContentData( fixture.findContentTypeByName( "MyRelatedTypes" ).getContentTypeConfig() ); contentData.add( new TextDataEntry( contentData.getInputConfig( "title" ), title ) ); createCommand.setContentData( contentData ); return contentService.createContent( createCommand ); } private List<ContentKey> extractContentKeys( List<RelatedContentEntity> relatedContentEntities ) { List<ContentKey> contentKeys = new ArrayList<ContentKey>(); for ( RelatedContentEntity relatedContentEntity : relatedContentEntities ) { contentKeys.add( relatedContentEntity.getKey().getChildContentKey() ); } return contentKeys; } private void assertStoredRelatedContent( Collection<ContentKey> expectedRelatedContentKeys, Collection<ContentKey> actual ) { for ( ContentKey expectedContentKey : expectedRelatedContentKeys ) { assertTrue( "expected related content with key: " + expectedContentKey, actual.contains( expectedContentKey ) ); } assertEquals( "unexpected number of related content", expectedRelatedContentKeys.size(), actual.size() ); } }