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.attr;
017
018import java.util.ArrayList;
019import java.util.HashSet;
020import java.util.Set;
021
022import org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024
025import org.ametys.cms.search.query.AndQuery;
026import org.ametys.cms.search.query.NotQuery;
027import org.ametys.cms.search.query.Query;
028
029/**
030 * This abstract class represents a {@link DuplicateAttributeConfiguration}
031 * @param <T> The type of the attribute
032 */
033public abstract class AbstractDuplicateAttributeConfiguration<T> implements DuplicateAttributeConfiguration<T>
034{
035    
036    /** The component role. */
037    public static final String ROLE = AbstractDuplicateAttributeConfiguration.class.getName();
038
039    /** The type of the attribute. */
040    protected String _type;
041
042    /** The path of the attribute. */
043    protected String _path;
044
045    /** Defines this attribute should also check for near duplicates. */
046    protected boolean _checkNearDuplicate;
047
048    /**
049     * Create a new DuplicateAttributeConfiguration
050     * @param configuration the configuration used to create the DuplicateAttributeConfiguration
051     * @param attributeType the attribute type id
052     * @throws ConfigurationException if the configuration is not valid.
053     */
054    public AbstractDuplicateAttributeConfiguration(Configuration configuration, String attributeType) throws ConfigurationException
055    {
056        _path = configuration.getAttribute("path");
057        _checkNearDuplicate = _computeCheckNearDuplicate(configuration);
058        _type = attributeType;
059    }
060
061    /**
062     * Check if this attribute should also check for near duplicates
063     * @param configuration the configuration used to create the DuplicateAttributeConfiguration
064     * @return true if this attribute should also check for near duplicates
065     */
066    protected boolean _computeCheckNearDuplicate(Configuration configuration)
067    {
068        return false;
069    }
070
071    @Override
072    public String getType()
073    {
074        return _type;
075    }
076
077    @Override
078    public void setType(String type)
079    {
080        this._type = type;
081    }
082
083    @Override
084    public String getPath()
085    {
086        return _path;
087    }
088
089    @Override
090    public void setPath(String path)
091    {
092        this._path = path;
093    }
094
095    @Override
096    public boolean checkNearDuplicate()
097    {
098        return _checkNearDuplicate;
099    }
100
101    /**
102     * Get the query to check if a field is filled
103     * @return the query
104     */
105    protected abstract Query getExistQuery();
106
107    /**
108     * Get the query to check if other contents have the same value
109     * @param value the value to check
110     * @return the query
111     */
112    protected abstract Query getDuplicateQuery(T value);
113
114    /**
115     * Get the query to check if other contents have almost the same value
116     * @param value the value to check
117     * @return the query
118     */
119    protected Query getNearDuplicateQuery(T value)
120    {
121        return getDuplicateQuery(value);
122    }
123
124    /**
125     * Get the query to find duplicate of this attributes
126     * @param value the value of the attribute
127     * @param nearDuplicateQuery true if the query should check near duplicates
128     * @return the query to find duplicate of this attributes
129     */
130    protected Query getDuplicate(T value, boolean nearDuplicateQuery)
131    {
132        return nearDuplicateQuery ? getNearDuplicateQuery(value) : getDuplicateQuery(value);
133    }
134
135    @Override
136    @SuppressWarnings("unchecked")
137    public Query getQuery(Object value, boolean nearDuplicateQuery)
138    {
139        if (value == null || isEmpty(value))
140        {
141            return new NotQuery(getExistQuery());
142        }
143        
144        Class<?> type = value.getClass();
145        if (type.isArray())
146        {
147            if (((T[]) value).length == 0)
148            {
149                return new NotQuery(getExistQuery());
150            }
151            
152            Set<Query> queries = new HashSet<>();
153            for (T typedValue : (T[]) value)
154            {
155                queries.add(getDuplicate(typedValue, nearDuplicateQuery));
156            }
157            return new AndQuery(new ArrayList<>(queries));
158        }
159        
160        return getDuplicate((T) value, nearDuplicateQuery);
161    }
162
163    /**
164     * Check if the value is empty
165     * @param value the value
166     * @return true if the value is empty
167     */
168    protected boolean isEmpty(Object value)
169    {
170        return false;
171    }
172}