/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.content.imports; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.enonic.cms.framework.util.GenericConcurrencyLock; import com.enonic.cms.core.content.ContentEntity; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.content.category.CategoryEntity; import com.enonic.cms.core.content.category.CategoryKey; import com.enonic.cms.core.content.contenttype.CtyImportConfig; import com.enonic.cms.core.content.contenttype.CtyImportPurgeConfig; import com.enonic.cms.core.search.query.ContentIndexService; import com.enonic.cms.core.security.user.UserEntity; import com.enonic.cms.store.dao.ContentDao; public class ImportJobImpl implements ImportJob { private static final Logger LOG = LoggerFactory.getLogger( ImportJobImpl.class ); private ImportService importService; private ContentIndexService contentIndexService; private ContentDao contentDao; private ImportResult importResult; private UserEntity importer; private CategoryEntity categoryToImportTo; private CtyImportConfig importConfig; private ImportDataReader importDataReader; private DateTime defaultPublishFrom; private DateTime defaultPublishTo; private List<ContentKey> contentNotAffectedByImport; private Map<String, ContentKey> existingContentKeysBySyncValue; private static boolean executeInOneTransaction = false; private UserEntity assignee; private Date assignmentDueDate; private String assignmentDescription; private static GenericConcurrencyLock<CategoryKey> concurrencyLock = GenericConcurrencyLock.create(); public ImportResult start() { final Lock locker = concurrencyLock.getLock( categoryToImportTo.getKey() ); try { locker.lock(); LOG.info( "Starting content import job #" + this.getImportJobNumber() ); LOG.info( "Import job #" + this.getImportJobNumber() + ": importing to category: key = " + categoryToImportTo.getKey() + ", path = " + categoryToImportTo.getPathAsString() ); importConfig.validateContentTypeImportConfig( categoryToImportTo.getContentType().getContentTypeConfig() ); if ( importConfig.isSyncEnabled() ) { initSyncMode(); } importResult = new ImportResult(); importResult.startTimer(); int count = 0; while ( importDataReader.hasMoreEntries() ) { count++; final ImportDataEntry nextEntry = importDataReader.getNextEntry(); long lastEntryImportTime = System.currentTimeMillis(); if ( executeInOneTransaction ) { importService.importData_withoutRequiresNewPropagation_for_test_only( nextEntry, this ); } else { importService.importData( nextEntry, this ); } LOG.info( "Import job #" + this.getImportJobNumber() + "entry #" + count + " finished in " + ( System.currentTimeMillis() - lastEntryImportTime ) + " milliseconds." ); } if ( importConfig.isSyncEnabled() ) { // Import content is done... now what to do with the unaffected content in the category we imported to? handleUnaffectedContentInCategory(); } importResult.stopTimer(); LOG.info( "Finished content import job #" + this.getImportJobNumber() ); return importResult; } finally { locker.unlock(); } } private int getImportJobNumber() { return this.hashCode(); } private void initSyncMode() { contentNotAffectedByImport = contentDao.findContentKeysByCategory( categoryToImportTo.getKey() ); LOG.info( "Import job #" + this.getImportJobNumber() + ": found " + contentNotAffectedByImport.size() + " existing content in category: " + categoryToImportTo.getPathAsString() ); existingContentKeysBySyncValue = new ExistingContentBySyncValueResolver( contentIndexService ).resolve( categoryToImportTo, importConfig ); LOG.info( "Import job #" + this.getImportJobNumber() + ": found " + existingContentKeysBySyncValue.size() + " matching content keys (by sync value) in category: " + categoryToImportTo.getPathAsString() ); } private void handleUnaffectedContentInCategory() { if ( contentNotAffectedByImport.isEmpty() ) { LOG.info( "Import job #" + this.getImportJobNumber() + ": No remaining content to purge. All content in the category was affected by the import the job." ); return; } for ( ContentKey contentKey : contentNotAffectedByImport ) { handleUnaffectedContent( contentKey ); } } private void handleUnaffectedContent( ContentKey contentKey ) { if ( CtyImportPurgeConfig.ARCHIVE == importConfig.getPurge() ) { if ( executeInOneTransaction ) { importService.archiveContent_withoutRequiresNewPropagation_for_test_only( importer, contentKey, importResult ); } else { importService.archiveContent( importer, contentKey, importResult ); } } else if ( CtyImportPurgeConfig.DELETE == importConfig.getPurge() ) { if ( executeInOneTransaction ) { importService.deleteContent_withoutRequiresNewPropagation_for_test_only( importer, contentKey, importResult ); } else { importService.deleteContent( importer, contentKey, importResult ); } } else if ( CtyImportPurgeConfig.NONE == importConfig.getPurge() ) { final ContentEntity content = contentDao.findByKey( contentKey ); importResult.addRemaining( content ); } } public ContentKey resolveExistingContentBySyncValue( final ImportDataEntry importDataEntry ) { //String value = StringUtil.replaceECC( importDataEntry.getSyncValue() ); String value = importDataEntry.getSyncValue(); return existingContentKeysBySyncValue.get( value.toLowerCase() ); } public void registerImportedContent( ContentKey contentKey ) { if ( importConfig.isSyncEnabled() ) { contentNotAffectedByImport.remove( contentKey ); } } public CategoryEntity getCategoryToImportTo() { return categoryToImportTo; } public DateTime getDefaultPublishFrom() { return defaultPublishFrom; } public DateTime getDefaultPublishTo() { return defaultPublishTo; } public UserEntity getImporter() { return importer; } public CtyImportConfig getImportConfig() { return importConfig; } public ImportResult getImportResult() { return importResult; } public void setImportService( ImportService value ) { this.importService = value; } public void setContentIndexService( ContentIndexService value ) { this.contentIndexService = value; } public void setContentDao( ContentDao value ) { this.contentDao = value; } public void setImporter( UserEntity value ) { this.importer = value; } public void setCategoryToImportTo( CategoryEntity value ) { this.categoryToImportTo = value; } public void setImportConfig( CtyImportConfig value ) { this.importConfig = value; } public void setImportDataReader( ImportDataReader value ) { this.importDataReader = value; } public void setDefaultPublishFrom( DateTime value ) { this.defaultPublishFrom = value; } public void setDefaultPublishTo( DateTime value ) { this.defaultPublishTo = value; } public void setExecuteInOneTransaction( boolean value ) { executeInOneTransaction = value; } public UserEntity getAssignee() { return assignee; } public void setAssignee( UserEntity assignee ) { this.assignee = assignee; } public Date getAssignmentDueDate() { return assignmentDueDate; } public String getAssignmentDescription() { return assignmentDescription; } public void setAssignmentDueDate( Date assignmentDueDate ) { this.assignmentDueDate = assignmentDueDate; } public void setAssignmentDescription( String assignmentDescription ) { this.assignmentDescription = assignmentDescription; } }