001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.workplace.tools.accounts;
029
030import org.opencms.file.CmsUser;
031import org.opencms.jsp.CmsJspActionElement;
032import org.opencms.main.CmsException;
033import org.opencms.main.OpenCms;
034import org.opencms.security.CmsRole;
035import org.opencms.util.CmsDataTypeUtil;
036import org.opencms.util.CmsStringUtil;
037import org.opencms.util.CmsUUID;
038import org.opencms.widgets.CmsDisplayWidget;
039import org.opencms.widgets.CmsInputWidget;
040import org.opencms.widgets.I_CmsWidget;
041import org.opencms.workplace.CmsDialog;
042import org.opencms.workplace.CmsWidgetDialog;
043import org.opencms.workplace.CmsWidgetDialogParameter;
044import org.opencms.workplace.CmsWorkplaceSettings;
045import org.opencms.workplace.CmsWorkplaceUserInfoBlock;
046import org.opencms.workplace.CmsWorkplaceUserInfoEntry;
047import org.opencms.workplace.CmsWorkplaceUserInfoManager;
048import org.opencms.workplace.tools.CmsToolManager;
049
050import java.util.ArrayList;
051import java.util.HashMap;
052import java.util.Iterator;
053import java.util.List;
054import java.util.Map;
055import java.util.Map.Entry;
056import java.util.SortedMap;
057import java.util.TreeMap;
058
059import javax.servlet.http.HttpServletRequest;
060import javax.servlet.http.HttpServletResponse;
061import javax.servlet.jsp.PageContext;
062
063/**
064 * Dialog to edit the users additional info in the administration view.<p>
065 *
066 * @since 6.5.6
067 */
068public class CmsEditUserAddInfoDialog extends CmsWidgetDialog {
069
070    /** localized messages Keys prefix. */
071    public static final String KEY_PREFIX = "userinfo";
072
073    /** Defines which pages are valid for this dialog. */
074    public static final String[] PAGES = {"page1"};
075
076    /** The additional information. */
077    protected List<CmsUserAddInfoBean> m_addInfoList;
078
079    /** The user object that is edited on this dialog. */
080    protected CmsUser m_user;
081
082    /** The map of editable additional info entries. */
083    private SortedMap<String, Object> m_addInfoEditable;
084
085    /** The map of non-editable additional info entries. */
086    private SortedMap<String, Object> m_addInfoReadOnly;
087
088    /** Stores the value of the request parameter for the edit all infos flag. */
089    private String m_paramEditall;
090
091    /** Stores the value of the request parameter for the user id. */
092    private String m_paramUserid;
093
094    /**
095     * Public constructor with JSP action element.<p>
096     *
097     * @param jsp an initialized JSP action element
098     */
099    public CmsEditUserAddInfoDialog(CmsJspActionElement jsp) {
100
101        super(jsp);
102    }
103
104    /**
105     * Public constructor with JSP variables.<p>
106     *
107     * @param context the JSP page context
108     * @param req the JSP request
109     * @param res the JSP response
110     */
111    public CmsEditUserAddInfoDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
112
113        this(new CmsJspActionElement(context, req, res));
114    }
115
116    /**
117     * Commits the edited user to the db.<p>
118     */
119    @Override
120    public void actionCommit() {
121
122        List<Throwable> errors = new ArrayList<Throwable>();
123
124        try {
125            if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
126                // fill the values
127                Iterator<CmsUserAddInfoBean> it = m_addInfoList.iterator();
128                while (it.hasNext()) {
129                    CmsUserAddInfoBean infoBean = it.next();
130                    if (infoBean.getValue() == null) {
131                        m_user.deleteAdditionalInfo(infoBean.getName());
132                    } else {
133                        m_user.setAdditionalInfo(
134                            infoBean.getName(),
135                            CmsDataTypeUtil.parse(infoBean.getValue(), infoBean.getType()));
136                    }
137                }
138            } else {
139                Map<String, Object> readOnly = new HashMap<String, Object>();
140                Iterator<Entry<String, Object>> itEntries = m_user.getAdditionalInfo().entrySet().iterator();
141                while (itEntries.hasNext()) {
142                    Entry<String, Object> entry = itEntries.next();
143                    if (!CmsDataTypeUtil.isParseable(entry.getValue().getClass())) {
144                        String key = entry.getKey().toString();
145                        if (!entry.getValue().getClass().equals(String.class)) {
146                            key += "@" + entry.getValue().getClass().getName();
147                        }
148                        if (m_addInfoReadOnly.containsKey(key)) {
149                            readOnly.put(entry.getKey(), entry.getValue());
150                        }
151                    }
152                }
153                m_user.setAdditionalInfo(readOnly);
154                itEntries = m_addInfoEditable.entrySet().iterator();
155                while (itEntries.hasNext()) {
156                    Entry<String, Object> entry = itEntries.next();
157                    String key = entry.getKey();
158                    int pos = key.indexOf("@");
159                    if (pos < 0) {
160                        m_user.setAdditionalInfo(key, entry.getValue());
161                        continue;
162                    }
163                    String className = key.substring(pos + 1);
164                    key = key.substring(0, pos);
165                    Class<?> clazz;
166                    try {
167                        // try the class name
168                        clazz = Class.forName(className);
169                    } catch (Throwable e) {
170                        try {
171                            // try the class in the java.lang package
172                            clazz = Class.forName(Integer.class.getPackage().getName() + "." + className);
173                        } catch (Throwable e1) {
174                            clazz = String.class;
175                        }
176                    }
177                    m_user.setAdditionalInfo(key, CmsDataTypeUtil.parse((String)entry.getValue(), clazz));
178                }
179            }
180
181            // write the edited user
182            getCms().writeUser(m_user);
183        } catch (Throwable t) {
184            errors.add(t);
185        }
186
187        if (errors.isEmpty()) {
188            if (getCurrentToolPath().endsWith("/orgunit/users/edit/addinfo/all")) {
189                // set closelink
190                Map<String, String[]> argMap = new HashMap<String, String[]>();
191                argMap.put(A_CmsEditUserDialog.PARAM_USERID, new String[] {m_user.getId().toString()});
192                argMap.put("oufqn", new String[] {m_user.getOuFqn()});
193                setParamCloseLink(
194                    CmsToolManager.linkForToolPath(
195                        getJsp(),
196                        getCurrentToolPath().substring(
197                            0,
198                            getCurrentToolPath().indexOf("/orgunit/users/edit/addinfo/all")) + "/orgunit/users/edit/",
199                        argMap));
200            }
201        }
202
203        // set the list of errors to display when saving failed
204        setCommitErrors(errors);
205    }
206
207    /**
208     * Returns the additional info map.<p>
209     *
210     * @return the additional info map
211     */
212    public SortedMap<String, Object> getInfo() {
213
214        return m_addInfoEditable;
215    }
216
217    /**
218     * Returns the edit all flag parameter value.<p>
219     *
220     * @return the edit all flag parameter value
221     */
222    public String getParamEditall() {
223
224        CmsWorkplaceUserInfoManager manager = OpenCms.getWorkplaceManager().getUserInfoManager();
225        if ((manager == null) || (manager.getBlocks() == null) || manager.getBlocks().isEmpty()) {
226            // if the configuration is empty
227            return Boolean.TRUE.toString();
228        }
229        return m_paramEditall;
230    }
231
232    /**
233     * Returns the user id parameter value.<p>
234     *
235     * @return the user id parameter value
236     */
237    public String getParamUserid() {
238
239        return m_paramUserid;
240    }
241
242    /**
243     * Returns the read only add info.<p>
244     *
245     * @return the read only add info
246     */
247    public SortedMap<String, Object> getReadonly() {
248
249        return m_addInfoReadOnly;
250    }
251
252    /**
253     * Sets the modified additional information.<p>
254     *
255     * @param addInfo the additional information to set
256     */
257    public void setInfo(SortedMap<String, Object> addInfo) {
258
259        m_addInfoEditable = new TreeMap<String, Object>(addInfo);
260    }
261
262    /**
263     * Sets the edit all flag parameter value.<p>
264     *
265     * @param editAll the edit all flag parameter value
266     */
267    public void setParamEditall(String editAll) {
268
269        m_paramEditall = editAll;
270    }
271
272    /**
273     * Sets the user id parameter value.<p>
274     *
275     * @param userId the user id parameter value to set
276     */
277    public void setParamUserid(String userId) {
278
279        m_paramUserid = userId;
280    }
281
282    /**
283     * Sets the read only add info.<p>
284     *
285     * @param addInfoReadOnly the read only add info to set
286     */
287    public void setReadonly(SortedMap<String, Object> addInfoReadOnly) {
288
289        m_addInfoReadOnly = addInfoReadOnly;
290    }
291
292    /**
293     * Creates the dialog HTML for all defined widgets of the named dialog (page).<p>
294     *
295     * This overwrites the method from the super class to create a layout variation for the widgets.<p>
296     *
297     * @param dialog the dialog (page) to get the HTML for
298     *
299     * @return the dialog HTML for all defined widgets of the named dialog (page)
300     */
301    @Override
302    protected String createDialogHtml(String dialog) {
303
304        StringBuffer result = new StringBuffer(1024);
305
306        result.append(createWidgetTableStart());
307        // show error header once if there were validation errors
308        result.append(createWidgetErrorHeader());
309
310        if (dialog.equals(PAGES[0])) {
311            if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
312                int pos = 0;
313                Iterator<CmsWorkplaceUserInfoBlock> it = OpenCms.getWorkplaceManager().getUserInfoManager().getBlocks().iterator();
314                while (it.hasNext()) {
315                    CmsWorkplaceUserInfoBlock block = it.next();
316
317                    result.append(dialogBlockStart(key(block.getTitle())));
318                    result.append(createWidgetTableStart());
319                    result.append(createDialogRowsHtml(pos, (pos - 1) + block.getEntries().size()));
320                    result.append(createWidgetTableEnd());
321                    result.append(dialogBlockEnd());
322                    pos += block.getEntries().size();
323                }
324            } else {
325                result.append(createWidgetBlockStart(key(Messages.GUI_USER_EDITOR_LABEL_ADDITIONALINFO_BLOCK_0)));
326                result.append(createDialogRowsHtml(0, 0));
327                result.append(createWidgetBlockEnd());
328                result.append(createWidgetBlockStart(key(Messages.GUI_USER_EDITOR_LABEL_READONLY_BLOCK_0)));
329                result.append(createDialogRowsHtml(1, 1));
330                result.append(createWidgetBlockEnd());
331            }
332        }
333        result.append(createWidgetTableEnd());
334        return result.toString();
335    }
336
337    /**
338     * @see org.opencms.workplace.tools.accounts.A_CmsEditUserDialog#defineWidgets()
339     */
340    @Override
341    protected void defineWidgets() {
342
343        // initialize the user object to use for the dialog
344        initUserObject();
345
346        setKeyPrefix(KEY_PREFIX);
347
348        int count = 0;
349        if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
350            // widgets to display
351            Iterator<CmsWorkplaceUserInfoBlock> itBlocks = OpenCms.getWorkplaceManager().getUserInfoManager().getBlocks().iterator();
352            while (itBlocks.hasNext()) {
353                CmsWorkplaceUserInfoBlock block = itBlocks.next();
354
355                Iterator<CmsWorkplaceUserInfoEntry> itEntries = block.getEntries().iterator();
356                while (itEntries.hasNext()) {
357                    CmsWorkplaceUserInfoEntry entry = itEntries.next();
358
359                    int min = entry.isOptional() ? 0 : 1;
360                    I_CmsWidget widget = entry.getWidgetObject();
361                    addWidget(
362                        new CmsWidgetDialogParameter(
363                            m_addInfoList.get(count),
364                            "value",
365                            entry.getKey(),
366                            "",
367                            PAGES[0],
368                            widget,
369                            min,
370                            1));
371                    count++;
372                }
373            }
374        } else {
375            addWidget(new CmsWidgetDialogParameter(this, "info", PAGES[0], new CmsInputWidget()));
376            addWidget(new CmsWidgetDialogParameter(this, "readonly", PAGES[0], new CmsDisplayWidget()));
377        }
378    }
379
380    /**
381     * @see org.opencms.workplace.CmsWidgetDialog#getPageArray()
382     */
383    @Override
384    protected String[] getPageArray() {
385
386        return PAGES;
387    }
388
389    /**
390     * @see org.opencms.workplace.CmsWorkplace#initMessages()
391     */
392    @Override
393    protected void initMessages() {
394
395        // add specific dialog resource bundle
396        addMessages(Messages.get().getBundleName());
397        // add default resource bundles
398        super.initMessages();
399    }
400
401    /**
402     * Initializes the additional info bean to work with, depending on the dialog state and request parameters.<p>
403     */
404    @SuppressWarnings("unchecked")
405    protected void initUserObject() {
406
407        try {
408            if (CmsStringUtil.isEmpty(getParamAction()) || CmsDialog.DIALOG_INITIAL.equals(getParamAction())) {
409                // edit an existing user, get the user object from db
410                m_user = getCms().readUser(new CmsUUID(getParamUserid()));
411                if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
412                    m_addInfoList = createAddInfoList(m_user);
413                } else {
414                    setAddInfoMaps();
415                }
416                return;
417            } else {
418                // this is not the initial call, get the user object from session
419                m_user = getCms().readUser(new CmsUUID(getParamUserid()));
420                if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
421                    m_addInfoList = (List<CmsUserAddInfoBean>)getDialogObject();
422                } else {
423                    Map<String, SortedMap<String, Object>> dObj = (Map<String, SortedMap<String, Object>>)getDialogObject();
424                    m_addInfoEditable = dObj.get("editable");
425                    m_addInfoReadOnly = dObj.get("readonly");
426                }
427                return;
428            }
429        } catch (Exception e) {
430            // noop
431        }
432        // create a new user object
433        try {
434            m_user = getCms().readUser(new CmsUUID(getParamUserid()));
435        } catch (CmsException e) {
436            // ignore
437        }
438        if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
439            m_addInfoList = createAddInfoList(m_user);
440        } else {
441            setAddInfoMaps();
442        }
443    }
444
445    /**
446     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
447     */
448    @Override
449    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
450
451        // initialize parameters and dialog actions in super implementation
452        super.initWorkplaceRequestValues(settings, request);
453
454        // save the current state (may be changed because of the widget values)
455        if (!Boolean.valueOf(getParamEditall()).booleanValue()) {
456            setDialogObject(m_addInfoList);
457        } else {
458            Map<String, SortedMap<String, Object>> dObj = new HashMap<String, SortedMap<String, Object>>();
459            dObj.put("editable", m_addInfoEditable);
460            dObj.put("readonly", m_addInfoReadOnly);
461            setDialogObject(dObj);
462        }
463    }
464
465    /**
466     * @see org.opencms.workplace.CmsWidgetDialog#validateParamaters()
467     */
468    @Override
469    protected void validateParamaters() throws Exception {
470
471        // test the needed parameters
472        String ou = getCms().readUser(new CmsUUID(getParamUserid())).getOuFqn();
473        OpenCms.getRoleManager().checkRole(getCms(), CmsRole.ACCOUNT_MANAGER.forOrgUnit(ou));
474    }
475
476    /**
477     * Creates a new additional information bean object.<p>
478     *
479     * @param user the user to create the bean for
480     *
481     * @return a new additional information bean object
482     */
483    private List<CmsUserAddInfoBean> createAddInfoList(CmsUser user) {
484
485        List<CmsUserAddInfoBean> addInfoList = new ArrayList<CmsUserAddInfoBean>();
486        // add beans
487        Iterator<CmsWorkplaceUserInfoBlock> itBlocks = OpenCms.getWorkplaceManager().getUserInfoManager().getBlocks().iterator();
488        while (itBlocks.hasNext()) {
489            CmsWorkplaceUserInfoBlock block = itBlocks.next();
490            Iterator<CmsWorkplaceUserInfoEntry> itEntries = block.getEntries().iterator();
491            while (itEntries.hasNext()) {
492                CmsWorkplaceUserInfoEntry entry = itEntries.next();
493                Object value = user.getAdditionalInfo(entry.getKey());
494                if (value == null) {
495                    value = "";
496                }
497                addInfoList.add(new CmsUserAddInfoBean(entry.getKey(), value.toString(), entry.getClassType()));
498            }
499        }
500        return addInfoList;
501    }
502
503    /**
504     * Builds the additional info maps.<p>
505     */
506    private void setAddInfoMaps() {
507
508        m_addInfoEditable = new TreeMap<String, Object>();
509        m_addInfoReadOnly = new TreeMap<String, Object>();
510        Iterator<Entry<String, Object>> itEntries = m_user.getAdditionalInfo().entrySet().iterator();
511        while (itEntries.hasNext()) {
512            Entry<String, Object> entry = itEntries.next();
513            String key = entry.getKey().toString();
514            if ((entry.getValue() == null) || CmsStringUtil.isEmptyOrWhitespaceOnly(entry.getValue().toString())) {
515                // skip empty entries
516                continue;
517            }
518            if (!entry.getValue().getClass().equals(String.class)) {
519                // only show type different to string
520                key += "@" + entry.getValue().getClass().getName();
521            }
522            if (CmsDataTypeUtil.isParseable(entry.getValue().getClass())) {
523                m_addInfoEditable.put(key, entry.getValue());
524            } else {
525                String value = entry.getValue().toString();
526                if (value.length() > (75 - key.length())) {
527                    if ((75 - key.length()) > 5) {
528                        value = value.substring(0, (75 - key.length())) + " ...";
529                    } else {
530                        value = "...";
531                    }
532                }
533                m_addInfoReadOnly.put(key, value);
534            }
535        }
536    }
537}