/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.itest.search;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.node.shutdown.NodesShutdownRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.SearchHit;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.enonic.cms.core.content.ContentKey;
import com.enonic.cms.core.content.ContentService;
import com.enonic.cms.core.content.category.CategoryKey;
import com.enonic.cms.core.content.contenttype.ContentTypeKey;
import com.enonic.cms.core.content.index.UserDefinedField;
import com.enonic.cms.core.content.resultset.ContentResultSet;
import com.enonic.cms.core.search.ContentIndexServiceImpl;
import com.enonic.cms.core.search.ElasticSearchIndexService;
import com.enonic.cms.core.search.IndexMappingProvider;
import com.enonic.cms.core.search.IndexType;
import com.enonic.cms.core.search.query.ContentDocument;
import com.enonic.cms.core.search.query.SimpleText;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* Created by IntelliJ IDEA.
* User: rmh
* Date: 12/20/11
* Time: 3:35 PM
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles(profiles = "itest")
@ContextConfiguration("classpath:com/enonic/cms/itest/base-core-test-context.xml")
public abstract class ContentIndexServiceTestBase
{
private IndexMappingProvider indexMappingProvider;
@Autowired
protected ContentService contentService;
@Autowired
protected ContentIndexServiceImpl contentIndexService;
@Autowired
protected ElasticSearchIndexService elasticSearchIndexService;
@Before
public void initIndex()
throws Exception
{
final ClusterHealthResponse clusterHealth =
elasticSearchIndexService.getClusterHealth( ContentIndexServiceImpl.CONTENT_INDEX_NAME, true );
final boolean indexExists = elasticSearchIndexService.indexExists( ContentIndexServiceImpl.CONTENT_INDEX_NAME );
if ( indexExists )
{
elasticSearchIndexService.deleteIndex( ContentIndexServiceImpl.CONTENT_INDEX_NAME );
}
elasticSearchIndexService.createIndex( ContentIndexServiceImpl.CONTENT_INDEX_NAME );
addMapping();
}
// @After
public void shutDown()
{
final Client client = elasticSearchIndexService.getClient();
final NodesShutdownRequest nodesShutdown = new NodesShutdownRequest();
client.admin().cluster().nodesShutdown( nodesShutdown.exit( false ) ).actionGet();
client.close();
}
private void addMapping()
{
doAddMapping( ContentIndexServiceImpl.CONTENT_INDEX_NAME, IndexType.Content );
doAddMapping( ContentIndexServiceImpl.CONTENT_INDEX_NAME, IndexType.Binaries );
}
private void doAddMapping( String indexName, IndexType indexType )
{
String mapping = indexMappingProvider.getMapping( indexName, indexType.toString() );
elasticSearchIndexService.putMapping( ContentIndexServiceImpl.CONTENT_INDEX_NAME, indexType.toString(), mapping );
}
protected void assertContentResultSetEquals( int[] contentKeys, ContentResultSet result )
{
assertEquals( "contentResultSet length", contentKeys.length, result.getTotalCount() );
List<ContentKey> list = result.getKeys();
for ( int contentKey : contentKeys )
{
if ( !list.contains( new ContentKey( contentKey ) ) )
{
// ContentIndexServiceImplTest.LOG.info( "{}", contentKey );
}
assertTrue( "Unexpected ContentResultSet. ContentKey not found: " + contentKey, list.contains( new ContentKey( contentKey ) ) );
}
}
protected Map<String, Object> getFieldMapForId( ContentKey contentKey )
{
SearchResponse result = fetchDocumentByContentKey( contentKey );
assertEquals( "Should get one hit only", 1, result.getHits().getHits().length );
SearchHit hit = result.getHits().getAt( 0 );
return hit.getSource();
}
private SearchResponse fetchDocumentByContentKey( ContentKey contentKey )
{
String termQuery = "{\n" +
" \"from\" : 0,\n" +
" \"size\" : " + 100 + ",\n" +
// "\"fields\" : [\"*\"],\n" +
" \"query\" : {\n" +
" \"term\" : {\n" +
" \"key\" : \"" + new Long( contentKey.toString() ).toString() + "\"\n" +
" }\n" +
" }\n" +
"}";
return elasticSearchIndexService.search( ContentIndexServiceImpl.CONTENT_INDEX_NAME, IndexType.Content.toString(), termQuery );
}
protected void printAllIndexContent()
{
String termQuery = "{\n" +
" \"from\" : 0,\n" +
" \"size\" : 100,\n" +
"\"fields\" : [\"_source\"],\n" +
" \"query\" : {\n" +
" \"match_all\" : {\n" +
" }\n" +
" }\n" +
"}";
SearchResponse result =
elasticSearchIndexService.search( ContentIndexServiceImpl.CONTENT_INDEX_NAME, IndexType.Content.toString(), termQuery );
System.out.println( "\n\n---------- CONTENT --------------------------------" );
System.out.println( result.toString() );
System.out.println( "\n\n" );
result = elasticSearchIndexService.search( ContentIndexServiceImpl.CONTENT_INDEX_NAME, IndexType.Binaries.toString(), termQuery );
System.out.println( "\n\n---------- BINARIES --------------------------------" );
System.out.println( result.toString() );
System.out.println( "\n\n\n\n" );
}
protected void flushIndex()
{
this.contentIndexService.flush();
}
protected ContentDocument createContentDocument( int contentKey, String title, String preface, String fulltext )
{
return createContentDocument( contentKey, title, new String[][]{{"data/preface", preface}, {"fulltext", fulltext}} );
}
protected ContentDocument createContentDocumentWithTextField( int contentKey, String title, String preface, String fulltext )
{
return createContentDocument( contentKey, title, new String[][]{{"data/preface", preface}, {"data/textfield", fulltext}} );
}
protected ContentDocument createContentDocument( ContentKey contentKey, CategoryKey categoryKey, ContentTypeKey contentTypeKey,
int status, String title, String[][] fields )
{
ContentDocument doc = new ContentDocument( contentKey );
doc.setCategoryKey( categoryKey );
doc.setContentTypeKey( contentTypeKey );
doc.setContentTypeName( "Article" );
if ( title != null )
{
doc.setTitle( title );
}
if ( fields != null )
{
for ( String[] field : fields )
{
doc.addUserDefinedField( field[0], field[1] );
}
}
doc.setStatus( status );
doc.setPriority( 0 );
return doc;
}
ContentDocument createContentDocument( int contentKey, String title, String[][] fields )
{
ContentDocument doc = new ContentDocument( new ContentKey( contentKey ) );
doc.setCategoryKey( new CategoryKey( 9 ) );
doc.setContentTypeKey( new ContentTypeKey( 32 ) );
doc.setContentTypeName( "Article" );
if ( title != null )
{
doc.setTitle( title );
}
if ( fields != null )
{
for ( String[] field : fields )
{
doc.addUserDefinedField( field[0], field[1] );
}
}
doc.setStatus( 2 );
doc.setPriority( 0 );
return doc;
}
protected void setUpStandardTestValues()
{
final GregorianCalendar date = new GregorianCalendar( 2008, Calendar.FEBRUARY, 28 );
// Index content 1, 2 og 3:
ContentDocument doc1 = new ContentDocument( new ContentKey( 1322 ) );
doc1.setCategoryKey( new CategoryKey( 9 ) );
doc1.setContentTypeKey( new ContentTypeKey( 32 ) );
doc1.setContentTypeName( "Adults" );
doc1.setTitle( "Homer" );
doc1.addUserDefinedField( "data/person/age", new SimpleText( "38" ) );
doc1.addUserDefinedField( "data/person/gender", "male" );
doc1.addUserDefinedField( "data/person/description", "description1-1" );
doc1.addUserDefinedField( "data/person/birthdate", new SimpleText( "1975-05-05" ) );
doc1.addUserDefinedField( "data/person/age", new SimpleText( "39" ) );
doc1.addUserDefinedField( "data/person/gender", "male" );
doc1.addUserDefinedField( "data/person/description", "description1-2" );
doc1.addUserDefinedField( "data/person/birthdate", new SimpleText( "1976-06-06" ) );
// Publish from February 28th to March 28th.
doc1.setPublishFrom( date.getTime() );
date.add( Calendar.MONTH, 1 );
doc1.setPublishTo( date.getTime() );
date.add( Calendar.MONTH, -1 );
doc1.setStatus( 2 );
doc1.setPriority( 0 );
doc1.setLanguageCode( "en" );
contentIndexService.index( doc1 );
date.add( Calendar.DAY_OF_MONTH, 1 );
ContentDocument doc2 = new ContentDocument( new ContentKey( 1327 ) );
doc2.setCategoryKey( new CategoryKey( 7 ) );
doc2.setContentTypeKey( new ContentTypeKey( 32 ) );
doc2.setContentTypeName( "Adults" );
doc2.setTitle( "Fry" );
doc2.addUserDefinedField( "data/person/age", new SimpleText( "28" ) );
doc2.addUserDefinedField( "data/person/gender", "male" );
doc2.addUserDefinedField( "data/person/description", "description2" );
doc2.addUserDefinedField( "data/person/birthdate", new SimpleText( "1978-08-01" ) );
// Publish from February 29th to March 29th.
doc2.setPublishFrom( date.getTime() );
date.add( Calendar.MONTH, 1 );
doc2.setPublishTo( date.getTime() );
date.add( Calendar.MONTH, -1 );
doc2.setStatus( 2 );
doc2.setPriority( 0 );
doc2.setLanguageCode( "fr" );
contentIndexService.index( doc2 );
date.add( Calendar.DAY_OF_MONTH, 1 );
ContentDocument doc3 = new ContentDocument( new ContentKey( 1323 ) );
doc3.setCategoryKey( new CategoryKey( 9 ) );
doc3.setContentTypeKey( new ContentTypeKey( 37 ) );
doc3.setContentTypeName( "Children" );
doc3.setTitle( "Bart" );
doc3.addUserDefinedField( "data/person/age", new SimpleText( "10" ) );
doc3.addUserDefinedField( "data/person/gender", "male" );
doc3.addUserDefinedField( "data/person/description", "description3" );
doc3.addUserDefinedField( "data/person/birthdate", new SimpleText( "2003-03-28" ) );
// Publish from March 1st to April 1st
doc3.setPublishFrom( date.getTime() );
date.add( Calendar.MONTH, 1 );
doc3.setPublishTo( date.getTime() );
date.add( Calendar.MONTH, -1 );
doc3.setStatus( 2 );
doc3.setPriority( 0 );
doc3.setLanguageCode( "en" );
contentIndexService.index( doc3 );
ContentDocument doc4 = new ContentDocument( new ContentKey( 1324 ) );
doc4.setCategoryKey( new CategoryKey( 9 ) );
doc4.setContentTypeKey( new ContentTypeKey( 32 ) );
doc4.setContentTypeName( "Adults" );
doc4.setTitle( "Bender" );
doc4.addUserDefinedField( "data/person/age", new SimpleText( "5" ) );
doc4.addUserDefinedField( "data/person/gender", "man-bot" );
doc4.addUserDefinedField( "data/person/description", "description4" );
doc3.addUserDefinedField( "data/person/birthdate", new SimpleText( "2010-05-22" ) );
// Publish from March 1st to March 28th.
doc4.setPublishFrom( date.getTime() );
date.add( Calendar.DAY_OF_MONTH, 27 );
doc4.setPublishTo( date.getTime() );
doc4.setStatus( 2 );
doc4.setPriority( 0 );
doc4.setLanguageCode( "en" );
contentIndexService.index( doc4 );
flushIndex();
}
protected ContentDocument createContentDocument( ContentKey contentKey, CategoryKey categoryKey, ContentTypeKey contentTypeKey,
String title, List<UserDefinedField> userDefinedFields )
{
ContentDocument doc = new ContentDocument( contentKey );
doc.setCategoryKey( categoryKey );
doc.setContentTypeKey( contentTypeKey );
doc.setContentTypeName( "Article" );
if ( title != null )
{
doc.setTitle( title );
}
for ( UserDefinedField userDefinedField : userDefinedFields )
{
doc.addUserDefinedField( userDefinedField );
}
doc.setStatus( 2 );
doc.setPriority( 0 );
return doc;
}
protected void verifyField( String fieldName, int expected, Map<String, Object> fieldMapForId )
{
final Object hits = fieldMapForId.get( fieldName );
if ( expected > 1 )
{
assertNotNull( "Hits is null for field: " + fieldName, hits );
assertTrue( "Hits should be a collection", hits instanceof Collection );
Assert.assertEquals( "Wrong number of hits for field: " + fieldName, expected, ( (Collection) hits ).size() );
}
else if ( expected == 1 )
{
assertNotNull( "Hits is null for field: " + fieldName, hits );
if ( hits instanceof Collection )
{
Assert.assertEquals( "Wrong number of hits for field: " + fieldName, expected, ( (Collection) hits ).size() );
}
}
else
{
assertNull( "Should be null", hits );
}
}
@Autowired
public void setIndexMappingProvider( IndexMappingProvider indexMappingProvider )
{
this.indexMappingProvider = indexMappingProvider;
}
}