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.projects;
029
030import org.opencms.file.CmsGroup;
031import org.opencms.file.CmsProject;
032import org.opencms.jsp.CmsJspActionElement;
033import org.opencms.main.CmsException;
034import org.opencms.main.CmsIllegalArgumentException;
035import org.opencms.main.OpenCms;
036import org.opencms.security.CmsOrganizationalUnit;
037import org.opencms.security.CmsRole;
038import org.opencms.util.CmsFileUtil;
039import org.opencms.util.CmsStringUtil;
040import org.opencms.util.CmsUUID;
041import org.opencms.widgets.CmsCheckboxWidget;
042import org.opencms.widgets.CmsDisplayWidget;
043import org.opencms.widgets.CmsGroupWidget;
044import org.opencms.widgets.CmsInputWidget;
045import org.opencms.widgets.CmsOrgUnitWidget;
046import org.opencms.widgets.CmsTextareaWidget;
047import org.opencms.widgets.CmsVfsFileWidget;
048import org.opencms.workplace.CmsDialog;
049import org.opencms.workplace.CmsWidgetDialog;
050import org.opencms.workplace.CmsWidgetDialogParameter;
051import org.opencms.workplace.CmsWorkplaceSettings;
052
053import java.util.ArrayList;
054import java.util.HashMap;
055import java.util.Iterator;
056import java.util.List;
057import java.util.Map;
058
059import javax.servlet.http.HttpServletRequest;
060import javax.servlet.http.HttpServletResponse;
061import javax.servlet.jsp.PageContext;
062
063/**
064 * Dialog to edit new and existing project in the administration view.<p>
065 *
066 * @since 6.0.0
067 */
068public class CmsEditProjectDialog extends CmsWidgetDialog {
069
070    /** localized messages Keys prefix. */
071    public static final String KEY_PREFIX = "project";
072
073    /** Defines which pages are valid for this dialog. */
074    public static final String[] PAGES = {"page1"};
075
076    /** Request parameter name for the project id. */
077    public static final String PARAM_PROJECTID = "projectid";
078
079    /** Request parameter name for the project name. */
080    public static final String PARAM_PROJECTNAME = "projectname";
081
082    /** The project object that is edited on this dialog. */
083    protected CmsProject m_project;
084
085    /** Stores the value of the request parameter for the project id. */
086    private String m_paramProjectid;
087
088    /** Auxiliary Property for better representation of the bean VFS resources. */
089    private List m_resources;
090
091    /**
092     * Public constructor with JSP action element.<p>
093     *
094     * @param jsp an initialized JSP action element
095     */
096    public CmsEditProjectDialog(CmsJspActionElement jsp) {
097
098        super(jsp);
099    }
100
101    /**
102     * Public constructor with JSP variables.<p>
103     *
104     * @param context the JSP page context
105     * @param req the JSP request
106     * @param res the JSP response
107     */
108    public CmsEditProjectDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
109
110        this(new CmsJspActionElement(context, req, res));
111    }
112
113    /**
114     * Commits the edited project to the database.<p>
115     */
116    @Override
117    public void actionCommit() {
118
119        List errors = new ArrayList();
120
121        try {
122            // if new create it first
123            if (m_project.getUuid() == null) {
124                CmsProject newProject = getCms().createProject(
125                    m_project.getName(),
126                    m_project.getDescription(),
127                    getUserGroup(),
128                    getManagerGroup(),
129                    m_project.getType());
130                m_project = newProject;
131            } else {
132                getCms().writeProject(m_project);
133            }
134            // write the edited project resources
135            CmsProject currentProject = getCms().getRequestContext().getCurrentProject();
136            // change the current project
137            getCms().getRequestContext().setCurrentProject(m_project);
138            // store the current site root
139            String currentSite = getCms().getRequestContext().getSiteRoot();
140            // copy the resources to the current project
141            try {
142                // switch to the root site
143                getCms().getRequestContext().setSiteRoot("");
144
145                // remove deleted resources
146                Iterator itDel = getCms().readProjectResources(m_project).iterator();
147                while (itDel.hasNext()) {
148                    String resName = itDel.next().toString();
149                    if (!getResources().contains(resName)) {
150                        getCms().removeResourceFromProject(resName);
151                    }
152                }
153                // read project resources again!
154                List currentResNames = getCms().readProjectResources(m_project);
155                // copy missing resources
156                Iterator itAdd = getResources().iterator();
157                while (itAdd.hasNext()) {
158                    String resName = itAdd.next().toString();
159                    if (!currentResNames.contains(resName)) {
160                        getCms().copyResourceToProject(resName);
161                    }
162                }
163            } finally {
164                // switch back to current site and project
165                getCms().getRequestContext().setSiteRoot(currentSite);
166                getCms().getRequestContext().setCurrentProject(currentProject);
167            }
168            // refresh the list
169            Map objects = (Map)getSettings().getListObject();
170            if (objects != null) {
171                objects.remove(CmsProjectsList.class.getName());
172            }
173        } catch (Throwable t) {
174            errors.add(t);
175        }
176        // set the list of errors to display when saving failed
177        setCommitErrors(errors);
178    }
179
180    /**
181     * Returns the description of the parent ou.<p>
182     *
183     * @return the description of the parent ou
184     */
185    public String getAssignedOu() {
186
187        try {
188            CmsOrganizationalUnit ou;
189            if (!isNewProject()) {
190                ou = OpenCms.getOrgUnitManager().readOrganizationalUnit(getCms(), m_project.getOuFqn());
191            } else {
192                ou = OpenCms.getRoleManager().getOrgUnitsForRole(getCms(), CmsRole.PROJECT_MANAGER, true).get(0);
193            }
194            return ou.getDisplayName(getLocale());
195        } catch (CmsException e) {
196            return null;
197        }
198    }
199
200    /**
201     * Returns the manager Group name.<p>
202     *
203     * @return the manager Group name
204     */
205    public String getManagerGroup() {
206
207        try {
208            return getCms().readGroup(m_project.getManagerGroupId()).getName();
209        } catch (Throwable e) {
210            return "";
211        }
212    }
213
214    /**
215     * Returns the simple name of the project.<p>
216     *
217     * @return the simple name of the project
218     */
219    public String getName() {
220
221        String name = m_project.getSimpleName();
222        if (CmsStringUtil.isEmptyOrWhitespaceOnly(name) || name.equals("/")) {
223            name = "";
224        }
225        return name;
226    }
227
228    /**
229     * Returns the fully qualified name of the organizational unit.<p>
230     *
231     * @return the fully qualified name of the organizational unit
232     */
233    public String getOufqn() {
234
235        return m_project.getOuFqn();
236    }
237
238    /**
239     * Returns the project id parameter value.<p>
240     *
241     * @return the project id parameter value
242     */
243    public String getParamProjectid() {
244
245        return m_paramProjectid;
246    }
247
248    /**
249     * Returns the list of VFS resources that belong to this project.<p>
250     *
251     * @return the list of VFS resources that belong to this project
252     */
253    public List getResources() {
254
255        if (m_resources == null) {
256            return new ArrayList();
257        }
258        return m_resources;
259    }
260
261    /**
262     * Returns the user Group name.<p>
263     *
264     * @return the user Group name
265     */
266    public String getUserGroup() {
267
268        try {
269            return getCms().readGroup(m_project.getGroupId()).getName();
270        } catch (Throwable e) {
271            return "";
272        }
273    }
274
275    /**
276     * Just a setter method needed for the widget dialog.<p>
277     *
278     * @param ou ignored
279     */
280    public void setAssignedOu(String ou) {
281
282        ou.length(); // prevent warning
283    }
284
285    /**
286     * Sets the manager Group name.<p>
287     *
288     * @param managerGroup the manager Group name to set
289     */
290    public void setManagerGroup(String managerGroup) {
291
292        CmsGroup group = checkGroup(managerGroup);
293        if (group != null) {
294            m_project.setManagerGroupId(group.getId());
295        }
296    }
297
298    /**
299     * Sets the name of the project.<p>
300     *
301     * @param name the name to set
302     */
303    public void setName(String name) {
304
305        String oufqn = getOufqn();
306        if (oufqn != null) {
307            if (!oufqn.endsWith("/")) {
308                oufqn += "/";
309            }
310        } else {
311            oufqn = "/";
312        }
313        m_project.setName(oufqn + name);
314
315    }
316
317    /**
318     * Sets the fully qualified name of the organizational unit.<p>
319     *
320     * @param oufqn the fully qualified name of the organizational unit to set
321     */
322    public void setOufqn(String oufqn) {
323
324        if (oufqn != null) {
325            if (!oufqn.endsWith("/")) {
326                oufqn += '/';
327            }
328        } else {
329            oufqn = "/";
330        }
331        String name = m_project.getSimpleName();
332        if (name == null) {
333            name = "";
334        }
335        name = oufqn + name;
336        if (CmsStringUtil.isEmptyOrWhitespaceOnly(name)) {
337            name = "/";
338        }
339        m_project.setName(name);
340    }
341
342    /**
343     * Sets the project id parameter value.<p>
344     *
345     * @param projectId the project id parameter value
346     */
347    public void setParamProjectid(String projectId) {
348
349        m_paramProjectid = projectId;
350    }
351
352    /**
353     * Sets the resources of this project.<p>
354     *
355     * @param value the project resources to set
356     */
357    public void setResources(List value) {
358
359        if (value == null) {
360            m_resources = new ArrayList();
361            return;
362        }
363        m_resources = CmsFileUtil.removeRedundancies(value);
364    }
365
366    /**
367     * Sets the user Group name.<p>
368     *
369     * @param userGroup the user Group name to set
370     */
371    public void setUserGroup(String userGroup) {
372
373        CmsGroup group = checkGroup(userGroup);
374        if (group != null) {
375            m_project.setGroupId(group.getId());
376        }
377    }
378
379    /**
380     * @see org.opencms.workplace.CmsWidgetDialog#createDialogHtml(java.lang.String)
381     */
382    @Override
383    protected String createDialogHtml(String dialog) {
384
385        StringBuffer result = new StringBuffer(1024);
386
387        result.append(createWidgetTableStart());
388        // show error header once if there were validation errors
389        result.append(createWidgetErrorHeader());
390
391        if (dialog.equals(PAGES[0])) {
392            // create the widgets for the first dialog page
393            result.append(dialogBlockStart(key(Messages.GUI_PROJECT_EDITOR_LABEL_IDENTIFICATION_BLOCK_0)));
394            result.append(createWidgetTableStart());
395            result.append(createDialogRowsHtml(0, 5));
396            result.append(createWidgetTableEnd());
397            result.append(dialogBlockEnd());
398            result.append(dialogBlockStart(key(Messages.GUI_PROJECT_EDITOR_LABEL_CONTENT_BLOCK_0)));
399            result.append(createWidgetTableStart());
400            result.append(createDialogRowsHtml(6, 6));
401            result.append(createWidgetTableEnd());
402            result.append(dialogBlockEnd());
403        }
404
405        result.append(createWidgetTableEnd());
406        return result.toString();
407    }
408
409    /**
410     * Creates the list of widgets for this dialog.<p>
411     */
412    @Override
413    protected void defineWidgets() {
414
415        // initialize the project object to use for the dialog
416        initProjectObject();
417
418        setKeyPrefix(KEY_PREFIX);
419
420        // widgets to display
421        if (isNewProject()) {
422            addWidget(new CmsWidgetDialogParameter(this, "name", PAGES[0], new CmsInputWidget()));
423        } else {
424            addWidget(new CmsWidgetDialogParameter(this, "name", PAGES[0], new CmsDisplayWidget()));
425        }
426        addWidget(new CmsWidgetDialogParameter(m_project, "description", "", PAGES[0], new CmsTextareaWidget(), 0, 1));
427        addWidget(new CmsWidgetDialogParameter(this, "managerGroup", PAGES[0], new CmsGroupWidget(null, null)));
428        addWidget(new CmsWidgetDialogParameter(this, "userGroup", PAGES[0], new CmsGroupWidget(null, null)));
429        if (isNewProject()) {
430            int ous = 1;
431            try {
432                ous = OpenCms.getRoleManager().getOrgUnitsForRole(getCms(), CmsRole.PROJECT_MANAGER, true).size();
433            } catch (CmsException e) {
434                // should never happen
435            }
436            if (ous < 2) {
437                addWidget(new CmsWidgetDialogParameter(this, "assignedOu", PAGES[0], new CmsDisplayWidget()));
438            } else {
439                addWidget(
440                    new CmsWidgetDialogParameter(
441                        this,
442                        "oufqn",
443                        PAGES[0],
444                        new CmsOrgUnitWidget(CmsRole.PROJECT_MANAGER)));
445            }
446        } else {
447            addWidget(new CmsWidgetDialogParameter(this, "assignedOu", PAGES[0], new CmsDisplayWidget()));
448        }
449        addWidget(new CmsWidgetDialogParameter(m_project, "deleteAfterPublishing", PAGES[0], new CmsCheckboxWidget()));
450        addWidget(
451            new CmsWidgetDialogParameter(this, "resources", PAGES[0], new CmsVfsFileWidget(false, "", false, false)));
452    }
453
454    /**
455     * @see org.opencms.workplace.CmsWidgetDialog#getPageArray()
456     */
457    @Override
458    protected String[] getPageArray() {
459
460        return PAGES;
461    }
462
463    /**
464     * @see org.opencms.workplace.CmsWorkplace#initMessages()
465     */
466    @Override
467    protected void initMessages() {
468
469        // add specific dialog resource bundle
470        addMessages(Messages.get().getBundleName());
471        // add default resource bundles
472        super.initMessages();
473    }
474
475    /**
476     * Initializes the project object to work with depending on the dialog state and request parameters.<p>
477     *
478     * Two initializations of the project object on first dialog call are possible:
479     * <ul>
480     * <li>edit an existing project</li>
481     * <li>create a new project</li>
482     * </ul>
483     */
484    protected void initProjectObject() {
485
486        Object o = null;
487
488        try {
489            if (CmsStringUtil.isEmpty(getParamAction()) || CmsDialog.DIALOG_INITIAL.equals(getParamAction())) {
490                // edit an existing project, get the project object from database
491                m_project = getCms().readProject(new CmsUUID(getParamProjectid()));
492                m_resources = getCms().readProjectResources(m_project);
493            } else {
494                // this is not the initial call, get the project object from session
495                o = getDialogObject();
496                Map map = (Map)o;
497                m_project = (CmsProject)map.get("prj");
498                // test
499                m_project.getUuid();
500                m_resources = (List)map.get("res");
501                m_resources.isEmpty();
502            }
503        } catch (Exception e) {
504            // create a new project object
505            m_project = new CmsProject();
506            m_resources = new ArrayList();
507            setOufqn(getCms().getRequestContext().getOuFqn());
508            setUserGroup(getCms().getRequestContext().getOuFqn() + OpenCms.getDefaultUsers().getGroupUsers());
509        }
510    }
511
512    /**
513     * Overridden to set a custom online help mapping.<p>
514     *
515     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceMembers(org.opencms.jsp.CmsJspActionElement)
516     */
517    @Override
518    protected void initWorkplaceMembers(CmsJspActionElement jsp) {
519
520        super.initWorkplaceMembers(jsp);
521        setOnlineHelpUriCustom("/projects/project_edit.jsp");
522    }
523
524    /**
525     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
526     */
527    @Override
528    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
529
530        // initialize parameters and dialog actions in super implementation
531        super.initWorkplaceRequestValues(settings, request);
532
533        Map map = new HashMap();
534        map.put("prj", m_project);
535        map.put("res", m_resources);
536        // save the current state of the project (may be changed because of the widget values)
537        setDialogObject(map);
538    }
539
540    /**
541     * Checks if the Project overview has to be displayed.<p>
542     *
543     * @return <code>true</code> if the project overview has to be displayed
544     */
545    protected boolean isNewProject() {
546
547        return getCurrentToolPath().equals("/projects/new");
548    }
549
550    /**
551     * @see org.opencms.workplace.CmsWidgetDialog#validateParamaters()
552     */
553    @Override
554    protected void validateParamaters() throws Exception {
555
556        if (!isNewProject()) {
557            // test the needed parameters
558            getCms().readProject(new CmsUUID(getParamProjectid())).getName();
559        }
560
561    }
562
563    /**
564     * Checks if the given group name is a valid opencms user group.<p>
565     *
566     * @param groupName the group name to check
567     *
568     * @return the read group
569     */
570    private CmsGroup checkGroup(String groupName) {
571
572        try {
573            return getCms().readGroup(groupName);
574        } catch (CmsException e) {
575            throw new CmsIllegalArgumentException(e.getMessageContainer());
576        }
577    }
578}