001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 */
012package org.nuxeo.ecm.automation.features;
013
014import java.util.ArrayList;
015import java.util.Collection;
016import java.util.List;
017import java.util.Set;
018
019import org.apache.commons.lang.StringEscapeUtils;
020import org.apache.commons.lang.StringUtils;
021import org.nuxeo.ecm.automation.core.scripting.CoreFunctions;
022import org.nuxeo.ecm.automation.core.util.StringList;
023import org.nuxeo.ecm.core.api.DataModel;
024import org.nuxeo.ecm.core.api.DocumentModel;
025import org.nuxeo.ecm.core.api.NuxeoPrincipal;
026import org.nuxeo.ecm.core.query.sql.NXQL;
027import org.nuxeo.ecm.core.uidgen.UIDGeneratorService;
028import org.nuxeo.ecm.core.uidgen.UIDSequencer;
029import org.nuxeo.ecm.directory.Session;
030import org.nuxeo.ecm.directory.api.DirectoryService;
031import org.nuxeo.ecm.platform.usermanager.UserManager;
032import org.nuxeo.runtime.api.Framework;
033
034/**
035 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
036 */
037public class PlatformFunctions extends CoreFunctions {
038
039    private volatile DirectoryService dirService;
040
041    private volatile UserManager userMgr;
042
043    public UserManager getUserManager() {
044        if (userMgr == null) {
045            userMgr = Framework.getService(UserManager.class);
046        }
047        return userMgr;
048    }
049
050    public DirectoryService getDirService() {
051        if (dirService == null) {
052            dirService = Framework.getService(DirectoryService.class);
053        }
054        return dirService;
055    }
056
057    public String getVocabularyLabel(String voc, String key) {
058        try (Session session = getDirService().open(voc)) {
059            DocumentModel doc = session.getEntry(key);
060            // TODO: which is the best method to get "label" property when not
061            // knowing vocabulary schema?
062            // AT: the best is to accept it as a parameter of the method, and
063            // fallback on "label" when not given
064            DataModel dm = doc.getDataModels().values().iterator().next();
065            return (String) dm.getData("label");
066        }
067    }
068
069    public NuxeoPrincipal getPrincipal(String username) {
070        return getUserManager().getPrincipal(username);
071    }
072
073    protected String getEmail(NuxeoPrincipal principal, String userSchemaName, String userEmailFieldName) {
074        if (principal == null) {
075            return null;
076        }
077        return (String) principal.getModel().getProperty(userSchemaName, userEmailFieldName);
078    }
079
080    public String getEmail(String username) {
081        UserManager userManager = getUserManager();
082        return getEmail(userManager.getPrincipal(username), userManager.getUserSchemaName(),
083                userManager.getUserEmailField());
084    }
085
086    public Set<NuxeoPrincipal> getPrincipalsFromGroup(String group) {
087        return getPrincipalsFromGroup(group, false);
088    }
089
090    public Set<NuxeoPrincipal> getPrincipalsFromGroup(String group, boolean ignoreGroups) {
091        PrincipalHelper ph = new PrincipalHelper(getUserManager(), null);
092        return ph.getPrincipalsFromGroup(group, !ignoreGroups);
093    }
094
095    public StringList getEmailsFromGroup(String group) {
096        return getEmailsFromGroup(group, false);
097    }
098
099    public StringList getEmailsFromGroup(String group, boolean ignoreGroups) {
100        PrincipalHelper ph = new PrincipalHelper(getUserManager(), null);
101        Set<String> emails = ph.getEmailsFromGroup(group, !ignoreGroups);
102        return new StringList(emails);
103    }
104
105    public StringList getPrincipalEmails(List<NuxeoPrincipal> principals) {
106        StringList result = new StringList(principals.size());
107        String schemaName = getUserManager().getUserSchemaName();
108        String fieldName = getUserManager().getUserEmailField();
109        for (NuxeoPrincipal principal : principals) {
110            String email = getEmail(principal, schemaName, fieldName);
111            if (!StringUtils.isEmpty(email)) {
112                result.add(email);
113            }
114        }
115        return result;
116    }
117
118    public StringList getEmails(List<String> usernames) {
119        return getEmails(usernames, false);
120    }
121
122    /**
123     * Returns user emails
124     *
125     * @param usernames list of user names
126     * @param usePrefix indicates if user resolution takes into account nuxeo prefix <b>user:</b>
127     * @since 5.5
128     */
129    public StringList getEmails(List<String> usernames, boolean usePrefix) {
130        if (usernames == null) {
131            return new StringList(0);
132        }
133        UserManager userManager = getUserManager();
134        StringList result = new StringList(usernames.size());
135        String schemaName = getUserManager().getUserSchemaName();
136        String fieldName = getUserManager().getUserEmailField();
137        for (String username : usernames) {
138            NuxeoPrincipal principal = null;
139            if (usePrefix) {
140                if (username.startsWith(NuxeoPrincipal.PREFIX)) {
141                    principal = userManager.getPrincipal(username.replace(NuxeoPrincipal.PREFIX, ""));
142                }
143            } else {
144                principal = userManager.getPrincipal(username);
145            }
146            if (principal != null) {
147                String email = getEmail(principal, schemaName, fieldName);
148                if (!StringUtils.isEmpty(email)) {
149                    result.add(email);
150                }
151            }
152        }
153        return result;
154    }
155
156    public String getNextId(final String key) {
157        return getNextId(key, "hibernateSequencer");
158    }
159
160    public String getNextId(final String key, final String sequencerName) {
161        UIDGeneratorService uidGeneratorService = Framework.getService(UIDGeneratorService.class);
162        UIDSequencer seq = uidGeneratorService.getSequencer(sequencerName);
163        return Integer.toString(seq.getNext(key));
164    }
165
166    public static String htmlEscape(String str) {
167        return StringEscapeUtils.escapeHtml(str);
168    }
169
170    /**
171     * Escapes a string according to NXQL escaping rules.
172     * <p>
173     * The resulting string is safe to include between single quotes in a NXQL expression.
174     *
175     * @param str the input string
176     * @return the escaped string
177     * @since 6.0-HF21, 7.10
178     */
179    public static String nxqlEscape(String str) {
180        return NXQL.escapeStringInner(str);
181    }
182
183    /**
184     * Concatenate into the list given as first argument other arguments. Other arguments will be explosed if it is a
185     * list of object. ex: concatenateInto(myList, a, anotherList) with a is scalar object and anotherList is a list of
186     * object will produced myList.add(a) and the same for each object contained into the anotherList list.
187     *
188     * @param <T>
189     * @param list List of values of type A
190     * @param value Value can be instance of java.util.Collection<Object> or an array of Objects or simply a scalar
191     *            Object. If Null, the parameter is ignored
192     * @return the list that contains the list contain and value (see value description)
193     * @exception xxxxx if in values there is at least one object type not compatible with the collection list
194     */
195    @SuppressWarnings("unchecked")
196    public <T> List<T> concatenateIntoList(List<T> list, Object... values) {
197
198        if (list == null) {
199            throw new IllegalArgumentException("First parameter must not be null");
200        }
201
202        for (Object value : values) {
203            if (value == null) {
204                continue;
205            }
206
207            if (value instanceof Object[]) {
208                for (Object subValue : (Object[]) value) {
209                    if (subValue != null) {
210                        list.add((T) subValue);
211                    }
212                }
213                continue;
214            }
215
216            if (value instanceof Collection) {
217                for (Object subValue : (Collection<Object>) value) {
218                    if (subValue != null) {
219                        list.add((T) subValue);
220                    }
221                }
222                continue;
223            }
224
225            list.add((T) value);
226
227        }
228        return list;
229    }
230
231    /**
232     * Idem than concatenateInto except that a new list is created.
233     */
234    public <T> List<T> concatenateValuesAsNewList(Object... values) {
235
236        List<T> result = new ArrayList<T>();
237        return concatenateIntoList(result, values);
238    }
239
240}