protected boolean saveContentSpec(final DataProviderFactory providerFactory, final ProcessorData processorData, final boolean edit) {
        final ContentSpecProvider contentSpecProvider = providerFactory.getProvider(ContentSpecProvider.class);

        try {
            final ContentSpec contentSpec = processorData.contentSpec;
            final LocaleWrapper locale = contentSpec.getLocale() != null ?
                    EntityUtilities.findLocaleFromString(serverSettings.getLocales(), contentSpec.getLocale())
                    : serverSettings.getDefaultLocale();
            final List<ITopicNode> topicNodes = contentSpec.getAllTopicNodes();

            // Create the duplicate topic map
            final Map<ITopicNode, ITopicNode> duplicatedTopicMap = createDuplicatedTopicMap(topicNodes);

            // Create the new topic entities
            createOrUpdateTopics(topicNodes, topics, processorData, locale);

            // Check if the app should be shutdown
            if (isShuttingDown.get()) {
                shutdown.set(true);
                throw new ProcessingException("Shutdown Requested");
            }

            // From here on the main saving happens so this shouldn't be interrupted

            // Save the new topic entities
            if (!topics.savePool()) {
                log.error(ProcessorConstants.ERROR_DATABASE_ERROR_MSG);
                throw new ProcessingException("Failed to save the pool of topics.");
            }

            // Initialise the new and cloned topics using the populated topic pool
            for (final ITopicNode topicNode : topicNodes) {
                topics.initialiseFromPool(topicNode);
                cleanSpecTopicWhenCreatedOrUpdated(topicNode);
            }

            // Sync the Duplicated Topics (ID = X<Number>)
            syncDuplicatedTopics(duplicatedTopicMap);

            // Save the content spec
            mergeAndSaveContentSpec(providerFactory, processorData, !edit);
        } catch (ProcessingException e) {
            LOG.debug("", e);
            if (providerFactory.isTransactionsSupported()) {
                providerFactory.rollback();
            } else {
                // Clean up the data that was created
                if (processorData.getContentSpec().getId() != null && !edit) {
                    try {
                        contentSpecProvider.deleteContentSpec(processorData.getContentSpec().getId());
                    } catch (Exception e1) {
                        log.error("Unable to clean up the Content Specification from the database.", e);
                    }
                }
                if (topics.isInitialised()) topics.rollbackPool();
            }
            return false;
        } catch (Exception e) {
            LOG.error("", e);
            if (providerFactory.isTransactionsSupported()) {
                providerFactory.rollback();
            } else {
                // Clean up the data that was created
                if (processorData.getContentSpec().getId() != null && !edit) {
                    try {
                        contentSpecProvider.deleteContentSpec(processorData.getContentSpec().getId());
                    } catch (Exception e1) {
                        log.error("Unable to clean up the Content Specification from the database.", e);
                    }
                }
                if (topics.isInitialised()) topics.rollbackPool();
            }
            log.debug("", e);
            return false;
        }
        return true;
    }
protected boolean saveContentSpec ( final DataProviderFactory providerFactory , final ProcessorData processorData , final boolean edit ) { final ContentSpecProvider contentSpecProvider = providerFactory . getProvider ( ContentSpecProvider . class ) ; try { final ContentSpec contentSpec = processorData . contentSpec ; final LocaleWrapper locale = contentSpec . getLocale ( ) != null ? EntityUtilities . findLocaleFromString ( serverSettings . getLocales ( ) , contentSpec . getLocale ( ) ) : serverSettings . getDefaultLocale ( ) ; final List < ITopicNode > topicNodes = contentSpec . getAllTopicNodes ( ) ; final Map < ITopicNode , ITopicNode > duplicatedTopicMap = createDuplicatedTopicMap ( topicNodes ) ; createOrUpdateTopics ( topicNodes , topics , processorData , locale ) ; if ( isShuttingDown . get ( ) ) { shutdown . set ( true ) ; throw new ProcessingException ( "Shutdown Requested" ) ; } if ( ! topics . savePool ( ) ) { log . error ( ProcessorConstants . ERROR_DATABASE_ERROR_MSG ) ; throw new ProcessingException ( "Failed to save the pool of topics." ) ; } for ( final ITopicNode topicNode : topicNodes ) { topics . initialiseFromPool ( topicNode ) ; cleanSpecTopicWhenCreatedOrUpdated ( topicNode ) ; } syncDuplicatedTopics ( duplicatedTopicMap ) ; mergeAndSaveContentSpec ( providerFactory , processorData , ! edit ) ; } catch ( ProcessingException e ) { LOG . debug ( "" , e ) ; if ( providerFactory . isTransactionsSupported ( ) ) { providerFactory . rollback ( ) ; } else { if ( processorData . getContentSpec ( ) . getId ( ) != null && ! edit ) { try { contentSpecProvider . deleteContentSpec ( processorData . getContentSpec ( ) . getId ( ) ) ; } catch ( Exception e1 ) { log . error ( "Unable to clean up the Content Specification from the database." , e ) ; } } if ( topics . isInitialised ( ) ) topics . rollbackPool ( ) ; } return false ; } catch ( Exception e ) { LOG . error ( "" , e ) ; if ( providerFactory . isTransactionsSupported ( ) ) { providerFactory . rollback ( ) ; } else { if ( processorData . getContentSpec ( ) . getId ( ) != null && ! edit ) { try { contentSpecProvider . deleteContentSpec ( processorData . getContentSpec ( ) . getId ( ) ) ; } catch ( Exception e1 ) { log . error ( "Unable to clean up the Content Specification from the database." , e ) ; } } if ( topics . isInitialised ( ) ) topics . rollbackPool ( ) ; } log . debug ( "" , e ) ; return false ; } return true ; }
Saves the Content Specification and all of the topics in the content specification

@param providerFactory
@param processorData   The data to be processed.
@param edit            Whether the content specification is being edited or created.
@return True if the topic saved successfully otherwise false.