001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.contentio.synchronize; 017 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.Collection; 021import java.util.List; 022import java.util.Map; 023import java.util.Objects; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import javax.jcr.Node; 028import javax.jcr.RepositoryException; 029import javax.jcr.Value; 030 031import org.apache.avalon.framework.service.ServiceException; 032import org.apache.avalon.framework.service.ServiceManager; 033import org.apache.avalon.framework.service.Serviceable; 034 035import org.ametys.cms.content.external.ExternalizableMetadataProvider; 036import org.ametys.cms.contenttype.ContentTypesHelper; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.repository.DefaultContent; 039import org.ametys.plugins.repository.AmetysRepositoryException; 040import org.ametys.runtime.plugin.component.AbstractLogEnabled; 041 042import com.google.common.collect.ImmutableMap; 043 044/** 045 * {@link ExternalizableMetadataProvider} based on a {@link SynchronizableContentsCollection} 046 */ 047public class SynchronizableContentsCollectionMetadataProvider extends AbstractLogEnabled implements ExternalizableMetadataProvider, Serviceable 048{ 049 /** The DAO for synchronizable contents collections */ 050 protected SynchronizableContentsCollectionDAO _synchronizableContentsCollectionDAO; 051 052 /** The content types helper */ 053 protected ContentTypesHelper _contentTypesHelper; 054 055 @Override 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 _synchronizableContentsCollectionDAO = (SynchronizableContentsCollectionDAO) manager.lookup(SynchronizableContentsCollectionDAO.ROLE); 059 _contentTypesHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 060 } 061 062 @Override 063 public Set<String> getExternalOnlyMetadata(Content content) 064 { 065 List<SynchronizableContentsCollection> collections = _getCollectionIds(content).stream() 066 .map(_synchronizableContentsCollectionDAO::getSynchronizableContentsCollection) 067 .filter(Objects::nonNull) 068 .collect(Collectors.toList()); 069 070 Map<String, Object> params = buildParametersMap(content); 071 072 // Return the intersection of the no-synchronized metadata of each collection 073 Set<String> externalMetadata = collections.get(0).getExternalOnlyFields(params); 074 for (int i = 1; i < collections.size(); i++) 075 { 076 externalMetadata.retainAll(collections.get(i).getExternalOnlyFields(params)); 077 } 078 079 return externalMetadata; 080 } 081 082 @Override 083 public Set<String> getExternalAndLocalMetadata(Content content) 084 { 085 return _getCollectionIds(content).stream() 086 .map(_synchronizableContentsCollectionDAO::getSynchronizableContentsCollection) 087 .filter(Objects::nonNull) 088 .map(col -> col.getLocalAndExternalFields(buildParametersMap(content))) 089 .flatMap(Collection::stream) 090 .collect(Collectors.toSet()); 091 } 092 093 private Map<String, Object> buildParametersMap(Content content) 094 { 095 String commonContentType = _contentTypesHelper.getCommonAncestor(Arrays.asList(content.getTypes())); 096 return commonContentType != null ? ImmutableMap.of("contentType", commonContentType) : null; 097 } 098 099 private List<String> _getCollectionIds(Content content) throws AmetysRepositoryException 100 { 101 List<String> collectionIds = new ArrayList<>(); 102 103 if (content instanceof DefaultContent) 104 { 105 try 106 { 107 Node node = ((DefaultContent) content).getNode(); 108 if (node.hasProperty(SynchronizableContentsCollection.COLLECTION_ID_PROPERTY)) 109 { 110 Value[] values = node.getProperty(SynchronizableContentsCollection.COLLECTION_ID_PROPERTY).getValues(); 111 for (Value value : values) 112 { 113 collectionIds.add(value.getString()); 114 } 115 } 116 } 117 catch (RepositoryException e) 118 { 119 getLogger().error("Failed to get linked synchronizable collections for content {}", content.getId(), e); 120 throw new AmetysRepositoryException("Failed to get linked synchronizable collections for content " + content.getId(), e); 121 } 122 } 123 124 return collectionIds; 125 } 126}