001/* 002 * Copyright 2021 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.cms.duplicate.contents; 017 018import java.util.ArrayList; 019import java.util.List; 020 021import org.apache.avalon.framework.configuration.Configuration; 022import org.apache.avalon.framework.configuration.ConfigurationException; 023import org.apache.commons.lang3.tuple.Pair; 024 025import org.ametys.cms.contenttype.ContentType; 026import org.ametys.cms.duplicate.contents.attr.AbstractDuplicateAttributeConfiguration; 027import org.ametys.cms.duplicate.contents.attr.DuplicateAttributeConfiguration; 028import org.ametys.cms.duplicate.contents.attr.impl.BooleanDuplicateAttributeConfiguration; 029import org.ametys.cms.duplicate.contents.attr.impl.ContentDuplicateAttributeConfiguration; 030import org.ametys.cms.duplicate.contents.attr.impl.DateDuplicateAttributeConfiguration; 031import org.ametys.cms.duplicate.contents.attr.impl.DateTimeDuplicateAttributeConfiguration; 032import org.ametys.cms.duplicate.contents.attr.impl.DoubleDuplicateAttributeConfiguration; 033import org.ametys.cms.duplicate.contents.attr.impl.LongDuplicateAttributeConfiguration; 034import org.ametys.cms.duplicate.contents.attr.impl.StringDuplicateAttributeConfiguration; 035import org.ametys.runtime.model.ModelItemGroup; 036import org.ametys.runtime.model.type.ModelItemTypeConstants; 037 038/** 039 * Represents the configuration for a content type of content duplicate detection configuration 040 */ 041public class DuplicateContentTypeConfiguration 042{ 043 044 private String _contentTypeId; 045 private List<DuplicateAttributeConfiguration> _attributeList = new ArrayList<>(); 046 private List<Pair<String, List<Object>>> _errorList = new ArrayList<>(); 047 private List<Pair<String, List<Object>>> _warnList = new ArrayList<>(); 048 049 /** 050 * Create a new DuplicateContentTypeConfiguration 051 * @param configuration the configuration used to create the DuplicateContentTypeConfiguration 052 * @param duplicateContentsManager the duplicate contents manager, only use this parameter to get linked components 053 * @throws ConfigurationException if the configuration is not valid. 054 */ 055 public DuplicateContentTypeConfiguration(Configuration configuration, DuplicateContentsManager duplicateContentsManager) throws ConfigurationException 056 { 057 String contentTypeId; 058 contentTypeId = configuration.getAttribute("id"); 059 060 if (duplicateContentsManager._cTypeEP.hasExtension(contentTypeId)) 061 { 062 _contentTypeId = contentTypeId; 063 064 ContentType contentType = duplicateContentsManager._cTypeEP.getExtension(contentTypeId); 065 066 for (Configuration attributeConf : configuration.getChildren("attribute")) 067 { 068 DuplicateAttributeConfiguration duplicateAttributeConfiguration = _createDuplicateAttributeConfiguration(contentType, attributeConf); 069 070 if (duplicateAttributeConfiguration != null) 071 { 072 _attributeList.add(duplicateAttributeConfiguration); 073 } 074 } 075 } 076 else 077 { 078 _errorList.add(Pair.of("Content type not found for identifier '{}'. @{}", List.of(contentTypeId, configuration.getLocation()))); 079 } 080 } 081 082 private AbstractDuplicateAttributeConfiguration _createDuplicateAttributeConfiguration(ContentType contentType, Configuration attributeConfiguration) throws ConfigurationException 083 { 084 085 String path = attributeConfiguration.getAttribute("path"); 086 if (contentType.hasModelItem(path)) 087 { 088 //ModelItemTypeConstants.REPEATER_TYPE_ID.equals 089 boolean insideOfRepeater = false; 090 091 ModelItemGroup parent = contentType.getModelItem(path).getParent(); 092 while (parent != null) 093 { 094 insideOfRepeater = insideOfRepeater || org.ametys.plugins.repository.data.type.ModelItemTypeConstants.REPEATER_TYPE_ID.equals(parent.getType().getId()); 095 parent = parent.getParent(); 096 } 097 098 if (insideOfRepeater) 099 { 100 _warnList.add(Pair.of("Ignored attribute query for attribute with path: {}. Attributes inside of a repeater are not handled.", 101 List.of(path))); 102 } 103 else 104 { 105 String attributeType = contentType.getModelItem(path).getType().getId(); 106 switch (attributeType) 107 { 108 case ModelItemTypeConstants.STRING_TYPE_ID: 109 return new StringDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 110 case org.ametys.cms.data.type.ModelItemTypeConstants.CONTENT_ELEMENT_TYPE_ID: 111 return new ContentDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 112 case ModelItemTypeConstants.DATE_TYPE_ID: 113 return new DateDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 114 case ModelItemTypeConstants.DATETIME_TYPE_ID: 115 return new DateTimeDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 116 case ModelItemTypeConstants.LONG_TYPE_ID: 117 return new LongDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 118 case ModelItemTypeConstants.DOUBLE_TYPE_ID: 119 return new DoubleDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 120 case ModelItemTypeConstants.BOOLEAN_TYPE_ID: 121 return new BooleanDuplicateAttributeConfiguration(attributeConfiguration, attributeType); 122 default: 123 _warnList.add(Pair.of("Ignored attribute query for attribute with path: {}. This attribute type is not handled for duplicate attributes: {}.", 124 List.of(path, 125 contentType.getModelItem(path).getType()))); 126 break; 127 } 128 } 129 } 130 else 131 { 132 _errorList.add(Pair.of("Attribute '{}' not found for content type '{}'. @{}" 133 , List.of(path 134 , contentType.getId() 135 , attributeConfiguration.getLocation()))); 136 } 137 return null; 138 } 139 140 /** 141 * Check if the content type has any attributes that require near duplicate check 142 * @return true if the content type has any attributes that require near duplicate check 143 */ 144 public boolean hasAnyNearDuplicateAttributes() 145 { 146 return _attributeList.stream() 147 .anyMatch(DuplicateAttributeConfiguration::checkNearDuplicate); 148 } 149 150 /** 151 * Get the content type id 152 * @return the content type id 153 */ 154 public String getContentTypeId() 155 { 156 return _contentTypeId; 157 } 158 159 /** 160 * Get the attribute list 161 * @return the attribute list 162 */ 163 public List<DuplicateAttributeConfiguration> getAttributeList() 164 { 165 return _attributeList; 166 } 167 168 /** 169 * get the list of errors 170 * @return the error list 171 */ 172 public List<Pair<String, List<Object>>> getErrors() 173 { 174 return _errorList; 175 } 176 177 /** 178 * get the list of warns 179 * @return the warn list 180 */ 181 public List<Pair<String, List<Object>>> getWarns() 182 { 183 return _warnList; 184 } 185 186}