001/*
002 *  Copyright 2017 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.userdirectory;
017
018import java.util.ArrayList;
019import java.util.List;
020
021import org.apache.avalon.framework.component.Component;
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025
026import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
027import org.ametys.cms.repository.Content;
028import org.ametys.core.user.UserIdentity;
029import org.ametys.plugins.contentio.synchronize.rights.SynchronizedRootContentHelper;
030import org.ametys.plugins.repository.AmetysObjectIterable;
031import org.ametys.plugins.repository.AmetysObjectResolver;
032import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
033import org.ametys.plugins.repository.UnknownAmetysObjectException;
034import org.ametys.plugins.repository.collection.AmetysObjectCollection;
035import org.ametys.runtime.plugin.component.AbstractLogEnabled;
036
037/**
038 * Helper for user directory.
039 */
040public class UserDirectoryHelper extends AbstractLogEnabled implements Component, Serviceable
041{
042    /** The avalon role. */
043    public static final String ROLE = UserDirectoryHelper.class.getName();
044    
045    /** The root node name of the plugin */
046    public static final String USER_DIRECTORY_ROOT_NODE = "userdirectory";
047    
048    /** The orgUnit parent metadata */
049    public static final String ORGUNITS_METADATA = "orgunits";
050    
051    /** The ametys object resolver */
052    protected AmetysObjectResolver _resolver;
053    
054    /** The content type extension point */
055    protected ContentTypeExtensionPoint _cTypeEP;
056    
057    @Override
058    public void service(ServiceManager manager) throws ServiceException
059    {
060        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
061        _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
062    }
063    
064    /**
065     * Gets the root of user directory contents
066     * @return the root of user directory contents
067     */
068    public AmetysObjectCollection getUserDirectoryRootContent()
069    {
070        return getUserDirectoryRootContent(false);
071    }
072    
073    /**
074     * Gets the root of user directory contents
075     * @param create <code>true</code> to create automatically the root when missing.
076     * @return the root of user directory contents
077     */
078    public AmetysObjectCollection getUserDirectoryRootContent(boolean create)
079    {
080        ModifiableTraversableAmetysObject pluginsNode = _resolver.resolveByPath("/ametys:plugins/");
081        
082        boolean needSave = false;
083        if (!pluginsNode.hasChild(USER_DIRECTORY_ROOT_NODE))
084        {
085            if (create)
086            {
087                pluginsNode.createChild(USER_DIRECTORY_ROOT_NODE, "ametys:unstructured");
088                needSave = true;
089            }
090            else
091            {
092                throw new UnknownAmetysObjectException("Node '/ametys:plugins/userdirectory' is missing");
093            }
094        }
095        
096        ModifiableTraversableAmetysObject userdirectoryNode = pluginsNode.getChild(USER_DIRECTORY_ROOT_NODE);
097        if (!userdirectoryNode.hasChild(SynchronizedRootContentHelper.IMPORTED_CONTENTS_ROOT_NODE))
098        {
099            if (create)
100            {
101                userdirectoryNode.createChild(SynchronizedRootContentHelper.IMPORTED_CONTENTS_ROOT_NODE, "ametys:collection");
102                needSave = true;
103            }
104            else
105            {
106                throw new UnknownAmetysObjectException("Node '/ametys:plugins/userdirectory/ametys:contents' is missing");
107            }
108        }
109        
110        if (needSave)
111        {
112            pluginsNode.saveChanges();
113        }
114        
115        return userdirectoryNode.getChild(SynchronizedRootContentHelper.IMPORTED_CONTENTS_ROOT_NODE);
116    }
117    
118    /**
119     * Get the list of orgunits content
120     * @param user the user content
121     * @return the list of orgunits
122     */
123    public List<Content> getOrgUnits(Content user)
124    {
125        List<Content> contentList = new ArrayList<>();
126        String[] contents = user.getMetadataHolder().getStringArray(ORGUNITS_METADATA, new String[0]);
127        for (String contentId : contents)
128        {
129            try
130            {
131                contentList.add(_resolver.resolveById(contentId));
132            }
133            catch (Exception e) 
134            {
135                getLogger().warn("The content with id " + contentId + " doesn't exist", e);
136            }
137        }
138        
139        return contentList;
140    }
141    
142    /**
143     * Get user content from user identity
144     * @param user the user identity
145     * @param lang the lang
146     * @return the user content (null if it not exist)
147     */
148    public Content getUserContent(UserIdentity user, String lang)
149    {
150     // Content type condition
151        StringBuilder conditionAsString = new StringBuilder("(@ametys-internal:contentType='");
152        conditionAsString.append(UserDirectoryPageHandler.ABSTRACT_USER_CONTENT_TYPE);              
153        conditionAsString.append("'");              
154        for (String contentTypeId : _cTypeEP.getSubTypes(UserDirectoryPageHandler.ABSTRACT_USER_CONTENT_TYPE))
155        {              
156            conditionAsString.append(" or @ametys-internal:contentType='");
157            conditionAsString.append(contentTypeId);
158            conditionAsString.append("'");
159        }
160        
161        // Lang condition
162        conditionAsString.append(") and ametys-internal:language='");
163        conditionAsString.append(lang);
164        conditionAsString.append("'");
165        
166        // Login condition
167        conditionAsString.append(" and ametys:user/@ametys:login='");
168        conditionAsString.append(user.getLogin());
169        conditionAsString.append("'");
170        
171        // Population condition
172        conditionAsString.append(" and ametys:user/@ametys:population='");
173        conditionAsString.append(user.getPopulationId());
174        conditionAsString.append("'");
175        
176        String query = "//element(*, ametys:content)[" + conditionAsString + "]";
177        AmetysObjectIterable<Content> contents = _resolver.query(query);
178        
179        long size = contents.getSize();
180        if (size > 1)
181        {
182            getLogger().warn("There are several content user link to user " + user.getLogin() + " (" + user.getPopulationId() + ")");
183        }
184        
185        if (size > 0)
186        {
187            return contents.iterator().next();
188        }
189        
190        return null;
191    }
192}