KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > workplace > editors > CmsXmlContentEditor


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/workplace/editors/CmsXmlContentEditor.java,v $
3  * Date : $Date: 2006/11/21 09:25:00 $
4  * Version: $Revision: 1.71 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.workplace.editors;
33
34 import org.opencms.file.CmsFile;
35 import org.opencms.file.CmsRequestContext;
36 import org.opencms.file.CmsResource;
37 import org.opencms.file.CmsResourceFilter;
38 import org.opencms.file.collectors.I_CmsResourceCollector;
39 import org.opencms.i18n.CmsEncoder;
40 import org.opencms.i18n.CmsLocaleManager;
41 import org.opencms.jsp.CmsJspActionElement;
42 import org.opencms.lock.CmsLock;
43 import org.opencms.main.CmsException;
44 import org.opencms.main.CmsLog;
45 import org.opencms.main.OpenCms;
46 import org.opencms.util.CmsRequestUtil;
47 import org.opencms.util.CmsStringUtil;
48 import org.opencms.widgets.A_CmsWidget;
49 import org.opencms.widgets.I_CmsWidget;
50 import org.opencms.widgets.I_CmsWidgetDialog;
51 import org.opencms.widgets.I_CmsWidgetParameter;
52 import org.opencms.workplace.CmsWorkplaceSettings;
53 import org.opencms.workplace.editors.directedit.CmsDirectEditButtonSelection;
54 import org.opencms.xml.CmsXmlContentDefinition;
55 import org.opencms.xml.CmsXmlException;
56 import org.opencms.xml.CmsXmlUtils;
57 import org.opencms.xml.content.CmsXmlContent;
58 import org.opencms.xml.content.CmsXmlContentErrorHandler;
59 import org.opencms.xml.content.CmsXmlContentFactory;
60 import org.opencms.xml.content.CmsXmlContentValueSequence;
61 import org.opencms.xml.types.CmsXmlNestedContentDefinition;
62 import org.opencms.xml.types.I_CmsXmlContentValue;
63 import org.opencms.xml.types.I_CmsXmlSchemaType;
64
65 import java.io.IOException JavaDoc;
66 import java.io.UnsupportedEncodingException JavaDoc;
67 import java.util.ArrayList JavaDoc;
68 import java.util.HashSet JavaDoc;
69 import java.util.Iterator JavaDoc;
70 import java.util.List JavaDoc;
71 import java.util.Locale JavaDoc;
72 import java.util.Set JavaDoc;
73
74 import javax.servlet.ServletException JavaDoc;
75 import javax.servlet.http.HttpServletRequest JavaDoc;
76 import javax.servlet.jsp.JspException JavaDoc;
77
78 import org.apache.commons.logging.Log;
79
80 /**
81  * Creates the editor for XML content definitions.<p>
82  *
83  * @author Alexander Kandzior
84  * @author Andreas Zahner
85  *
86  * @version $Revision: 1.71 $
87  *
88  * @since 6.0.0
89  */

90 public class CmsXmlContentEditor extends CmsEditor implements I_CmsWidgetDialog {
91
92     /** Action for checking content before executing the direct edit action. */
93     public static final int ACTION_CHECK = 151;
94
95     /** Action for optional element creation. */
96     public static final int ACTION_ELEMENT_ADD = 152;
97
98     /** Action for element move down operation. */
99     public static final int ACTION_ELEMENT_MOVE_DOWN = 154;
100
101     /** Action for element move up operation. */
102     public static final int ACTION_ELEMENT_MOVE_UP = 153;
103
104     /** Action for optional element removal. */
105     public static final int ACTION_ELEMENT_REMOVE = 155;
106
107     /** Action for new file creation. */
108     public static final int ACTION_NEW = 156;
109
110     /** Indicates that the content should be checked before executing the direct edit action. */
111     public static final String JavaDoc EDITOR_ACTION_CHECK = "check";
112
113     /** Indicates an optional element should be created. */
114     public static final String JavaDoc EDITOR_ACTION_ELEMENT_ADD = "addelement";
115
116     /** Indicates an element should be moved down. */
117     public static final String JavaDoc EDITOR_ACTION_ELEMENT_MOVE_DOWN = "elementdown";
118
119     /** Indicates an element should be moved up. */
120     public static final String JavaDoc EDITOR_ACTION_ELEMENT_MOVE_UP = "elementup";
121
122     /** Indicates an optional element should be removed. */
123     public static final String JavaDoc EDITOR_ACTION_ELEMENT_REMOVE = "removeelement";
124
125     /** Indicates a new file should be created. */
126     public static final String JavaDoc EDITOR_ACTION_NEW = CmsDirectEditButtonSelection.VALUE_NEW;
127
128     /** Parameter name for the request parameter "elementindex". */
129     public static final String JavaDoc PARAM_ELEMENTINDEX = "elementindex";
130
131     /** Parameter name for the request parameter "elementname". */
132     public static final String JavaDoc PARAM_ELEMENTNAME = "elementname";
133
134     /** Constant for the editor type, must be the same as the editors subfolder name in the VFS. */
135     private static final String JavaDoc EDITOR_TYPE = "xmlcontent";
136
137     /** The log object for this class. */
138     private static final Log LOG = CmsLog.getLog(CmsXmlContentEditor.class);
139
140     /** The content object to edit. */
141     private CmsXmlContent m_content;
142
143     /** The element locale. */
144     private Locale JavaDoc m_elementLocale;
145
146     /** The error handler for the xml content. */
147     private CmsXmlContentErrorHandler m_errorHandler;
148
149     /** File object used to read and write contents. */
150     private CmsFile m_file;
151
152     /** The set of help message ids that have already been used. */
153     private Set JavaDoc m_helpMessageIds;
154
155     /** Indicates if an optional element is included in the form. */
156     private boolean m_optionalElementPresent;
157
158     /** Parameter stores the index of the element to add or remove. */
159     private String JavaDoc m_paramElementIndex;
160
161     /** Parameter stores the name of the element to add or remove. */
162     private String JavaDoc m_paramElementName;
163
164     /** Parameter to indicate if a new XML content resource should be created. */
165     private String JavaDoc m_paramNewLink;
166
167     /** Visitor implementation that stored the widgets for the content. */
168     private CmsXmlContentWidgetVisitor m_widgetCollector;
169
170     /**
171      * Public constructor.<p>
172      *
173      * @param jsp an initialized JSP action element
174      */

175     public CmsXmlContentEditor(CmsJspActionElement jsp) {
176
177         super(jsp);
178     }
179
180     /**
181      * Performs the change element language action of the editor.<p>
182      */

183     public void actionChangeElementLanguage() {
184
185         // save eventually changed content of the editor
186
Locale JavaDoc oldLocale = CmsLocaleManager.getLocale(getParamOldelementlanguage());
187         try {
188             setEditorValues(oldLocale);
189             if (!getErrorHandler().hasErrors()) {
190                 // no errors found in content
191
if (!m_content.hasLocale(getElementLocale())) {
192                     // create new element if selected language element is not present
193
try {
194                         m_content.addLocale(getCms(), getElementLocale());
195                     } catch (CmsXmlException e) {
196                         if (LOG.isErrorEnabled()) {
197                             LOG.error(e.getLocalizedMessage(), e);
198                         }
199                     }
200                 }
201                 // save to temporary file
202
writeContent();
203                 // set default action to suppress error messages
204
setAction(ACTION_DEFAULT);
205             } else {
206                 // errors found, switch back to old language to show errors
207
setParamElementlanguage(getParamOldelementlanguage());
208                 // set stored locale to null to reinitialize it
209
m_elementLocale = null;
210             }
211         } catch (Exception JavaDoc e) {
212             // should usually never happen
213
if (LOG.isInfoEnabled()) {
214                 LOG.info(e.getLocalizedMessage(), e);
215             }
216         }
217     }
218
219     /**
220      * Deletes the temporary file and unlocks the edited resource when in direct edit mode.<p>
221      *
222      * @param forceUnlock if true, the resource will be unlocked anyway
223      */

224     public void actionClear(boolean forceUnlock) {
225
226         // delete the temporary file
227
deleteTempFile();
228         boolean directEditMode = Boolean.valueOf(getParamDirectedit()).booleanValue();
229         boolean modified = Boolean.valueOf(getParamModified()).booleanValue();
230         if (directEditMode || forceUnlock || !modified) {
231             // unlock the resource when in direct edit mode, force unlock is true or resource was not modified
232
try {
233                 getCms().unlockResource(getParamResource());
234             } catch (CmsException e) {
235                 // should usually never happen
236
if (LOG.isInfoEnabled()) {
237                     LOG.info(e.getLocalizedMessage(), e);
238                 }
239             }
240         }
241     }
242
243     /**
244      * Performs the delete locale action.<p>
245      *
246      * @throws JspException if something goes wrong
247      */

248     public void actionDeleteElementLocale() throws JspException JavaDoc {
249
250         try {
251             Locale JavaDoc loc = getElementLocale();
252             m_content.removeLocale(loc);
253             //write the modified xml content
254
writeContent();
255             List JavaDoc locales = m_content.getLocales();
256             if (locales.size() > 0) {
257                 // set first locale as new display locale
258
Locale JavaDoc newLoc = (Locale JavaDoc)locales.get(0);
259                 setParamElementlanguage(newLoc.toString());
260                 m_elementLocale = newLoc;
261             } else {
262                 if (LOG.isErrorEnabled()) {
263                     LOG.error(Messages.get().getBundle().key(Messages.LOG_GET_LOCALES_1, getParamResource()));
264                 }
265             }
266
267         } catch (CmsXmlException e) {
268             // an error occured while trying to delete the locale, stop action
269
showErrorPage(e);
270         } catch (CmsException e) {
271             // should usually never happen
272
if (LOG.isInfoEnabled()) {
273                 LOG.info(e.getLocalizedMessage(), e);
274             }
275         }
276     }
277
278     /**
279      * Performs a configurable action performed by the editor.<p>
280      *
281      * The default action is: save resource, clear temporary files and publish the resource directly.<p>
282      *
283      * @throws IOException if a forward fails
284      * @throws ServletException of a forward fails
285      * @throws JspException if including a JSP fails
286      */

287     public void actionDirectEdit() throws IOException JavaDoc, JspException JavaDoc, ServletException JavaDoc {
288
289         // get the action class from the OpenCms runtime property
290
I_CmsEditorActionHandler actionClass = OpenCms.getWorkplaceManager().getEditorActionHandler();
291         if (actionClass == null) {
292             // error getting the action class, save content and exit the editor
293
actionSave();
294             actionExit();
295         } else {
296             actionClass.editorAction(this, getJsp());
297         }
298     }
299
300     /**
301      * Performs the exit editor action.<p>
302      *
303      * @see org.opencms.workplace.editors.CmsEditor#actionExit()
304      */

305     public void actionExit() throws IOException JavaDoc, JspException JavaDoc, ServletException JavaDoc {
306
307         if (getAction() == ACTION_CANCEL) {
308             // save and exit was cancelled
309
return;
310         }
311         // unlock resource if we are in direct edit mode
312
actionClear(false);
313         // close the editor
314
actionClose();
315     }
316
317     /**
318      * Moves an element in the xml content either up or down.<p>
319      *
320      * Depends on the given action value.<p>
321      *
322      * @throws JspException if including the error page fails
323      */

324     public void actionMoveElement() throws JspException JavaDoc {
325
326         // set editor values from request
327
try {
328             setEditorValues(getElementLocale());
329         } catch (CmsXmlException e) {
330             // an error occured while trying to set the values, stop action
331
showErrorPage(e);
332             return;
333         }
334         // get the necessary parameters to move the element
335
int index = 0;
336         try {
337             index = Integer.parseInt(getParamElementIndex());
338         } catch (Exception JavaDoc e) {
339             // ignore, should not happen
340
}
341
342         // get the value to move
343
I_CmsXmlContentValue value = m_content.getValue(getParamElementName(), getElementLocale(), index);
344
345         if (getAction() == ACTION_ELEMENT_MOVE_DOWN) {
346             // move down the value
347
value.moveDown();
348         } else {
349             // move up the value
350
value.moveUp();
351         }
352
353         if (getErrorHandler().hasWarnings(getElementLocale())) {
354             // there were warnings for the edited content, reset error handler to avoid display issues
355
resetErrorHandler();
356         }
357
358         try {
359             // write the modified content to the temporary file
360
writeContent();
361         } catch (CmsException e) {
362             // an error occured while trying to save
363
showErrorPage(e);
364         }
365     }
366
367     /**
368      * Creates a new XML content item for editing.<p>
369      *
370      * @throws JspException in case something goes wrong
371      */

372     public void actionNew() throws JspException JavaDoc {
373
374         // get the collector used to create the new content
375
int pos = m_paramNewLink.indexOf('|');
376         String JavaDoc collectorName = m_paramNewLink.substring(0, pos);
377         String JavaDoc param = m_paramNewLink.substring(pos + 1);
378
379         // get the collector used for calculating the next file name
380
I_CmsResourceCollector collector = OpenCms.getResourceManager().getContentCollector(collectorName);
381         String JavaDoc newFileName = "";
382         try {
383
384             // one resource serves as a "template" for the new resource
385
CmsFile templateFile = getCms().readFile(getParamResource(), CmsResourceFilter.IGNORE_EXPIRATION);
386             CmsXmlContent template = CmsXmlContentFactory.unmarshal(getCms(), templateFile);
387             Locale JavaDoc locale = (Locale JavaDoc)OpenCms.getLocaleManager().getDefaultLocales(getCms(), getParamResource()).get(0);
388
389             // now create a new XML content based on the templates content definition
390
CmsXmlContent newContent = CmsXmlContentFactory.createDocument(
391                 getCms(),
392                 locale,
393                 template.getEncoding(),
394                 template.getContentDefinition());
395
396             // IMPORTANT: calculation of the name MUST be done here so the file name is ensured to be valid
397
newFileName = collector.getCreateLink(getCms(), collectorName, param);
398
399             // now create the resource, fill it with the marshalled XML and write it back to the VFS
400
getCms().createResource(newFileName, templateFile.getTypeId());
401             // re-read the created resource
402
CmsFile newFile = getCms().readFile(newFileName, CmsResourceFilter.ALL);
403             newFile.setContents(newContent.marshal());
404             // write the file with the updated content
405
getCms().writeFile(newFile);
406
407             // wipe out parameters for the editor to ensure proper operation
408
setParamNewLink(null);
409             setParamAction(null);
410             setParamResource(newFileName);
411             setAction(ACTION_DEFAULT);
412
413             // create the temporary file to work with
414
setParamTempfile(createTempFile());
415
416             // set the member variables for the content
417
m_file = getCms().readFile(getParamTempfile(), CmsResourceFilter.ALL);
418             m_content = newContent;
419
420         } catch (CmsException e) {
421             if (LOG.isErrorEnabled()) {
422                 LOG.error(Messages.get().getBundle().key(Messages.LOG_CREATE_XML_CONTENT_ITEM_1, m_paramNewLink), e);
423             }
424             throw new JspException JavaDoc(e);
425         } finally {
426             try {
427                 // delete the new file
428
getCms().deleteResource(newFileName, CmsResource.DELETE_PRESERVE_SIBLINGS);
429             } catch (CmsException e) {
430                 // ignore
431
}
432         }
433     }
434
435     /**
436      * Performs the preview xml content action in a new browser window.<p>
437      *
438      * @throws IOException if redirect fails
439      * @throws JspException if inclusion of error page fails
440      */

441     public void actionPreview() throws IOException JavaDoc, JspException JavaDoc {
442
443         try {
444             // save content of the editor only to the temporary file
445
setEditorValues(getElementLocale());
446             writeContent();
447             // remove eventual release & expiration date from temporary file to make preview work
448
getCms().setDateReleased(getParamTempfile(), CmsResource.DATE_RELEASED_DEFAULT, false);
449             getCms().setDateExpired(getParamTempfile(), CmsResource.DATE_EXPIRED_DEFAULT, false);
450         } catch (CmsException e) {
451             // show error page
452
showErrorPage(this, e);
453         }
454
455         // get preview uri from content handler
456
String JavaDoc previewUri = m_content.getContentDefinition().getContentHandler().getPreview(
457             getCms(),
458             m_content,
459             getParamTempfile());
460
461         // create locale request parameter
462
StringBuffer JavaDoc param = new StringBuffer JavaDoc(8);
463         if (previewUri.indexOf('?') != -1) {
464             param.append("&");
465         } else {
466             param.append("?");
467         }
468         param.append(CmsLocaleManager.PARAMETER_LOCALE);
469         param.append("=");
470         param.append(getParamElementlanguage());
471
472         // redirect to the temporary file with currently active element language or to the specified preview uri
473
sendCmsRedirect(previewUri + param);
474     }
475
476     /**
477      * Performs the save content action.<p>
478      *
479      * @see org.opencms.workplace.editors.CmsEditor#actionSave()
480      */

481     public void actionSave() throws JspException JavaDoc {
482
483         actionSave(getElementLocale());
484         if (getAction() != ACTION_CANCEL) {
485             // save successful, set save action
486
setAction(ACTION_SAVE);
487         }
488     }
489
490     /**
491      * Performs the save content action.<p>
492      *
493      * This is also used when changing the element language.<p>
494      *
495      * @param locale the locale to save the content
496      * @throws JspException if including the error page fails
497      */

498     public void actionSave(Locale JavaDoc locale) throws JspException JavaDoc {
499
500         try {
501             setEditorValues(locale);
502             // check if content has errors
503
if (!getErrorHandler().hasErrors()) {
504                 // no errors found, write content and copy temp file contents
505
writeContent();
506                 commitTempFile();
507                 // set the modified parameter
508
setParamModified(Boolean.TRUE.toString());
509             }
510         } catch (CmsException e) {
511             showErrorPage(e);
512         }
513
514     }
515
516     /**
517      * Adds an optional element to the xml content or removes an optional element from the xml content.<p>
518      *
519      * Depends on the given action value.<p>
520      *
521      * @throws JspException if including the error page fails
522      */

523     public void actionToggleElement() throws JspException JavaDoc {
524
525         // set editor values from request
526
try {
527             setEditorValues(getElementLocale());
528         } catch (CmsXmlException e) {
529             // an error occured while trying to set the values, stop action
530
showErrorPage(e);
531             return;
532         }
533
534         // get the necessary parameters to add/remove the element
535
int index = 0;
536         try {
537             index = Integer.parseInt(getParamElementIndex());
538         } catch (Exception JavaDoc e) {
539             // ignore, should not happen
540
}
541
542         if (getAction() == ACTION_ELEMENT_REMOVE) {
543             // remove the value
544
m_content.removeValue(getParamElementName(), getElementLocale(), index);
545         } else {
546             // add the new value after the clicked element
547
if (m_content.hasValue(getParamElementName(), getElementLocale())) {
548                 // when other values are present, increase index to use right position
549
index += 1;
550             }
551             m_content.addValue(getCms(), getParamElementName(), getElementLocale(), index);
552         }
553
554         if (getErrorHandler().hasWarnings(getElementLocale())) {
555             // there were warnings for the edited content, reset error handler to avoid display issues
556
resetErrorHandler();
557         }
558
559         try {
560             // write the modified content to the temporary file
561
writeContent();
562         } catch (CmsException e) {
563             // an error occured while trying to save
564
showErrorPage(e);
565         }
566     }
567
568     /**
569      * Builds the html String for the element language selector.<p>
570      *
571      * This method has to use the resource request parameter because the temporary file is
572      * not available in the upper button frame.<p>
573      *
574      * @param attributes optional attributes for the &lt;select&gt; tag
575      * @return the html for the element language selectbox
576      */

577     public String JavaDoc buildSelectElementLanguage(String JavaDoc attributes) {
578
579         return buildSelectElementLanguage(attributes, getParamResource(), getElementLocale());
580     }
581
582     /**
583      * @see org.opencms.widgets.I_CmsWidgetDialog#getButtonStyle()
584      */

585     public int getButtonStyle() {
586
587         return getSettings().getUserSettings().getEditorButtonStyle();
588     }
589
590     /**
591      * @see org.opencms.workplace.editors.CmsEditor#getEditorResourceUri()
592      */

593     public String JavaDoc getEditorResourceUri() {
594
595         return getSkinUri() + "editors/" + EDITOR_TYPE + "/";
596     }
597
598     /**
599      * Returns the current element locale.<p>
600      *
601      * @return the current element locale
602      */

603     public Locale JavaDoc getElementLocale() {
604
605         if (m_elementLocale == null) {
606             if (CmsStringUtil.isNotEmpty(getParamElementlanguage()) && !"null".equals(getParamElementlanguage())) {
607                 m_elementLocale = CmsLocaleManager.getLocale(getParamElementlanguage());
608             } else {
609                 initElementLanguage();
610                 m_elementLocale = CmsLocaleManager.getLocale(getParamElementlanguage());
611             }
612         }
613         return m_elementLocale;
614     }
615
616     /**
617      * @see org.opencms.widgets.I_CmsWidgetDialog#getHelpMessageIds()
618      */

619     public Set JavaDoc getHelpMessageIds() {
620
621         if (m_helpMessageIds == null) {
622             m_helpMessageIds = new HashSet JavaDoc();
623         }
624         return m_helpMessageIds;
625     }
626
627     /**
628      * Returns the index of the element to add or remove.<p>
629      *
630      * @return the index of the element to add or remove
631      */

632     public String JavaDoc getParamElementIndex() {
633
634         return m_paramElementIndex;
635     }
636
637     /**
638      * Returns the name of the element to add or remove.<p>
639      *
640      * @return the name of the element to add or remove
641      */

642     public String JavaDoc getParamElementName() {
643
644         return m_paramElementName;
645     }
646
647     /**
648      * Returns the "new link" parameter.<p>
649      *
650      * @return the "new link" parameter
651      */

652     public String JavaDoc getParamNewLink() {
653
654         return m_paramNewLink;
655     }
656
657     /**
658      * @see org.opencms.widgets.I_CmsWidgetDialog#getUserAgent()
659      */

660     public String JavaDoc getUserAgent() {
661
662         return getJsp().getRequest().getHeader(CmsRequestUtil.HEADER_USER_AGENT);
663     }
664
665     /**
666      * Generates the HTML form for the XML content editor.<p>
667      *
668      * @return the HTML that generates the form for the XML editor
669      */

670     public String JavaDoc getXmlEditorForm() {
671
672         // set "editor mode" attribute (required for link replacement in the root site)
673
getCms().getRequestContext().setAttribute(CmsRequestContext.ATTRIBUTE_EDITOR, Boolean.TRUE);
674
675         // add customized message bundle eventually specified in XSD of XML content
676
addMessages(m_content.getContentDefinition().getContentHandler().getMessages(getLocale()));
677
678         return getXmlEditorForm(m_content.getContentDefinition(), "", true).toString();
679     }
680
681     /**
682      * Generates the HTML for the end of the html editor form page.<p>
683      *
684      * @return the HTML for the end of the html editor form page
685      * @throws JspException if including the error page fails
686      */

687     public String JavaDoc getXmlEditorHtmlEnd() throws JspException JavaDoc {
688
689         StringBuffer JavaDoc result = new StringBuffer JavaDoc(16384);
690         if (m_optionalElementPresent) {
691             // disabled optional element(s) present, reset widgets to show help bubbles on optional form entries
692
resetWidgetCollector();
693         }
694         try {
695             // get all widgets from collector
696
Iterator JavaDoc i = getWidgetCollector().getWidgets().keySet().iterator();
697             while (i.hasNext()) {
698                 // get the value of the widget
699
String JavaDoc key = (String JavaDoc)i.next();
700                 I_CmsXmlContentValue value = (I_CmsXmlContentValue)getWidgetCollector().getValues().get(key);
701                 I_CmsWidget widget = (I_CmsWidget)getWidgetCollector().getWidgets().get(key);
702                 result.append(widget.getDialogHtmlEnd(getCms(), this, (I_CmsWidgetParameter)value));
703
704             }
705
706             // add empty help text layer
707
result.append("<div class=\"help\" id=\"helpText\" ");
708             result.append("onmouseover=\"showHelpText();\" onmouseout=\"hideHelpText();\"></div>\n");
709
710             // add empty element button layer
711
result.append("<div class=\"xmlButtons\" id=\"xmlElementButtons\" ");
712             result.append("onmouseover=\"checkElementButtons(true);\" onmouseout=\"checkElementButtons(false);\"></div>\n");
713
714             // return the HTML
715
return result.toString();
716         } catch (Exception JavaDoc e) {
717             showErrorPage(e);
718             return "";
719         }
720     }
721
722     /**
723      * Generates the javascript includes for the used widgets in the editor form.<p>
724      *
725      * @return the javascript includes for the used widgets
726      * @throws JspException if including the error page fails
727      */

728     public String JavaDoc getXmlEditorIncludes() throws JspException JavaDoc {
729
730         StringBuffer JavaDoc result = new StringBuffer JavaDoc(32);
731         try {
732             // iterate over unique widgets from collector
733
Iterator JavaDoc i = getWidgetCollector().getUniqueWidgets().iterator();
734             while (i.hasNext()) {
735                 I_CmsWidget widget = (I_CmsWidget)i.next();
736                 result.append(widget.getDialogIncludes(getCms(), this));
737                 result.append("\n");
738             }
739         } catch (Exception JavaDoc e) {
740             showErrorPage(e);
741         }
742         return result.toString();
743     }
744
745     /**
746      * Generates the javascript initialization calls for the used widgets in the editor form.<p>
747      *
748      * @return the javascript initialization calls for the used widgets
749      * @throws JspException if including the error page fails
750      */

751     public String JavaDoc getXmlEditorInitCalls() throws JspException JavaDoc {
752
753         StringBuffer JavaDoc result = new StringBuffer JavaDoc(32);
754         try {
755             // iterate over unique widgets from collector
756
Iterator JavaDoc i = getWidgetCollector().getUniqueWidgets().iterator();
757             while (i.hasNext()) {
758                 I_CmsWidget widget = (I_CmsWidget)i.next();
759                 result.append(widget.getDialogInitCall(getCms(), this));
760             }
761         } catch (Exception JavaDoc e) {
762             showErrorPage(e);
763         }
764         return result.toString();
765     }
766
767     /**
768      * Generates the JavaScript initialization methods for the used widgets.<p>
769      *
770      * @return the JavaScript initialization methods for the used widgets
771      *
772      * @throws JspException if an error occurs during JavaScript generation
773      */

774     public String JavaDoc getXmlEditorInitMethods() throws JspException JavaDoc {
775
776         StringBuffer JavaDoc result = new StringBuffer JavaDoc(32);
777         try {
778             // iterate over unique widgets from collector
779
Iterator JavaDoc i = getWidgetCollector().getUniqueWidgets().iterator();
780             while (i.hasNext()) {
781                 I_CmsWidget widget = (I_CmsWidget)i.next();
782                 result.append(widget.getDialogInitMethod(getCms(), this));
783                 result.append("\n");
784             }
785         } catch (Exception JavaDoc e) {
786             showErrorPage(e);
787         }
788         return result.toString();
789     }
790
791     /**
792      * Returns true if the edited content contains validation errors, otherwise false.<p>
793      *
794      * @return true if the edited content contains validation errors, otherwise false
795      */

796     public boolean hasValidationErrors() {
797
798         return getErrorHandler().hasErrors();
799     }
800
801     /**
802      * Returns true if the preview is available for the edited xml content.<p>
803      *
804      * This method has to use the resource request parameter and read the file from vfs because the temporary file is
805      * not available in the upper button frame.<p>
806      *
807      * @return true if the preview is enabled, otherwise false
808      */

809     public boolean isPreviewEnabled() {
810
811         try {
812             // read the original file because temporary file is not created when opening button frame
813
CmsFile file = getCms().readFile(getParamResource(), CmsResourceFilter.ALL);
814             CmsXmlContent content = CmsXmlContentFactory.unmarshal(getCms(), file);
815             return content.getContentDefinition().getContentHandler().getPreview(
816                 getCms(),
817                 m_content,
818                 getParamResource()) != null;
819         } catch (Exception JavaDoc e) {
820             // error reading or unmarshalling, no preview available
821
return false;
822         }
823     }
824
825     /**
826      * Sets the editor values for the locale with the parameters from the request.<p>
827      *
828      * Called before saving the xml content, redisplaying the input form,
829      * changing the language and adding or removing elements.<p>
830      *
831      * @param locale the locale of the content to save
832      * @throws CmsXmlException if something goes wrong
833      */

834     public void setEditorValues(Locale JavaDoc locale) throws CmsXmlException {
835
836         List JavaDoc valueNames = getSimpleValueNames(m_content.getContentDefinition(), "", locale);
837         Iterator JavaDoc i = valueNames.iterator();
838         while (i.hasNext()) {
839             String JavaDoc valueName = (String JavaDoc)i.next();
840             I_CmsXmlContentValue value = m_content.getValue(valueName, locale);
841             I_CmsWidget widget = value.getContentDefinition().getContentHandler().getWidget(value);
842             widget.setEditorValue(getCms(), getJsp().getRequest().getParameterMap(), this, (I_CmsWidgetParameter)value);
843         }
844     }
845
846     /**
847      * Sets the index of the element to add or remove.<p>
848      *
849      * @param elementIndex the index of the element to add or remove
850      */

851     public void setParamElementIndex(String JavaDoc elementIndex) {
852
853         m_paramElementIndex = elementIndex;
854     }
855
856     /**
857      * Sets the name of the element to add or remove.<p>
858      *
859      * @param elementName the name of the element to add or remove
860      */

861     public void setParamElementName(String JavaDoc elementName) {
862
863         m_paramElementName = elementName;
864     }
865
866     /**
867      * Sets the "new link" parameter.<p>
868      *
869      * @param paramNewLink the "new link" parameter to set
870      */

871     public void setParamNewLink(String JavaDoc paramNewLink) {
872
873         m_paramNewLink = CmsEncoder.decode(paramNewLink);
874     }
875
876     /**
877      * Determines if the element language selector is shown dependent on the available Locales.<p>
878      *
879      * @return true, if more than one Locale is available, otherwise false
880      */

881     public boolean showElementLanguageSelector() {
882
883         List JavaDoc locales = OpenCms.getLocaleManager().getAvailableLocales(getCms(), getParamResource());
884         if (locales == null || locales.size() < 2) {
885             // for less than two available locales, do not create language selector
886
return false;
887         }
888         return true;
889     }
890
891     /**
892      * @see org.opencms.workplace.tools.CmsToolDialog#useNewStyle()
893      */

894     public boolean useNewStyle() {
895
896         return false;
897     }
898
899     /**
900      * Initializes the editor content when opening the editor for the first time.<p>
901      *
902      * Not necessary for the xmlcontent editor.<p>
903      */

904     protected void initContent() {
905
906         // nothing to be done for the xmlcontent editor form
907
}
908
909     /**
910      * Initializes the element language for the first call of the editor.<p>
911      */

912     protected void initElementLanguage() {
913
914         // get all locales of the content
915
List JavaDoc locales = new ArrayList JavaDoc();
916         if (m_content != null) {
917             locales = m_content.getLocales();
918         }
919         Locale JavaDoc defaultLocale = (Locale JavaDoc)OpenCms.getLocaleManager().getDefaultLocales(getCms(), getParamResource()).get(0);
920
921         if (locales.size() > 0) {
922             // locale element present, get the language
923
if (locales.contains(defaultLocale)) {
924                 // get the element for the default locale
925
setParamElementlanguage(defaultLocale.toString());
926                 return;
927             } else {
928                 // get the first element that can be found
929
setParamElementlanguage(locales.get(0).toString());
930                 return;
931             }
932         }
933         setParamElementlanguage(defaultLocale.toString());
934     }
935
936     /**
937      * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
938      */

939     protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest JavaDoc request) {
940
941         // fill the parameter values in the get/set methods
942
fillParamValues(request);
943         // set the dialog type
944
setParamDialogtype(EDITOR_TYPE);
945
946         if (getParamNewLink() != null) {
947             setParamAction(EDITOR_ACTION_NEW);
948         } else {
949             // initialize a content object from the temporary file
950
if (getParamTempfile() != null && !"null".equals(getParamTempfile())) {
951                 try {
952                     m_file = getCms().readFile(this.getParamTempfile(), CmsResourceFilter.ALL);
953                     m_content = CmsXmlContentFactory.unmarshal(getCms(), m_file);
954                 } catch (CmsException e) {
955                     // error during initialization, show error page
956
try {
957                         showErrorPage(this, e);
958                     } catch (JspException JavaDoc exc) {
959                         // should usually never happen
960
if (LOG.isInfoEnabled()) {
961                             LOG.info(exc);
962                         }
963                     }
964                 }
965             }
966         }
967
968         // set the action for the JSP switch
969
if (EDITOR_SAVE.equals(getParamAction())) {
970             setAction(ACTION_SAVE);
971         } else if (EDITOR_SAVEEXIT.equals(getParamAction())) {
972             setAction(ACTION_SAVEEXIT);
973         } else if (EDITOR_EXIT.equals(getParamAction())) {
974             setAction(ACTION_EXIT);
975         } else if (EDITOR_CLOSEBROWSER.equals(getParamAction())) {
976             // closed browser window accidentally, unlock resource and delete temporary file
977
actionClear(true);
978             return;
979         } else if (EDITOR_ACTION_CHECK.equals(getParamAction())) {
980             setAction(ACTION_CHECK);
981         } else if (EDITOR_SAVEACTION.equals(getParamAction())) {
982             setAction(ACTION_SAVEACTION);
983             try {
984                 actionDirectEdit();
985             } catch (Exception JavaDoc e) {
986                 // should usually never happen
987
if (LOG.isInfoEnabled()) {
988                     LOG.info(e.getLocalizedMessage(), e);
989                 }
990             }
991             setAction(ACTION_EXIT);
992         } else if (EDITOR_DELETELOCALE.equals(getParamAction())) {
993             setAction(ACTION_DELETELOCALE);
994         } else if (EDITOR_SHOW.equals(getParamAction())) {
995             setAction(ACTION_SHOW);
996         } else if (EDITOR_SHOW_ERRORMESSAGE.equals(getParamAction())) {
997             setAction(ACTION_SHOW_ERRORMESSAGE);
998         } else if (EDITOR_CHANGE_ELEMENT.equals(getParamAction())) {
999             setAction(ACTION_SHOW);
1000            actionChangeElementLanguage();
1001        } else if (EDITOR_ACTION_ELEMENT_ADD.equals(getParamAction())) {
1002            setAction(ACTION_ELEMENT_ADD);
1003            try {
1004                actionToggleElement();
1005            } catch (JspException JavaDoc e) {
1006                if (LOG.isErrorEnabled()) {
1007                    LOG.error(org.opencms.workplace.Messages.get().getBundle().key(
1008                        org.opencms.workplace.Messages.LOG_INCLUDE_ERRORPAGE_FAILED_0));
1009                }
1010            }
1011            if (getAction() != ACTION_CANCEL && getAction() != ACTION_SHOW_ERRORMESSAGE) {
1012                // no error ocurred, redisplay the input form
1013
setAction(ACTION_SHOW);
1014            }
1015        } else if (EDITOR_ACTION_ELEMENT_REMOVE.equals(getParamAction())) {
1016            setAction(ACTION_ELEMENT_REMOVE);
1017            try {
1018                actionToggleElement();
1019            } catch (JspException JavaDoc e) {
1020                if (LOG.isErrorEnabled()) {
1021                    LOG.error(org.opencms.workplace.Messages.get().getBundle().key(
1022                        org.opencms.workplace.Messages.LOG_INCLUDE_ERRORPAGE_FAILED_0));
1023                }
1024            }
1025            if (getAction() != ACTION_CANCEL && getAction() != ACTION_SHOW_ERRORMESSAGE) {
1026                // no error ocurred, redisplay the input form
1027
setAction(ACTION_SHOW);
1028            }
1029        } else if (EDITOR_ACTION_ELEMENT_MOVE_DOWN.equals(getParamAction())) {
1030            setAction(ACTION_ELEMENT_MOVE_DOWN);
1031            try {
1032                actionMoveElement();
1033            } catch (JspException JavaDoc e) {
1034                if (LOG.isErrorEnabled()) {
1035                    LOG.error(org.opencms.workplace.Messages.get().getBundle().key(
1036                        org.opencms.workplace.Messages.LOG_INCLUDE_ERRORPAGE_FAILED_0));
1037                }
1038            }
1039            if (getAction() != ACTION_CANCEL && getAction() != ACTION_SHOW_ERRORMESSAGE) {
1040                // no error ocurred, redisplay the input form
1041
setAction(ACTION_SHOW);
1042            }
1043        } else if (EDITOR_ACTION_ELEMENT_MOVE_UP.equals(getParamAction())) {
1044            setAction(ACTION_ELEMENT_MOVE_UP);
1045            try {
1046                actionMoveElement();
1047            } catch (JspException JavaDoc e) {
1048                if (LOG.isErrorEnabled()) {
1049                    LOG.error(org.opencms.workplace.Messages.get().getBundle().key(
1050                        org.opencms.workplace.Messages.LOG_INCLUDE_ERRORPAGE_FAILED_0));
1051                }
1052            }
1053            if (getAction() != ACTION_CANCEL && getAction() != ACTION_SHOW_ERRORMESSAGE) {
1054                // no error ocurred, redisplay the input form
1055
setAction(ACTION_SHOW);
1056            }
1057        } else if (EDITOR_ACTION_NEW.equals(getParamAction())) {
1058            setAction(ACTION_NEW);
1059            return;
1060        } else if (EDITOR_PREVIEW.equals(getParamAction())) {
1061            setAction(ACTION_PREVIEW);
1062        } else {
1063            // initial call of editor
1064
setAction(ACTION_DEFAULT);
1065            try {
1066                // lock resource if autolock is enabled in configuration
1067
if (Boolean.valueOf(getParamDirectedit()).booleanValue()) {
1068                    // set a temporary lock in direct edit mode
1069
checkLock(getParamResource(), CmsLock.TEMPORARY);
1070                } else {
1071                    // set common lock
1072
checkLock(getParamResource());
1073                }
1074                // create the temporary file
1075
setParamTempfile(createTempFile());
1076                // initialize a content object from the created temporary file
1077
m_file = getCms().readFile(this.getParamTempfile(), CmsResourceFilter.ALL);
1078                m_content = CmsXmlContentFactory.unmarshal(getCms(), m_file);
1079            } catch (CmsException e) {
1080                // error during initialization
1081
try {
1082                    showErrorPage(this, e);
1083                } catch (JspException JavaDoc exc) {
1084                    // should usually never happen
1085
if (LOG.isInfoEnabled()) {
1086                        LOG.info(exc);
1087                    }
1088                }
1089            }
1090            // set the initial element language if not given in request parameters
1091
if (getParamElementlanguage() == null) {
1092                initElementLanguage();
1093            }
1094        }
1095    }
1096
1097    /**
1098     * Returns the html for the element operation buttons add, move, remove.<p>
1099     *
1100     * @param elementName name of the element
1101     * @param index the index of the element
1102     * @param addElement if true, the button to add an element is shown
1103     * @param removeElement if true, the button to remove an element is shown
1104     * @return the html for the element operation buttons
1105     */

1106    private String JavaDoc buildElementButtons(String JavaDoc elementName, int index, boolean addElement, boolean removeElement) {
1107
1108        StringBuffer JavaDoc jsCall = new StringBuffer JavaDoc(512);
1109
1110        // indicates if at least one button is active
1111
boolean buttonPresent = false;
1112
1113        jsCall.append("showElementButtons('");
1114        jsCall.append(elementName);
1115        jsCall.append("', ");
1116        jsCall.append(index);
1117        jsCall.append(", ");
1118
1119        // build the remove element button if required
1120
if (removeElement) {
1121            jsCall.append(Boolean.TRUE);
1122            buttonPresent = true;
1123        } else {
1124            jsCall.append(Boolean.FALSE);
1125        }
1126        jsCall.append(", ");
1127
1128        // build the move down button (move down in API is move up for content editor)
1129
if (index > 0) {
1130            // build active move down button
1131
jsCall.append(Boolean.TRUE);
1132            buttonPresent = true;
1133        } else {
1134            jsCall.append(Boolean.FALSE);
1135        }
1136        jsCall.append(", ");
1137
1138        // build the move up button (move up in API is move down for content editor)
1139
int indexCount = m_content.getIndexCount(elementName, getElementLocale());
1140        if (index < (indexCount - 1)) {
1141            // build active move up button
1142
jsCall.append(Boolean.TRUE);
1143            buttonPresent = true;
1144        } else {
1145            jsCall.append(Boolean.FALSE);
1146        }
1147        jsCall.append(", ");
1148
1149        // build the add element button if required
1150
if (addElement) {
1151            jsCall.append(Boolean.TRUE);
1152            buttonPresent = true;
1153        } else {
1154            jsCall.append(Boolean.FALSE);
1155        }
1156        jsCall.append(");");
1157
1158        String JavaDoc result;
1159        if (buttonPresent) {
1160            // at least one button active, create mouseover button
1161
String JavaDoc btIcon = "xmledit.png";
1162            String JavaDoc btAction = jsCall.toString();
1163            // determine icon to use and if a direct click action is possible
1164
if (addElement && removeElement) {
1165                btIcon = "xmledit_del_add.png";
1166            } else if (addElement) {
1167                btIcon = "xmledit_add.png";
1168                // create button action to add element on button click
1169
StringBuffer JavaDoc action = new StringBuffer JavaDoc(128);
1170                action.append("addElement('");
1171                action.append(elementName);
1172                action.append("', ");
1173                action.append(index);
1174                action.append(");");
1175                btAction = action.toString();
1176            } else if (removeElement) {
1177                btIcon = "xmledit_del.png";
1178                // create button action to remove element on button click
1179
StringBuffer JavaDoc action = new StringBuffer JavaDoc(128);
1180                action.append("removeElement('");
1181                action.append(elementName);
1182                action.append("', ");
1183                action.append(index);
1184                action.append(");");
1185                btAction = action.toString();
1186            }
1187            StringBuffer JavaDoc href = new StringBuffer JavaDoc(512);
1188            href.append("javascript:");
1189            href.append(btAction);
1190            href.append("\" onmouseover=\"");
1191            href.append(jsCall);
1192            href.append("checkElementButtons(true);\" onmouseout=\"checkElementButtons(false);\" id=\"btimg.");
1193            href.append(elementName).append(".").append(index);
1194            result = button(href.toString(), null, btIcon, Messages.GUI_EDITOR_XMLCONTENT_ELEMENT_BUTTONS_0, 0);
1195        } else {
1196            // no active button, create a spacer
1197
result = buttonBarSpacer(1);
1198        }
1199
1200        return result;
1201    }
1202
1203    /**
1204     * Returns the error handler for error handling of the edited xml content.<p>
1205     *
1206     * @return the error handler
1207     */

1208    private CmsXmlContentErrorHandler getErrorHandler() {
1209
1210        if (m_errorHandler == null) {
1211            // errors were not yet checked, do this now and store result in member
1212
m_errorHandler = m_content.validate(getCms());
1213        }
1214        return m_errorHandler;
1215    }
1216
1217    /**
1218     * Returns a list of value names containing the complete xpath of each value as String.<p>
1219     *
1220     * @param contentDefinition the content definition to use
1221     * @param pathPrefix the xpath prefix
1222     * @param locale the locale to use
1223     * @return list of value names (containing the xpath of each value)
1224     */

1225    private List JavaDoc getSimpleValueNames(CmsXmlContentDefinition contentDefinition, String JavaDoc pathPrefix, Locale JavaDoc locale) {
1226
1227        List JavaDoc valueNames = new ArrayList JavaDoc();
1228        Iterator JavaDoc i = contentDefinition.getTypeSequence().iterator();
1229        while (i.hasNext()) {
1230
1231            I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)i.next();
1232
1233            String JavaDoc name = pathPrefix + type.getName();
1234
1235            // get the element sequence of the type
1236
CmsXmlContentValueSequence elementSequence = m_content.getValueSequence(name, locale);
1237            int elementCount = elementSequence.getElementCount();
1238            // loop through elements
1239
for (int j = 0; j < elementCount; j++) {
1240                I_CmsXmlContentValue value = elementSequence.getValue(j);
1241
1242                StringBuffer JavaDoc xPath = new StringBuffer JavaDoc(pathPrefix.length() + 16);
1243                xPath.append(pathPrefix);
1244                xPath.append(CmsXmlUtils.createXpathElement(type.getName(), value.getIndex() + 1));
1245
1246                if (!type.isSimpleType()) {
1247                    // recurse into nested type sequence
1248
CmsXmlNestedContentDefinition nestedSchema = (CmsXmlNestedContentDefinition)type;
1249                    xPath.append("/");
1250                    valueNames.addAll(getSimpleValueNames(
1251                        nestedSchema.getNestedContentDefinition(),
1252                        xPath.toString(),
1253                        locale));
1254                } else {
1255                    // this is a simple type, get widget to display
1256
valueNames.add(xPath.toString());
1257                }
1258            }
1259        }
1260        return valueNames;
1261    }
1262
1263    /**
1264     * Returns the different xml editor widgets used in the form to display.<p>
1265     *
1266     * @return the different xml editor widgets used in the form to display
1267     */

1268    private CmsXmlContentWidgetVisitor getWidgetCollector() {
1269
1270        if (m_widgetCollector == null) {
1271            // create an instance of the widget collector
1272
m_widgetCollector = new CmsXmlContentWidgetVisitor(getElementLocale());
1273            m_content.visitAllValuesWith(m_widgetCollector);
1274        }
1275        return m_widgetCollector;
1276    }
1277
1278    /**
1279     * Generates the HTML form for the XML content editor.<p>
1280     *
1281     * This is a recursive method because nested schemas are possible,
1282     * do not call this method directly.<p>
1283     *
1284     * @param contentDefinition the content definition to start with
1285     * @param pathPrefix for nested xml content
1286     * @param showHelpBubble if the code for a help bubble should be generated
1287     *
1288     * @return the HTML that generates the form for the XML editor
1289     */

1290    private StringBuffer JavaDoc getXmlEditorForm(
1291        CmsXmlContentDefinition contentDefinition,
1292        String JavaDoc pathPrefix,
1293        boolean showHelpBubble) {
1294
1295        StringBuffer JavaDoc result = new StringBuffer JavaDoc(1024);
1296        // only show errors if editor is not opened initially
1297
boolean showErrors = (getAction() != ACTION_NEW) && (getAction() != ACTION_DEFAULT);
1298
1299        try {
1300            // check if we are in a nested content definition
1301
boolean nested = CmsStringUtil.isNotEmpty(pathPrefix);
1302
1303            // create table
1304
result.append("<table class=\"xmlTable");
1305            if (nested) {
1306                // use other style for nested content definition table
1307
result.append("Nested");
1308            }
1309            result.append("\">\n");
1310
1311            // show error header once if there were validation errors
1312
if (!nested && showErrors && getErrorHandler().hasErrors(getElementLocale())) {
1313                result.append("<tr><td colspan=\"4\">&nbsp;</td></tr>\n");
1314                result.append("<tr><td colspan=\"2\">&nbsp;</td>");
1315                result.append("<td class=\"xmlTdErrorHeader\">");
1316                result.append(key(Messages.ERR_EDITOR_XMLCONTENT_VALIDATION_ERROR_TITLE_0));
1317                result.append("</td><td>&nbsp;");
1318                result.append("</td></tr>\n");
1319            }
1320
1321            // iterate the type sequence
1322
Iterator JavaDoc i = contentDefinition.getTypeSequence().iterator();
1323            while (i.hasNext()) {
1324                // get the type
1325
I_CmsXmlSchemaType type = (I_CmsXmlSchemaType)i.next();
1326                CmsXmlContentDefinition nestedContentDefinition = contentDefinition;
1327                if (!type.isSimpleType()) {
1328                    // get nested content definition for nested types
1329
CmsXmlNestedContentDefinition nestedSchema = (CmsXmlNestedContentDefinition)type;
1330                    nestedContentDefinition = nestedSchema.getNestedContentDefinition();
1331                }
1332                // create xpath to the current element
1333
String JavaDoc name = pathPrefix + type.getName();
1334
1335                // get the element sequence of the current type
1336
CmsXmlContentValueSequence elementSequence = m_content.getValueSequence(name, getElementLocale());
1337                int elementCount = elementSequence.getElementCount();
1338
1339                // check if value is optional or multiple
1340
boolean addValue = false;
1341                if (elementCount < type.getMaxOccurs()) {
1342                    addValue = true;
1343                }
1344                boolean removeValue = false;
1345                if (elementCount > type.getMinOccurs()) {
1346                    removeValue = true;
1347                }
1348
1349                // assure that at least one element is present in sequence
1350
boolean disabledElement = false;
1351                if (elementCount < 1) {
1352                    // current element is disabled, create dummy element
1353
elementCount = 1;
1354                    elementSequence.addValue(getCms(), 0);
1355                    disabledElement = true;
1356                    m_optionalElementPresent = true;
1357                }
1358
1359                // loop through multiple elements
1360
for (int j = 0; j < elementCount; j++) {
1361                    // get value and corresponding widget
1362
I_CmsXmlContentValue value = elementSequence.getValue(j);
1363                    I_CmsWidget widget = null;
1364                    if (type.isSimpleType()) {
1365                        widget = contentDefinition.getContentHandler().getWidget(value);
1366                    }
1367
1368                    // create label and help bubble cells
1369
result.append("<tr>");
1370                    result.append("<td class=\"xmlLabel");
1371                    if (disabledElement) {
1372                        // element is disabled, mark it with css
1373
result.append("Disabled");
1374                    }
1375                    result.append("\">");
1376                    result.append(keyDefault(A_CmsWidget.getLabelKey((I_CmsWidgetParameter)value), value.getName()));
1377                    if (elementCount > 1) {
1378                        result.append(" [").append(value.getIndex() + 1).append("]");
1379                    }
1380                    result.append(": </td>");
1381                    if (showHelpBubble && type.isSimpleType() && value.getIndex() == 0) {
1382                        // show help bubble only on first element of each content definition
1383
result.append(widget.getHelpBubble(getCms(), this, (I_CmsWidgetParameter)value));
1384                    } else {
1385                        // create empty cell for all following elements
1386
result.append(buttonBarSpacer(16));
1387                    }
1388
1389                    // append individual widget html cell if element is enabled
1390
if (!disabledElement) {
1391                        if (!type.isSimpleType()) {
1392                            // recurse into nested type sequence
1393
String JavaDoc newPath = CmsXmlUtils.createXpathElement(value.getName(), value.getIndex() + 1);
1394                            result.append("<td class=\"maxwidth\">");
1395                            boolean showHelp = (j == 0);
1396                            result.append(getXmlEditorForm(
1397                                nestedContentDefinition,
1398                                pathPrefix + newPath + "/",
1399                                showHelp));
1400                            result.append("</td>");
1401                        } else {
1402                            // this is a simple type, display widget
1403
result.append(widget.getDialogWidget(getCms(), this, (I_CmsWidgetParameter)value));
1404                        }
1405                    } else {
1406                        // disabled element, show message for optional element
1407
result.append("<td class=\"xmlTdDisabled maxwidth\">");
1408                        result.append(key(Messages.GUI_EDITOR_XMLCONTENT_OPTIONALELEMENT_0));
1409                        result.append("</td>");
1410                    }
1411
1412                    // append element operation (add, remove, move) buttons if required
1413
result.append(buildElementButtons(name, value.getIndex(), addValue, removeValue));
1414
1415                    // close row
1416
result.append("</tr>\n");
1417
1418                    // show errors and/or warnings
1419
String JavaDoc key = value.getPath();
1420                    if (showErrors
1421                        && getErrorHandler().hasErrors(getElementLocale())
1422                        && getErrorHandler().getErrors(getElementLocale()).containsKey(key)) {
1423                        // show error message
1424
result.append("<tr><td></td><td><img SRC=\"");
1425                        result.append(getEditorResourceUri());
1426                        result.append("error.png");
1427                        result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError\">");
1428                        result.append(resolveMacros((String JavaDoc)getErrorHandler().getErrors(getElementLocale()).get(key)));
1429                        result.append("</td><td></td></tr>\n");
1430                    }
1431                    // warnings can be additional to errors
1432
if (showErrors
1433                        && getErrorHandler().hasWarnings(getElementLocale())
1434                        && getErrorHandler().getWarnings(getElementLocale()).containsKey(key)) {
1435                        // show warning message
1436
result.append("<tr><td></td><td><img SRC=\"");
1437                        result.append(getEditorResourceUri());
1438                        result.append("warning.png");
1439                        result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdWarning\">");
1440                        result.append(resolveMacros((String JavaDoc)getErrorHandler().getWarnings(getElementLocale()).get(key)));
1441                        result.append("</td><td></td></tr>\n");
1442                    }
1443                }
1444            }
1445            // close table
1446
result.append("</table>\n");
1447        } catch (Throwable JavaDoc t) {
1448            LOG.error(Messages.get().getBundle().key(Messages.ERR_XML_EDITOR_0), t);
1449        }
1450        return result;
1451    }
1452
1453    /**
1454     * Resets the error handler member variable to reinitialize the error messages.<p>
1455     */

1456    private void resetErrorHandler() {
1457
1458        m_errorHandler = null;
1459    }
1460
1461    /**
1462     * Resets the widget collector member variable to reinitialize the widgets.<p>
1463     *
1464     * This is needed to display the help messages of optional elements before building the html end of the form.<p>
1465     */

1466    private void resetWidgetCollector() {
1467
1468        m_widgetCollector = null;
1469    }
1470
1471    /**
1472     * Writes the xml content to the vfs and re-initializes the member variables.<p>
1473     *
1474     * @throws CmsException if writing the file fails
1475     */

1476    private void writeContent() throws CmsException {
1477
1478        String JavaDoc decodedContent = m_content.toString();
1479        try {
1480            m_file.setContents(decodedContent.getBytes(getFileEncoding()));
1481        } catch (UnsupportedEncodingException JavaDoc e) {
1482            throw new CmsException(Messages.get().container(Messages.ERR_INVALID_CONTENT_ENC_1, getParamResource()), e);
1483        }
1484        // the file content might have been modified during the write operation
1485
m_file = getCms().writeFile(m_file);
1486        m_content = CmsXmlContentFactory.unmarshal(getCms(), m_file);
1487    }
1488}
Popular Tags