001/*
002 *  Copyright 2019 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.data.type.impl;
017
018import java.util.Arrays;
019import java.util.List;
020import java.util.Optional;
021import java.util.stream.Collectors;
022
023import javax.jcr.Session;
024
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.cms.data.ContentValue;
028import org.ametys.cms.data.type.indexing.impl.ContentIndexableElementType;
029import org.ametys.cms.repository.Content;
030import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
031import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
032import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
033import org.ametys.plugins.repository.data.type.RepositoryElementType;
034import org.ametys.runtime.model.exception.BadItemTypeException;
035
036/**
037 * Class for content type of elements stored in the repository
038 */
039public class ContentRepositoryElementType extends ContentIndexableElementType implements RepositoryElementType<ContentValue>
040{
041
042    public Object read(RepositoryData parentData, String name) throws BadItemTypeException
043    {
044        if (!parentData.hasValue(name))
045        {
046            return null;
047        }
048        
049        if (!isCompatible(parentData, name))
050        {
051            throw new BadItemTypeException("Try to get content value from the non content data '" + name + "' on '" + parentData + "'");
052        }
053        else
054        {
055            final Session session =  parentData instanceof JCRRepositoryData ? ((JCRRepositoryData) parentData).getSession() : null;
056            
057            if (parentData.isMultiple(name))
058            {
059                String[] values = parentData.getStrings(name);
060                return Arrays.stream(values)
061                             .map(contentId -> new ContentValue(_resolver, contentId, session))
062                             .collect(Collectors.toList())
063                             .toArray(new ContentValue[values.length]);
064            }
065            else
066            {
067                String contentId = parentData.getString(name);
068                return StringUtils.isNotEmpty(contentId) ? new ContentValue(_resolver, contentId, session) : null;
069            }
070        }
071    }
072    
073    public boolean hasNonEmptyValue(RepositoryData parentData, String name) throws BadItemTypeException
074    {
075        if (!parentData.hasValue(name))
076        {
077            return false;
078        }
079        
080        if (!isCompatible(parentData, name))
081        {
082            throw new BadItemTypeException("Try to check content value from the non content data '" + name + "' on '" + parentData + "'");
083        }
084        
085        if (parentData.isMultiple(name))
086        {
087            return parentData.getStrings(name).length > 0;
088        }
089        else
090        {
091            String contentId = parentData.getString(name);
092            return StringUtils.isNotEmpty(contentId);
093        }
094    }
095
096    public void write(ModifiableRepositoryData parentData, String name, Object value) throws BadItemTypeException
097    {
098        if (value == null)
099        {
100            if (parentData.hasValue(name) && parentData.isMultiple(name))
101            {
102                parentData.setValues(name, new String[0]);
103            }
104            else
105            {
106                parentData.setValue(name, StringUtils.EMPTY);
107            }
108        }
109        else if (value instanceof String)
110        {
111            parentData.setValue(name, (String) value);
112        }
113        else if (value instanceof String[])
114        {
115            List<String> values = Arrays.stream((String[]) value)
116                  .distinct()
117                  .map(v -> Optional.ofNullable(v)
118                                        .orElseThrow(() -> new IllegalArgumentException("Try to set a null value into the multiple " + getId() + " data '" + name + "' on '" + parentData + "'")))
119                  .collect(Collectors.toList());
120            
121            parentData.setValues(name, values.toArray(new String[values.size()]));
122        }
123        else if (value instanceof Content)
124        {
125            parentData.setValue(name, ((Content) value).getId());
126        }
127        else if (value instanceof Content[])
128        {
129            List<String> values = Arrays.stream((Content[]) value)
130                                    .distinct()
131                                    .map(content -> Optional.ofNullable(content)
132                                                            .map(Content::getId)
133                                                            .orElseThrow(() -> new IllegalArgumentException("Try to set a null value into the multiple " + getId() + " data '" + name + "' on '" + parentData + "'")))
134                                    .collect(Collectors.toList());
135            
136            parentData.setValues(name, values.toArray(new String[values.size()]));
137        }
138        else if (value instanceof ContentValue)
139        {
140            parentData.setValue(name, ((ContentValue) value).getContentId());
141        }
142        else if (value instanceof ContentValue[])
143        {
144            List<String> values = Arrays.stream((ContentValue[]) value)
145                                     .distinct()
146                                     .map(content -> Optional.ofNullable(content)
147                                                             .map(ContentValue::getContentId)
148                                                             .orElseThrow(() -> new IllegalArgumentException("Try to set a null value into the multiple " + getId() + " data '" + name + "' on '" + parentData + "'")))
149                                     .collect(Collectors.toList());
150            
151            parentData.setValues(name, values.toArray(new String[values.size()]));
152        }
153        else
154        {
155            throw new BadItemTypeException("Try to set the non string value '" + value + "' to the string data '" + name + "' on '" + parentData + "'");
156        }
157    }
158    
159    public String getRepositoryDataType()
160    {
161        return RepositoryData.STRING_REPOSITORY_DATA_TYPE;
162    }
163}