/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.content.resultset; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.base.Preconditions; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import com.enonic.cms.core.content.ContentEntity; import com.enonic.cms.core.content.ContentKey; import com.enonic.cms.core.content.ContentVersionEntity; import com.enonic.cms.core.content.ContentVersionKey; public class RelatedContentResultSetImpl implements RelatedContentResultSet { /** * The distinct set of related Content. */ private Set<ContentKey> contentKeySet = new LinkedHashSet<ContentKey>(); private Set<ContentEntity> contentSet = new LinkedHashSet<ContentEntity>(); /** * The distinct map of RelatedContent, mapped by content key. */ private Multimap<ContentKey, RelatedContent> multipleRelatedContentByContentKey = LinkedHashMultimap.create(); private Multimap<ContentVersionKey, RelatedChildContent> relatedChildrenByVersionKey = LinkedHashMultimap.create(); private Map<ContentKey, List<RelatedParentContent>> rootRelatedParents = new HashMap<ContentKey, List<RelatedParentContent>>(); private Map<ContentVersionKey, List<RelatedChildContent>> rootRelatedChildren = new HashMap<ContentVersionKey, List<RelatedChildContent>>(); public int size() { return contentSet.size(); } public boolean isEmpty() { return contentSet.isEmpty(); } public Collection<RelatedContent> getDistinctCollectionOfRelatedContent() { Map<ContentKey, RelatedContent> relatedContentDistinctByContentKey = new LinkedHashMap<ContentKey, RelatedContent>(); for ( RelatedContent rc : multipleRelatedContentByContentKey.values() ) { if ( !relatedContentDistinctByContentKey.containsKey( rc.getContent().getKey() ) ) { relatedContentDistinctByContentKey.put( rc.getContent().getKey(), rc ); } } return relatedContentDistinctByContentKey.values(); } public Set<ContentEntity> getDinstinctSetOfContent() { return contentSet; } public Collection<ContentKey> getContentKeys() { return Collections.unmodifiableSet( contentKeySet ); } public void add( RelatedContent relatedContent ) { doAdd( relatedContent ); } public void addAll( Collection<RelatedContent> collection ) { for ( RelatedContent node : collection ) { doAdd( node ); } } private void doAdd( RelatedContent relatedContent ) { contentKeySet.add( relatedContent.getContent().getKey() ); contentSet.add( relatedContent.getContent() ); if ( relatedContent instanceof RelatedChildContent ) { RelatedChildContent relatedChildContent = (RelatedChildContent) relatedContent; relatedChildrenByVersionKey.put( relatedChildContent.getParentVersionKey(), relatedChildContent ); } multipleRelatedContentByContentKey.put( relatedContent.getContent().getKey(), relatedContent ); multipleRelatedContentByContentKey.get( relatedContent.getContent().getKey() ).size(); } public Iterable<RelatedParentContent> getRootRelatedParents( ContentEntity content ) { List<RelatedParentContent> list = rootRelatedParents.get( content.getKey() ); if ( list == null ) { return new ArrayList<RelatedParentContent>(); } return list; } public Iterable<RelatedChildContent> getRootRelatedChildren( ContentVersionEntity contentVersion ) { List<RelatedChildContent> list = rootRelatedChildren.get( contentVersion.getKey() ); if ( list == null ) { return new ArrayList<RelatedChildContent>(); } return list; } public void addRootRelatedChild( RelatedChildContent child ) { List<RelatedChildContent> list = rootRelatedChildren.get( child.getParentVersionKey() ); if ( list == null ) { list = new ArrayList<RelatedChildContent>(); rootRelatedChildren.put( child.getParentVersionKey(), list ); } list.add( child ); } public void addRootRelatedParent( RelatedParentContent parent ) { List<RelatedParentContent> list = rootRelatedParents.get( parent.getChildContentKey() ); if ( list == null ) { list = new ArrayList<RelatedParentContent>(); rootRelatedParents.put( parent.getChildContentKey(), list ); } list.add( parent ); } public RelatedContent getRelatedContent( ContentKey contentKey ) { final Collection<RelatedContent> collection = multipleRelatedContentByContentKey.get( contentKey ); if ( collection.isEmpty() ) { return null; } return collection.iterator().next(); } public void overwriteRootRelatedChild( RelatedChildContent overwritingRCC ) { contentKeySet.add( overwritingRCC.getContent().getKey() ); contentSet.add( overwritingRCC.getContent() ); multipleRelatedContentByContentKey.put( overwritingRCC.getContent().getKey(), overwritingRCC ); relatedChildrenByVersionKey.put( overwritingRCC.getParentVersionKey(), overwritingRCC ); List<RelatedChildContent> children = rootRelatedChildren.get( overwritingRCC.getParentVersionKey() ); if ( children == null ) { children = new ArrayList<RelatedChildContent>(); rootRelatedChildren.put( overwritingRCC.getParentVersionKey(), children ); } if ( !children.contains( overwritingRCC ) ) { children.add( overwritingRCC ); } else { for ( int i = 0; i < children.size(); i++ ) { if ( overwritingRCC.equals( children.get( i ) ) ) { children.set( i, overwritingRCC ); } } } } public void overwrite( RelatedContentResultSet set ) { Preconditions.checkArgument( set instanceof RelatedContentResultSetImpl, "Given set must be of " + RelatedContentResultSetImpl.class.getSimpleName() ); RelatedContentResultSetImpl setImpl = (RelatedContentResultSetImpl) set; contentKeySet.addAll( setImpl.getContentKeys() ); contentSet.addAll( setImpl.getDinstinctSetOfContent() ); // multiple related content by contentKey for ( RelatedContent relatedContent : setImpl.multipleRelatedContentByContentKey.values() ) { if ( !this.multipleRelatedContentByContentKey.containsEntry( relatedContent.getContent().getKey(), relatedContent ) ) { this.multipleRelatedContentByContentKey.put( relatedContent.getContent().getKey(), relatedContent ); } } // related children by versionKey for ( RelatedChildContent relatedChildContent : setImpl.relatedChildrenByVersionKey.values() ) { this.relatedChildrenByVersionKey.put( relatedChildContent.getParentVersionKey(), relatedChildContent ); } // root related parents for ( RelatedParentContent overwritingRPC : setImpl.doGetAllRootRelatedParents() ) { List<RelatedParentContent> parents = rootRelatedParents.get( overwritingRPC.getChildContentKey() ); if ( parents == null ) { parents = new ArrayList<RelatedParentContent>(); rootRelatedParents.put( overwritingRPC.getChildContentKey(), parents ); } if ( !parents.contains( overwritingRPC ) ) { parents.add( overwritingRPC ); } } // root related children for ( RelatedChildContent overwritingRCC : setImpl.doGetAllRootRelatedChildren() ) { List<RelatedChildContent> children = rootRelatedChildren.get( overwritingRCC.getParentVersionKey() ); if ( children == null ) { children = new ArrayList<RelatedChildContent>(); rootRelatedChildren.put( overwritingRCC.getParentVersionKey(), children ); } if ( !children.contains( overwritingRCC ) ) { children.add( overwritingRCC ); } } } public void retainRelatedRootChildren( ContentVersionKey parent, Collection<ContentKey> children ) { List<RelatedChildContent> relatedChildContents = rootRelatedChildren.get( parent ); if ( relatedChildContents == null ) { return; } List<RelatedChildContent> rcContentsToRemove = new ArrayList<RelatedChildContent>(); for ( RelatedChildContent relatedChildContent : relatedChildContents ) { if ( !children.contains( relatedChildContent.getContent().getKey() ) ) { rcContentsToRemove.add( relatedChildContent ); } } relatedChildContents.removeAll( rcContentsToRemove ); doRemoveRelatedChildContent( parent, rcContentsToRemove ); } private void doRemoveRelatedChildContent( ContentVersionKey parent, Collection<RelatedChildContent> rcContentsToRemove ) { relatedChildrenByVersionKey.removeAll( parent ); for ( RelatedChildContent rccToRemove : rcContentsToRemove ) { doRemoveFromRelatedContentByContentKey( rccToRemove ); } contentKeySet.retainAll( multipleRelatedContentByContentKey.keys() ); List<ContentEntity> contentToRemove = new ArrayList<ContentEntity>(); for ( ContentEntity content : contentSet ) { if ( !contentKeySet.contains( content.getKey() ) ) { contentToRemove.add( content ); } } contentSet.removeAll( contentToRemove ); for ( RelatedChildContent rccToRemove : rcContentsToRemove ) { final ContentVersionEntity version = rccToRemove.getContent().getMainVersion(); final Collection<RelatedChildContent> versionsChildren = relatedChildrenByVersionKey.get( version.getKey() ); if ( versionsChildren == null || versionsChildren.isEmpty() ) { continue; } doRemoveRelatedChildContent( version.getKey(), Lists.newArrayList( versionsChildren ) ); } } private void doRemoveFromRelatedContentByContentKey( RelatedChildContent rccToRemove ) { List<RelatedChildContent> rccToRemoveFrom_relatedContentByContentKey = new ArrayList<RelatedChildContent>(); for ( RelatedContent rc : multipleRelatedContentByContentKey.values() ) { if ( rc instanceof RelatedChildContent ) { RelatedChildContent rcc = (RelatedChildContent) rc; if ( rcc.getParentVersionKey().equals( rccToRemove.getParentVersionKey() ) && rcc.getContent().equals( rccToRemove.getContent() ) ) { rccToRemoveFrom_relatedContentByContentKey.add( rcc ); } } } for ( RelatedChildContent itemToRemove : rccToRemoveFrom_relatedContentByContentKey ) { multipleRelatedContentByContentKey.remove( itemToRemove.getContent().getKey(), itemToRemove ); } } private Iterable<RelatedParentContent> doGetAllRootRelatedParents() { List<RelatedParentContent> allRootRelatedParents = new ArrayList<RelatedParentContent>(); for ( List<RelatedParentContent> list : rootRelatedParents.values() ) { allRootRelatedParents.addAll( list ); } return allRootRelatedParents; } private Iterable<RelatedChildContent> doGetAllRootRelatedChildren() { List<RelatedChildContent> allRootRelatedChildren = new ArrayList<RelatedChildContent>(); for ( List<RelatedChildContent> list : rootRelatedChildren.values() ) { allRootRelatedChildren.addAll( list ); } return allRootRelatedChildren; } }