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