/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.portal.datasource.service; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import org.apache.commons.lang.StringUtils; import org.jdom.Document; import org.jdom.Element; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.google.common.base.Strings; import com.enonic.vertical.engine.PresentationEngine; import com.enonic.vertical.engine.handlers.MenuHandler; import com.enonic.cms.framework.xml.XMLDocument; import com.enonic.cms.framework.xml.XMLDocumentFactory; import com.enonic.cms.core.InvalidKeyException; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.content.ContentService; import com.enonic.cms.core.content.ContentVersionEntity; import com.enonic.cms.core.content.ContentVersionKey; import com.enonic.cms.core.content.ContentXMLCreator; import com.enonic.cms.core.content.GetContentExecutor; import com.enonic.cms.core.content.GetContentResult; import com.enonic.cms.core.content.GetContentXmlCreator; import com.enonic.cms.core.content.GetRelatedContentExecutor; import com.enonic.cms.core.content.GetRelatedContentResult; import com.enonic.cms.core.content.GetRelatedContentXmlCreator; import com.enonic.cms.core.content.access.ContentAccessResolver; import com.enonic.cms.core.content.category.CategoryAccessResolver; import com.enonic.cms.core.content.category.CategoryKey; import com.enonic.cms.core.content.contenttype.ContentTypeKey; import com.enonic.cms.core.content.index.ContentIndexQuery.SectionFilterStatus; import com.enonic.cms.core.content.query.ContentByCategoryQuery; import com.enonic.cms.core.content.query.ContentByQueryQuery; import com.enonic.cms.core.content.query.ContentBySectionQuery; import com.enonic.cms.core.content.query.InvalidContentBySectionQueryException; import com.enonic.cms.core.content.query.RelatedChildrenContentQuery; import com.enonic.cms.core.content.query.RelatedContentQuery; import com.enonic.cms.core.content.resultset.ContentResultSet; import com.enonic.cms.core.content.resultset.RelatedContentResultSet; import com.enonic.cms.core.content.resultset.RelatedContentResultSetImpl; import com.enonic.cms.core.portal.datasource.DataSourceContext; import com.enonic.cms.core.portal.rendering.tracing.DataTraceInfo; import com.enonic.cms.core.portal.rendering.tracing.RenderTrace; import com.enonic.cms.core.preference.PreferenceEntity; import com.enonic.cms.core.preference.PreferenceKey; import com.enonic.cms.core.preference.PreferenceScope; import com.enonic.cms.core.preference.PreferenceScopeResolver; import com.enonic.cms.core.preference.PreferenceService; import com.enonic.cms.core.preference.PreferenceSpecification; import com.enonic.cms.core.preference.PreferenceUniqueMatchResolver; import com.enonic.cms.core.preference.PreferenceXmlCreator; import com.enonic.cms.core.preview.PreviewContext; import com.enonic.cms.core.search.result.FacetResultSetXmlCreator; import com.enonic.cms.core.security.user.User; import com.enonic.cms.core.security.user.UserEntity; import com.enonic.cms.core.security.userstore.UserStoreEntity; import com.enonic.cms.core.security.userstore.UserStoreNotFoundException; import com.enonic.cms.core.security.userstore.UserStoreParser; import com.enonic.cms.core.security.userstore.UserStoreService; import com.enonic.cms.core.security.userstore.UserStoreXmlCreator; import com.enonic.cms.core.structure.SiteEntity; import com.enonic.cms.core.structure.SiteKey; import com.enonic.cms.core.structure.SitePropertiesService; import com.enonic.cms.core.structure.SiteXmlCreator; import com.enonic.cms.core.structure.menuitem.MenuItemAccessResolver; import com.enonic.cms.core.structure.menuitem.MenuItemEntity; import com.enonic.cms.core.structure.menuitem.MenuItemKey; import com.enonic.cms.core.structure.menuitem.MenuItemXMLCreatorSetting; import com.enonic.cms.core.structure.menuitem.MenuItemXmlCreator; import com.enonic.cms.core.time.TimeService; import com.enonic.cms.store.dao.ContentDao; import com.enonic.cms.store.dao.ContentVersionDao; import com.enonic.cms.store.dao.GroupDao; import com.enonic.cms.store.dao.MenuItemDao; import com.enonic.cms.store.dao.SiteDao; import com.enonic.cms.store.dao.UserDao; import com.enonic.cms.store.dao.UserStoreDao; @Service("dataSourceService") public final class DataSourceServiceImpl implements DataSourceService { private ContentService contentService; private PreferenceService preferenceService; private PresentationEngine presentationEngine; @Autowired private ContentVersionDao contentVersionDao; private ContentDao contentDao; @Autowired private SiteDao siteDao; @Autowired private MenuItemDao menuItemDao; @Autowired private MenuHandler menuHandler; private UserDao userDao; @Autowired private GroupDao groupDao; @Autowired private UserStoreDao userStoreDao; private SitePropertiesService sitePropertiesService; private TimeService timeService; private UserStoreService userStoreService; private FacetResultSetXmlCreator facetResultSetXmlCreator = new FacetResultSetXmlCreator(); @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContentByQuery( DataSourceContext context, String query, String orderBy, int index, int count, boolean includeData, int childrenLevel, int parentLevel, final String facetsDefinition ) { final PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); ContentXMLCreator xmlCreator = new ContentXMLCreator(); final Date now = timeService.getNowAsDateTime().toDate(); try { ContentByQueryQuery spec = new ContentByQueryQuery(); spec.setQuery( query ); spec.setOrderBy( orderBy ); spec.setIndex( index ); spec.setCount( count ); spec.setFilterContentOnlineAt( now ); spec.setUser( user ); spec.setFacets( facetsDefinition ); ContentResultSet contents = contentService.queryContent( spec ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( contents ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( 0 ); relatedContentQuery.setIncludeOnlyMainVersions( true ); RelatedContentResultSet relatedContents = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContents = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContents ); } xmlCreator.setResultIndexing( index, count ); xmlCreator.setIncludeOwnerAndModifierData( true ); xmlCreator.setIncludeContentData( includeData ); xmlCreator.setIncludeCategoryData( true ); xmlCreator.setIncludeRelatedContentData( includeData ); xmlCreator.setIncludeUserRightsInfo( false, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); XMLDocument xml = xmlCreator.createContentsDocument( user, contents, relatedContents ); addFacetResultSet( contents, xml ); addDataTraceInfo( xml.getAsJDOMDocument() ); return xml; } catch ( InvalidKeyException e ) { return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } } private void addFacetResultSet( final ContentResultSet contents, final XMLDocument xml ) { if ( contents.getFacetsResultSet() != null ) { facetResultSetXmlCreator.addFacetResultXml( xml.getAsJDOMDocument(), contents.getFacetsResultSet() ); } } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContent( DataSourceContext context, int[] contentKeys, String query, String orderBy, int index, int count, boolean includeData, int childrenLevel, int parentLevel, final String facets ) { boolean includeUserRights = false; boolean categoryRecursive = false; return doGetContent( context, contentKeys, query, orderBy, index, count, parentLevel, childrenLevel, 0, includeData, includeData, includeUserRights, null, categoryRecursive, null, facets ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContentVersion( DataSourceContext context, int[] versionKeys, int childrenLevel ) { return doGetContentVersion( context, versionKeys, childrenLevel ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getRelatedContent( DataSourceContext context, int[] contentKeys, int relation, String query, String orderBy, int index, int count, boolean includeData, int childrenLevel, int parentLevel, final boolean requireAll, final String facets ) { boolean includeOwnerAndModifierData = true; boolean includeCategoryData = true; return doGetRelatedContent( context, contentKeys, relation, query, orderBy, requireAll, index, count, parentLevel, childrenLevel, includeOwnerAndModifierData, includeData, includeCategoryData, includeData, facets ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContentBySection( DataSourceContext context, int[] menuItemKeys, int levels, String query, String orderBy, int index, int count, boolean includeData, int childrenLevel, int parentLevel, final String facets ) { boolean includeOwnerAndModifierData = true; boolean includeCategoryData = true; boolean includeUserRights = false; return doGetContentBySection( context, menuItemKeys, levels, query, orderBy, index, count, parentLevel, childrenLevel, 0, includeOwnerAndModifierData, includeData, includeCategoryData, includeData, includeUserRights, null, facets ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getRandomContentBySection( DataSourceContext context, int[] menuItemKeys, int levels, String query, int count, boolean includeData, int childrenLevel, int parentLevel ) { boolean includeOwnerAndModifierData = true; boolean includeCategoryData = true; boolean includeUserRights = false; return doGetRandomContentBySection( context, menuItemKeys, levels, query, count, parentLevel, childrenLevel, includeOwnerAndModifierData, includeData, includeCategoryData, includeData, includeUserRights ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContentByCategory( DataSourceContext context, int[] categoryKeys, int levels, String query, String orderBy, int index, int count, boolean includeData, int childrenLevel, int parentLevel, final boolean filterOnUser, final String facets ) { boolean includeOwnerAndModifierData = true; boolean includeCategoryData = true; boolean includeUserRights = false; return doGetContentByCategory( context, categoryKeys, levels, query, orderBy, index, count, childrenLevel, parentLevel, 0, includeOwnerAndModifierData, includeData, includeCategoryData, includeData, includeUserRights, null, filterOnUser, facets ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getRandomContentByCategory( DataSourceContext context, int[] categoryKeys, int levels, String query, int count, boolean includeData, int childrenLevel, int parentLevel ) { PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); ContentXMLCreator xmlCreator = new ContentXMLCreator(); Collection<CategoryKey> categoryKeySet = CategoryKey.convertToList( categoryKeys ); final Date now = new Date(); ContentByCategoryQuery contentByCategoryQuery = new ContentByCategoryQuery(); contentByCategoryQuery.setUser( user ); contentByCategoryQuery.setCategoryKeyFilter( categoryKeySet, levels ); contentByCategoryQuery.setIndex( 0 ); contentByCategoryQuery.setQuery( query ); contentByCategoryQuery.setCount( Integer.MAX_VALUE ); contentByCategoryQuery.setFilterContentOnlineAt( now ); ContentResultSet contents = contentService.queryContent( contentByCategoryQuery ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } ContentResultSet randomContents = contents.createRandomizedResult( count ); RelatedContentResultSet relatedContent; if ( parentLevel > 0 || childrenLevel > 0 ) { RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( randomContents ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( 0 ); relatedContentQuery.setIncludeOnlyMainVersions( true ); relatedContent = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContent = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContent ); } } else { relatedContent = new RelatedContentResultSetImpl(); } xmlCreator.setResultIndexing( 0, count ); xmlCreator.setIncludeContentData( includeData ); xmlCreator.setIncludeRelatedContentData( includeData ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); XMLDocument doc = xmlCreator.createContentsDocument( user, randomContents, relatedContent ); addDataTraceInfo( doc.getAsJDOMDocument() ); return doc; } /** * @inheritDoc */ @Deprecated @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getContent( DataSourceContext context, int[] contentKeys, int parentLevel, int childrenLevel, int parentChildrenLevel, boolean updateStatistics, boolean relatedTitlesOnly, boolean includeUserRights, int[] filterByCategories, boolean categoryRecursive, int[] filterByContentTypes ) { boolean includeContentData = true; return doGetContent( context, contentKeys, "", "@key asc", 0, contentKeys.length, parentLevel, childrenLevel, parentChildrenLevel, includeContentData, !relatedTitlesOnly, includeUserRights, filterByCategories, categoryRecursive, filterByContentTypes, null ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getMenu( DataSourceContext context, int menuKey, int tagItem, int levels, boolean includeHidden ) { if ( menuKey < 0 ) { return SiteXmlCreator.createEmptyMenus(); } SiteEntity site = siteDao.findByKey( new SiteKey( menuKey ) ); if ( site == null ) { return SiteXmlCreator.createEmptyMenus(); } SiteXmlCreator siteXmlCreator = new SiteXmlCreator( new MenuItemAccessResolver( groupDao ), context.getPreviewContext().getMenuItemInPreviewOrNull(), menuHandler ); siteXmlCreator.setUserXmlAsAdminConsoleStyle( false ); siteXmlCreator.setUser( getUserEntity( context.getUser() ) ); siteXmlCreator.setActiveMenuItem( menuItemDao.findByKey( new MenuItemKey( tagItem ) ) ); siteXmlCreator.setMenuItemLevels( levels ); siteXmlCreator.setIncludeHiddenMenuItems( includeHidden ); return siteXmlCreator.createLegacyGetMenu( site, sitePropertiesService.getSiteProperties( site.getKey() ) ); } @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getMenuData( DataSourceContext context, int menuId ) { if ( menuId < 0 ) { return SiteXmlCreator.createEmptyMenus(); } SiteEntity site = siteDao.findByKey( menuId ); if ( site == null ) { return SiteXmlCreator.createEmptyMenus(); } SiteXmlCreator siteXmlCreator = new SiteXmlCreator( new MenuItemAccessResolver( groupDao ), context.getPreviewContext().getMenuItemInPreviewOrNull(), menuHandler ); siteXmlCreator.setUserXmlAsAdminConsoleStyle( false ); siteXmlCreator.setIncludeDeviceClassResolverInfo( true ); return siteXmlCreator.createLegacyGetMenuData( site, sitePropertiesService.getSiteProperties( site.getKey() ) ); } @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getMenuBranch( DataSourceContext context, int menuItemKey, boolean topLevel, int startLevel, int levels ) { if ( menuItemKey < 0 ) { return SiteXmlCreator.createEmptyMenuBranch(); } MenuItemEntity menuItem = menuItemDao.findByKey( new MenuItemKey( menuItemKey ) ); if ( menuItem == null ) { return SiteXmlCreator.createEmptyMenuBranch(); } SiteXmlCreator siteXmlCreator = new SiteXmlCreator( new MenuItemAccessResolver( groupDao ), context.getPreviewContext().getMenuItemInPreviewOrNull(), menuHandler ); siteXmlCreator.setUserXmlAsAdminConsoleStyle( false ); siteXmlCreator.setMenuItemInBranch( menuItem ); siteXmlCreator.setActiveMenuItem( menuItem ); siteXmlCreator.setMenuItemLevels( levels ); siteXmlCreator.setBranchStartLevel( startLevel ); siteXmlCreator.setIncludeTopLevel( topLevel ); siteXmlCreator.setUser( context.getUser() ); return siteXmlCreator.createLegacyGetMenuBranch( menuItem.getSite() ); } @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getMenuItem( DataSourceContext context, int key, boolean withParents ) { MenuItemXMLCreatorSetting setting = new MenuItemXMLCreatorSetting(); setting.user = getUserEntity( context.getUser() ); setting.includeParents = withParents; MenuItemXmlCreator creator = new MenuItemXmlCreator( setting, new MenuItemAccessResolver( groupDao ), context.getPreviewContext().getMenuItemInPreviewOrNull() ); MenuItemEntity menuItem = menuItemDao.findByKey( new MenuItemKey( key ) ); return creator.createLegacyGetMenuItem( menuItem ); } /** * Returns the sub menu that is shown in the menu * * @param context Site context * @param key Root menu item key * @param tagItem Menu item key to tag * @param levels Number of levels to fetch */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getSubMenu( DataSourceContext context, int key, int tagItem, int levels ) { if ( key < 0 ) { return SiteXmlCreator.createEmptyMenuItems(); } MenuItemEntity menuItem = menuItemDao.findByKey( new MenuItemKey( key ) ); if ( menuItem == null ) { return SiteXmlCreator.createEmptyMenuItems(); } SiteXmlCreator siteXmlCreator = new SiteXmlCreator( new MenuItemAccessResolver( groupDao ), context.getPreviewContext().getMenuItemInPreviewOrNull(), menuHandler ); siteXmlCreator.setUserXmlAsAdminConsoleStyle( false ); siteXmlCreator.setUser( getUserEntity( context.getUser() ) ); siteXmlCreator.setMenuItemInBranch( menuItem ); siteXmlCreator.setMenuItemLevels( levels ); if ( tagItem > -1 ) { siteXmlCreator.setActiveMenuItem( menuItemDao.findByKey( new MenuItemKey( tagItem ) ) ); } return siteXmlCreator.createLegacyGetSubMenu( menuItem.getSite() ); } /** * Get a list of category forming a path to a category. * * @param context the Vertical Site context * @param categoryKey a category key * @param withContentCount if true, include content count for each category * @param includeCategory if true, include the root category * @return category xml */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getSuperCategoryNames( DataSourceContext context, int categoryKey, boolean withContentCount, boolean includeCategory ) { return presentationEngine.getSuperCategoryNames( categoryKey, withContentCount, includeCategory ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getIndexValues( DataSourceContext context, String path, int[] categories, boolean includeSubCategories, int[] contentTypes, int index, int count, boolean distinct, String order ) { UserEntity user = getUserEntity( context.getUser() ); boolean descOrder = order != null && order.equalsIgnoreCase( "desc" ); Collection<CategoryKey> categoryFilter = CategoryKey.convertToList( categories ); Collection<ContentTypeKey> contentTypeFilter = ContentTypeKey.convertToList( contentTypes ); return contentService.getIndexValues( user, path, categoryFilter, includeSubCategories, contentTypeFilter, index, count, descOrder ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getAggregatedIndexValues( DataSourceContext context, String path, int[] categories, boolean includeSubCategories, int[] contentTypes ) { UserEntity user = getUserEntity( context.getUser() ); Collection<CategoryKey> categoryFilter = CategoryKey.convertToList( categories ); Collection<ContentTypeKey> contentTypeFilter = ContentTypeKey.convertToList( contentTypes ); return contentService.getAggregatedIndexValues( user, path, categoryFilter, includeSubCategories, contentTypeFilter ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getMyContentByCategory( DataSourceContext context, String query, int[] categories, boolean includeSubCategories, String orderBy, int index, int count, boolean titlesOnly, int childrenLevel, int parentLevel, int parentChildrenLevel, boolean relatedTitlesOnly, boolean includeTotalCount, boolean includeUserRights, int[] contentTypes ) { PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); if ( ( user != null ) && ( !user.isAnonymous() ) ) { String ownerQuery = "owner/@key = '" + user.getKey() + "'"; if ( ( query == null ) || ( query.trim().length() == 0 ) ) { query = ownerQuery; } else { query = "(" + query + ") AND " + ownerQuery; } } else { count = 0; } ContentXMLCreator xmlCreator = new ContentXMLCreator(); XMLDocument doc; if ( count == 0 ) { doc = xmlCreator.createEmptyDocument( "My content is not available for anonymous" ); } else { Collection<CategoryKey> categoryFilter = CategoryKey.convertToList( categories ); Collection<ContentTypeKey> contentTypeFilter = ContentTypeKey.convertToList( contentTypes ); final Date now = new Date(); ContentByCategoryQuery contentByCategoryQuery = new ContentByCategoryQuery(); contentByCategoryQuery.setUser( user ); contentByCategoryQuery.setCategoryKeyFilter( categoryFilter, includeSubCategories ? Integer.MAX_VALUE : 1 ); contentByCategoryQuery.setQuery( query ); contentByCategoryQuery.setOrderBy( orderBy ); contentByCategoryQuery.setContentTypeFilter( contentTypeFilter ); contentByCategoryQuery.setCount( count ); contentByCategoryQuery.setIndex( index ); contentByCategoryQuery.setFilterContentOnlineAt( now ); ContentResultSet contents = contentService.queryContent( contentByCategoryQuery ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( contents ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( parentChildrenLevel ); relatedContentQuery.setIncludeOnlyMainVersions( true ); RelatedContentResultSet relatedContents = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContents = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContents ); } xmlCreator.setIncludeContentData( !titlesOnly ); xmlCreator.setIncludeRelatedContentData( !relatedTitlesOnly ); xmlCreator.setIncludeUserRightsInfo( includeUserRights, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setResultIndexing( index, count ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); doc = xmlCreator.createContentsDocument( user, contents, relatedContents ); } addDataTraceInfo( doc.getAsJDOMDocument() ); return doc; } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getCategories( DataSourceContext context, int superCategoryKey, int level, boolean withContentCount, boolean includeCategory ) { org.w3c.dom.Document doc = presentationEngine.getCategories( context.getUser(), superCategoryKey, level, includeCategory, true, true, withContentCount ); DataSourceServiceCompabilityKeeper.fixCategoriesCompability( doc ); return XMLDocumentFactory.create( doc ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getCategories( DataSourceContext context, int key, int levels, boolean topLevel, boolean details, boolean catCount, boolean contentCount ) { return XMLDocumentFactory.create( presentationEngine.getCategories( context.getUser(), key, levels, topLevel, details, catCount, contentCount ) ); } @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getUserstore( final DataSourceContext context, final String userstore ) { final UserStoreXmlCreator userStoreXmlCreator = new UserStoreXmlCreator( userStoreService.getUserStoreConnectorConfigs() ); Document userstoreDoc; try { if ( Strings.isNullOrEmpty( userstore ) ) { userstoreDoc = userStoreXmlCreator.createUserStoresDocument( userStoreService.getDefaultUserStore() ); } else { UserStoreEntity userStore = new UserStoreParser( userStoreDao ).parseUserStore( userstore ); if ( userStore != null ) { userstoreDoc = userStoreXmlCreator.createUserStoresDocument( userStore ); } else { userstoreDoc = userStoreXmlCreator.createUserStoreNotFoundDocument( userstore ); } } } catch ( UserStoreNotFoundException e ) { userstoreDoc = userStoreXmlCreator.createUserStoreNotFoundDocument( userstore ); } return XMLDocumentFactory.create( userstoreDoc ); } /** * @inheritDoc */ @Transactional(propagation = Propagation.REQUIRED, readOnly = true) public XMLDocument getPreferences( DataSourceContext context, String scope, String wildCardKey, boolean uniqueMatch ) { final UserEntity user = getUserEntity( context.getUser() ); PreferenceSpecification spec = new PreferenceSpecification( user ); if ( StringUtils.isEmpty( scope ) || "*".equals( scope ) ) { spec.setPreferenceScopes( PreferenceScopeResolver.resolveAllScopes( context.getPortalInstanceKey(), context.getSiteKey() ) ); } else { List<PreferenceScope> resolvedScopes = PreferenceScopeResolver.resolveScopes( scope, context.getPortalInstanceKey(), context.getSiteKey() ); if ( resolvedScopes.isEmpty() ) { return PreferenceXmlCreator.createEmptyPreferencesDocument( "Scope " + scope + " is not a valid scope list" ); } spec.setPreferenceScopes( resolvedScopes ); } spec.setWildCardBaseKey( wildCardKey ); List<PreferenceEntity> preferences = this.preferenceService.getPreferences( spec ); if ( uniqueMatch ) { preferences = getUniqueMatches( preferences ); } return PreferenceXmlCreator.createPreferencesDocument( preferences ); } private List<PreferenceEntity> getUniqueMatches( List<PreferenceEntity> allPreferences ) { List<PreferenceEntity> uniquePreferences = new ArrayList<PreferenceEntity>(); PreferenceUniqueMatchResolver uniqueMatchResolver = new PreferenceUniqueMatchResolver(); for ( PreferenceEntity preference : allPreferences ) { uniqueMatchResolver.addPreferenceKeyIfHigherPriority( preference.getKey() ); } List<PreferenceKey> uniqueKeys = uniqueMatchResolver.getUniquePreferenceKeys(); for ( PreferenceEntity preference : allPreferences ) { if ( uniqueKeys.contains( preference.getKey() ) ) { uniquePreferences.add( preference ); } } return uniquePreferences; } private XMLDocument doGetRelatedContent( DataSourceContext context, int[] contentKeys, int relation, String query, String orderBy, boolean requireAll, int index, int count, int parentLevel, int childrenLevel, boolean includeOwnerAndModifierData, boolean includeContentData, boolean includeCategoryData, boolean includeRelatedContentData, final String facets ) { XMLDocument xmlDocument = null; try { final UserEntity user = getUserEntity( context.getUser() ); final List<ContentKey> contentFilter = ContentKey.convertToList( contentKeys ); final GetRelatedContentExecutor getRelatedContentExecutor = new GetRelatedContentExecutor( contentService, timeService.getNowAsDateTime().toDate(), context.getPreviewContext() ); getRelatedContentExecutor.user( user ); getRelatedContentExecutor.requireAll( requireAll ); getRelatedContentExecutor.relation( relation ); getRelatedContentExecutor.query( query ); getRelatedContentExecutor.orderBy( orderBy ); getRelatedContentExecutor.index( index ); getRelatedContentExecutor.count( count ); getRelatedContentExecutor.childrenLevel( childrenLevel ); getRelatedContentExecutor.parentLevel( parentLevel ); getRelatedContentExecutor.parentChildrenLevel( 0 ); if ( contentFilter != null ) { getRelatedContentExecutor.contentFilter( contentFilter ); } final GetRelatedContentResult result = getRelatedContentExecutor.execute(); final GetRelatedContentXmlCreator getRelatedContentXmlCreator = new GetRelatedContentXmlCreator( new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); getRelatedContentXmlCreator.user( user ); getRelatedContentXmlCreator.startingIndex( index ); getRelatedContentXmlCreator.resultLength( count ); getRelatedContentXmlCreator.includeContentsContentData( includeContentData ); getRelatedContentXmlCreator.includeRelatedContentsContentData( includeRelatedContentData ); getRelatedContentXmlCreator.includeOwnerAndModifierData( includeOwnerAndModifierData ); getRelatedContentXmlCreator.includeCategoryData( includeCategoryData ); xmlDocument = getRelatedContentXmlCreator.create( result ); addFacetResultSet( result.getContent(), xmlDocument ); } catch ( InvalidKeyException e ) { xmlDocument = new ContentXMLCreator().createEmptyDocument( "Invalid key: " + e.getMessage() ); } finally { if ( xmlDocument != null ) { addDataTraceInfo( xmlDocument.getAsJDOMDocument() ); } } return xmlDocument; } private XMLDocument doGetContent( DataSourceContext context, int[] contentKeys, String query, String orderBy, int index, int count, int parentLevel, int childrenLevel, int parentChildrenLevel, boolean includeContentData, boolean includeRelatedContentData, boolean includeUserRights, int[] filterByCategories, boolean categoryRecursive, int[] filterByContentTypes, final String facets ) { UserEntity user = getUserEntity( context.getUser() ); GetContentExecutor executor = new GetContentExecutor( contentService, contentDao, userDao, timeService.getNowAsDateTime(), context.getPreviewContext() ); try { executor.user( user.getKey() ); executor.query( query ); executor.orderBy( orderBy ); executor.index( index ); executor.count( count ); executor.parentLevel( parentLevel ); executor.childrenLevel( childrenLevel ); executor.parentChildrenLevel( parentChildrenLevel ); executor.contentFilter( ContentKey.convertToList( contentKeys ) ); executor.categoryFilter( CategoryKey.convertToList( filterByCategories ), categoryRecursive ? Integer.MAX_VALUE : 1 ); executor.contentTypeFilter( ContentTypeKey.convertToList( filterByContentTypes ) ); executor.facets( facets ); GetContentResult getContentResult = executor.execute(); GetContentXmlCreator getContentXmlCreator = new GetContentXmlCreator( new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); getContentXmlCreator.user( user ); getContentXmlCreator.startingIndex( index ); getContentXmlCreator.resultLength( count ); getContentXmlCreator.includeContentsContentData( includeContentData ); getContentXmlCreator.includeRelatedContentsContentData( includeRelatedContentData ); getContentXmlCreator.includeUserRights( includeUserRights ); getContentXmlCreator.versionInfoStyle( GetContentXmlCreator.VersionInfoStyle.PORTAL ); XMLDocument xml = getContentXmlCreator.create( getContentResult ); addFacetResultSet( getContentResult.getContentResultSet(), xml ); addDataTraceInfo( xml.getAsJDOMDocument() ); return xml; } catch ( InvalidKeyException e ) { ContentXMLCreator xmlCreator = new ContentXMLCreator(); return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } } private XMLDocument doGetContentVersion( DataSourceContext context, int[] versionKeys, int childrenLevel ) { ContentXMLCreator xmlCreator = new ContentXMLCreator(); try { if ( versionKeys == null || versionKeys.length == 0 ) { throw new IllegalArgumentException( "Missing one or more versionkeys" ); } Date now = new Date(); List<ContentVersionEntity> versions = new ArrayList<ContentVersionEntity>( versionKeys.length ); UserEntity user = getUserEntity( context.getUser() ); ContentAccessResolver contentAccessResolver = new ContentAccessResolver( groupDao ); for ( int versionKey : versionKeys ) { ContentVersionKey key = new ContentVersionKey( versionKey ); ContentVersionEntity version = contentVersionDao.findByKey( key ); if ( version == null ) { continue; } final boolean mainVersionOnline = version.getContent().isOnline( now ); final boolean versionCheckOK = version.isApproved() || version.isArchived() || version.isSnapshot(); final boolean accessCheckOK = contentAccessResolver.hasReadContentAccess( user, version.getContent() ); if ( mainVersionOnline && versionCheckOK && accessCheckOK ) { versions.add( version ); } } RelatedChildrenContentQuery spec = new RelatedChildrenContentQuery( now ); spec.setChildrenLevel( childrenLevel ); spec.setContentVersions( versions ); spec.setUser( user ); RelatedContentResultSet relatedContent = contentService.queryRelatedContent( spec ); xmlCreator.setIncludeVersionsInfoForPortal( true ); xmlCreator.setIncludeAccessRightsInfo( true ); xmlCreator.setIncludeUserRightsInfo( true, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setIncludeOwnerAndModifierData( true ); xmlCreator.setIncludeContentData( true ); xmlCreator.setIncludeCategoryData( true ); xmlCreator.setIncludeAssignment( true ); return xmlCreator.createContentVersionsDocument( user, versions, relatedContent ); } catch ( InvalidKeyException e ) { return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } } private XMLDocument doGetContentByCategory( DataSourceContext context, int[] categoryKeys, int levels, String query, String orderBy, int index, int count, int childrenLevel, int parentLevel, int parentChildrenLevel, boolean includeOwnerAndModifierData, boolean includeContentData, boolean includeCategoryData, boolean includeRelatedContentData, boolean includeUserRights, int[] contentTypes, final boolean filterOnUser, final String facets ) { final PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); if ( filterOnUser ) { query = applyUserFilterToQuery( query, user ); } ContentXMLCreator xmlCreator = new ContentXMLCreator(); Date now = timeService.getNowAsDateTime().toDate(); ContentByCategoryQuery contentByCategoryQuery = new ContentByCategoryQuery(); try { contentByCategoryQuery.setCategoryKeyFilter( CategoryKey.convertToList( categoryKeys ), levels ); contentByCategoryQuery.setContentTypeFilter( ContentTypeKey.convertToList( contentTypes ) ); contentByCategoryQuery.setUser( user ); contentByCategoryQuery.setQuery( query ); contentByCategoryQuery.setOrderBy( orderBy ); contentByCategoryQuery.setCount( count ); contentByCategoryQuery.setIndex( index ); contentByCategoryQuery.setFilterContentOnlineAt( now ); contentByCategoryQuery.setFacets( facets ); ContentResultSet contents = contentService.queryContent( contentByCategoryQuery ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( contents ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( parentChildrenLevel ); relatedContentQuery.setIncludeOnlyMainVersions( true ); relatedContentQuery.setOnlineCheckDate( now ); RelatedContentResultSet relatedContent = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContent = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContent ); } xmlCreator.setResultIndexing( index, count ); xmlCreator.setIncludeOwnerAndModifierData( includeOwnerAndModifierData ); xmlCreator.setIncludeContentData( includeContentData ); xmlCreator.setIncludeCategoryData( includeCategoryData ); xmlCreator.setIncludeRelatedContentData( includeRelatedContentData ); xmlCreator.setIncludeUserRightsInfo( includeUserRights, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); XMLDocument doc = xmlCreator.createContentsDocument( user, contents, relatedContent ); addFacetResultSet( contents, doc ); addDataTraceInfo( doc.getAsJDOMDocument() ); return doc; } catch ( InvalidKeyException e ) { return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } } private String applyUserFilterToQuery( String query, final UserEntity user ) { if ( ( user != null ) && ( !user.isAnonymous() ) ) { String ownerQuery = "owner/@key = '" + user.getKey() + "'"; if ( Strings.isNullOrEmpty( query ) ) { query = ownerQuery; } else { query = "(" + query + ") AND " + ownerQuery; } } return query; } private XMLDocument doGetContentBySection( DataSourceContext context, int[] menuItemKeys, int levels, String query, String orderBy, int fromIndex, int count, int parentLevel, int childrenLevel, int parentChildrenLevel, boolean includeOwnerAndModifierData, boolean includeContentData, boolean includeCategoryData, boolean includeRelatedContentData, boolean includeUserRights, int[] filterByContentTypes, final String facets ) { PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); ContentXMLCreator xmlCreator = new ContentXMLCreator(); ContentBySectionQuery spec = new ContentBySectionQuery(); final Date now = new Date(); try { spec.setMenuItemKeys( MenuItemKey.converToList( menuItemKeys ) ); spec.setContentTypeFilter( ContentTypeKey.convertToList( filterByContentTypes ) ); spec.setUser( user ); //spec.setApprovedSectionContentOnly( true ); spec.setSectionFilterStatus( SectionFilterStatus.APPROVED_ONLY ); spec.setLevels( levels ); spec.setIndex( fromIndex ); spec.setCount( count ); spec.setQuery( query ); spec.setOrderBy( orderBy ); spec.setFilterContentOnlineAt( now ); spec.setFacets( facets ); ContentResultSet contents = contentService.queryContent( spec ); xmlCreator.setIncludeOwnerAndModifierData( includeOwnerAndModifierData ); xmlCreator.setIncludeContentData( includeContentData ); xmlCreator.setIncludeCategoryData( includeCategoryData ); xmlCreator.setIncludeRelatedContentData( includeRelatedContentData ); xmlCreator.setIncludeUserRightsInfo( includeUserRights, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setResultIndexing( fromIndex, count ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( contents ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( parentChildrenLevel ); relatedContentQuery.setIncludeOnlyMainVersions( true ); relatedContentQuery.setFilterContentOnlineAt( now ); RelatedContentResultSet relatedContents = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContents = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContents ); } XMLDocument document = xmlCreator.createContentsDocument( user, contents, relatedContents ); addFacetResultSet( contents, document ); addDataTraceInfo( document.getAsJDOMDocument() ); return document; } catch ( InvalidKeyException e ) { return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } catch ( InvalidContentBySectionQueryException e ) { return xmlCreator.createEmptyDocument( e.getMessage() ); } } private XMLDocument doGetRandomContentBySection( DataSourceContext context, int[] menuItemKeys, int levels, String query, int count, int parentLevel, int childrenLevel, boolean includeOwnerAndModifierData, boolean includeContentData, boolean includeCategoryData, boolean includeRelatedContentData, boolean includeUserRights ) { PreviewContext previewContext = context.getPreviewContext(); UserEntity user = getUserEntity( context.getUser() ); ContentXMLCreator xmlCreator = new ContentXMLCreator(); final Date now = new Date(); ContentBySectionQuery spec = new ContentBySectionQuery(); try { spec.setMenuItemKeys( MenuItemKey.converToList( menuItemKeys ) ); } catch ( Exception e ) { return xmlCreator.createEmptyDocument( "Invalid key: " + e.getMessage() ); } spec.setUser( user ); spec.setSectionFilterStatus( SectionFilterStatus.APPROVED_ONLY ); spec.setLevels( levels ); spec.setIndex( 0 ); spec.setCount( Integer.MAX_VALUE ); spec.setQuery( query ); spec.setFilterContentOnlineAt( now ); ContentResultSet contents = contentService.queryContent( spec ); if ( previewContext.isPreviewingContent() ) { contents = previewContext.getContentPreviewContext().overrideContentResultSet( contents ); } ContentResultSet randomContent = contents.createRandomizedResult( count ); RelatedContentQuery relatedContentQuery = new RelatedContentQuery( now ); relatedContentQuery.setUser( user ); relatedContentQuery.setContentResultSet( randomContent ); relatedContentQuery.setParentLevel( parentLevel ); relatedContentQuery.setChildrenLevel( childrenLevel ); relatedContentQuery.setParentChildrenLevel( 0 ); relatedContentQuery.setIncludeOnlyMainVersions( true ); relatedContentQuery.setFilterContentOnlineAt( now ); RelatedContentResultSet relatedContent = contentService.queryRelatedContent( relatedContentQuery ); if ( previewContext.isPreviewingContent() ) { relatedContent = previewContext.getContentPreviewContext().overrideRelatedContentResultSet( relatedContent ); } xmlCreator.setIncludeOwnerAndModifierData( includeOwnerAndModifierData ); xmlCreator.setIncludeContentData( includeContentData ); xmlCreator.setIncludeCategoryData( includeCategoryData ); xmlCreator.setIncludeRelatedContentData( includeRelatedContentData ); xmlCreator.setIncludeUserRightsInfo( includeUserRights, new CategoryAccessResolver( groupDao ), new ContentAccessResolver( groupDao ) ); xmlCreator.setResultIndexing( 0, count ); xmlCreator.setIncludeVersionsInfoForPortal( false ); xmlCreator.setIncludeAssignment( true ); XMLDocument doc = xmlCreator.createContentsDocument( user, randomContent, relatedContent ); addDataTraceInfo( doc.getAsJDOMDocument() ); return doc; } /** * Adds traceInfo to a content document before it's returned. * * @param doc A JDom document with all information that needs to be traced. */ @SuppressWarnings("unchecked") private void addDataTraceInfo( Document doc ) { DataTraceInfo traceInfo = RenderTrace.getCurrentDataTraceInfo(); if ( traceInfo != null ) { Element root = doc.getRootElement(); List<Element> contentNodes = root.getChildren( "content" ); for ( Element e : contentNodes ) { Integer key = Integer.parseInt( e.getAttributeValue( "key" ) ); Element firstChild = (Element) e.getChildren( "title" ).get( 0 ); String title = firstChild.getText(); traceInfo.addContentInfo( key, title ); } Element relatedContentsNode = root.getChild( "relatedcontents" ); if ( relatedContentsNode != null ) { List<Element> relatedContentNodes = relatedContentsNode.getChildren( "content" ); for ( Element e : relatedContentNodes ) { Integer key = Integer.parseInt( e.getAttributeValue( "key" ) ); Element firstChild = (Element) e.getChildren( "title" ).get( 0 ); String title = firstChild.getText(); traceInfo.addRelatedContentInfo( key, title ); } } } } private UserEntity getUserEntity( User user ) { return userDao.findByKey( user.getKey() ); } @Autowired public void setContentDao( ContentDao contentDao ) { this.contentDao = contentDao; } @Autowired public void setUserDao( UserDao userDao ) { this.userDao = userDao; } @Autowired public void setPresentationEngine( PresentationEngine presentationEngine ) { this.presentationEngine = presentationEngine; } @Autowired public void setContentService( ContentService service ) { this.contentService = service; } @Autowired public void setPreferenceService( PreferenceService preferenceService ) { this.preferenceService = preferenceService; } @Autowired public void setSitePropertiesService( SitePropertiesService sitePropertiesService ) { this.sitePropertiesService = sitePropertiesService; } @Autowired public void setTimeService( TimeService timeService ) { this.timeService = timeService; } @Autowired public void setUserStoreService( UserStoreService userStoreService ) { this.userStoreService = userStoreService; } }