Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/xpn/xwiki/doc/XWikiDocument.java


1   /**
2    * ===================================================================
3    *
4    * Copyright (c) 2003 Ludovic Dubost, All rights reserved.
5    *
6    * This program is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU General Public License
8    * as published by the Free Software Foundation; either version 2
9    * of the License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details, published at
15   * http://www.gnu.org/copyleft/gpl.html or in gpl.txt in the
16   * root folder of this distribution.
17   *
18   * Created by
19   * User: Ludovic Dubost
20   * Date: 24 nov. 2003
21   * Time: 00:00:31
22   */
23  package com.xpn.xwiki.doc;
24  
25  import com.xpn.xwiki.XWiki;
26  import com.xpn.xwiki.XWikiContext;
27  import com.xpn.xwiki.XWikiException;
28  import com.xpn.xwiki.notify.XWikiNotificationRule;
29  import com.xpn.xwiki.objects.BaseCollection;
30  import com.xpn.xwiki.objects.BaseObject;
31  import com.xpn.xwiki.objects.BaseProperty;
32  import com.xpn.xwiki.objects.classes.BaseClass;
33  import com.xpn.xwiki.objects.classes.PropertyClass;
34  import com.xpn.xwiki.render.XWikiVelocityRenderer;
35  import com.xpn.xwiki.store.XWikiStoreInterface;
36  import com.xpn.xwiki.store.XWikiHibernateStore;
37  import com.xpn.xwiki.util.Util;
38  import com.xpn.xwiki.web.EditForm;
39  import com.xpn.xwiki.web.PrepareEditForm;
40  import com.xpn.xwiki.web.Utils;
41  import com.xpn.xwiki.web.ObjectAddForm;
42  import org.apache.commons.jrcs.diff.Diff;
43  import org.apache.commons.jrcs.diff.DifferentiationFailedException;
44  import org.apache.commons.jrcs.diff.Revision;
45  import org.apache.commons.jrcs.rcs.Archive;
46  import org.apache.commons.jrcs.rcs.Lines;
47  import org.apache.commons.jrcs.rcs.Version;
48  import org.apache.commons.jrcs.util.ToString;
49  import org.apache.commons.logging.Log;
50  import org.apache.commons.logging.LogFactory;
51  import org.apache.commons.lang.StringUtils;
52  import org.apache.ecs.filter.CharacterFilter;
53  import org.apache.tools.ant.filters.StringInputStream;
54  import org.apache.velocity.VelocityContext;
55  import org.apache.velocity.app.tools.VelocityFormatter;
56  import org.dom4j.Document;
57  import org.dom4j.DocumentException;
58  import org.dom4j.Element;
59  import org.dom4j.dom.DOMDocument;
60  import org.dom4j.dom.DOMElement;
61  import org.dom4j.io.OutputFormat;
62  import org.dom4j.io.SAXReader;
63  import org.dom4j.io.XMLWriter;
64  
65  import javax.servlet.http.HttpServletRequest;
66  import java.io.IOException;
67  import java.io.StringWriter;
68  import java.io.StringReader;
69  import java.net.URL;
70  import java.util.*;
71  import java.util.zip.ZipEntry;
72  import java.util.zip.ZipOutputStream;
73  
74  
75  public class XWikiDocument {
76      private static final Log log = LogFactory.getLog(XWikiHibernateStore.class);
77  
78      private String parent;
79      private String web;
80      private String name;
81      private String content;
82      private String meta;
83      private String format;
84      private String creator;
85      private String author;
86      private Archive archive;
87      private Date updateDate;
88      private Date creationDate;
89      private Version version;
90      private long id = 0;
91      private boolean mostRecent = false;
92      private boolean isNew = true;
93      private String template;
94      private String language;
95      private String defaultLanguage;
96      private int translation;
97      private String database;
98  
99      // Used to make sure the MetaData String is regenerated
100     private boolean isContentDirty = false;
101     // Used to make sure the MetaData String is regenerated
102     private boolean isMetaDataDirty = false;
103 
104     // Meta Data
105     private BaseClass xWikiClass;
106     private Map xWikiObjects = new HashMap();
107 
108     private List attachmentList;
109 
110     // Caching
111     private boolean fromCache = false;
112     private ArrayList objectsToRemove = new ArrayList();
113 
114     private XWikiStoreInterface store;
115 
116     public XWikiStoreInterface getStore() {
117         return store;
118     }
119 
120     public void setStore(XWikiStoreInterface store) {
121         this.store = store;
122     }
123 
124 
125     public long getId() {
126         if ((language==null)||language.trim().equals(""))
127             id = getFullName().hashCode();
128         else
129             id = (getFullName() + ":" + language).hashCode();
130 
131         //if (log.isDebugEnabled())
132         //    log.debug("ID: " + getFullName() + " " + language + ": " + id);
133         return id;
134     }
135 
136     public void setId(long id) {
137         this.id = id;
138     }
139 
140     public String getWeb() {
141         return web;
142     }
143 
144     public void setWeb(String web) {
145         this.web = web;
146     }
147 
148     public String getVersion() {
149         return getRCSVersion().toString();
150     }
151 
152     public void setVersion(String version) {
153         this.version = new Version(version);
154     }
155 
156     public Version getRCSVersion() {
157         if (version == null) {
158             version = new Version("1.1");
159         }
160         return version;
161     }
162 
163     public void setRCSVersion(Version version) {
164         this.version = version;
165     }
166 
167     public XWikiDocument() {
168         this("Main", "WebHome");
169     }
170 
171     public XWikiDocument(String web, String name) {
172         this.web = web;
173 
174         int i1 =name.indexOf(".");
175         if (i1==-1) {
176             this.name = name;
177         } else {
178             this.web = name.substring(0,i1);
179             this.name = name.substring(i1+1);
180         }
181         this.updateDate = new Date();
182         this.creationDate = new Date();
183         this.parent = "";
184         this.content = "\n";
185         this.format = "";
186         this.author = "";
187         this.language = "";
188         this.defaultLanguage = "";
189         this.archive = null;
190         this.attachmentList = new ArrayList();
191     }
192 
193     public XWikiDocument getParentDoc() {
194         return new XWikiDocument(web, getParent());
195     }
196 
197     public String getParent() {
198         return parent.trim();
199     }
200 
201     public void setParent(String parent) {
202         if (!parent.equals(this.parent)) {
203             setMetaDataDirty(true);
204         }
205         this.parent = parent;
206     }
207 
208     public String getContent() {
209         return content;
210     }
211 
212     public void setContent(String content) {
213         if (!content.equals(this.content)) {
214             setContentDirty(true);
215         }
216         this.content = content;
217     }
218 
219     public String getRenderedContent(XWikiContext context) throws XWikiException {
220         return context.getWiki().getRenderingEngine().renderDocument(this, context);
221     }
222 
223     public String getRenderedContent(String text, XWikiContext context) {
224         return context.getWiki().getRenderingEngine().renderText(text, this, context);
225     }
226 
227     public String getEscapedContent(XWikiContext context) throws XWikiException {
228         CharacterFilter filter = new CharacterFilter();
229         return filter.process(getTranslatedContent(context));
230     }
231 
232 
233     public String getName() {
234         return name;
235     }
236 
237     public void setName(String name) {
238         this.name = name;
239     }
240 
241     public String getFullName() {
242         StringBuffer buf = new StringBuffer();
243         buf.append(getWeb());
244         buf.append(".");
245         buf.append(getName());
246         return buf.toString();
247     }
248 
249     public void setFullName(String name) {
250         // Should not be used
251     }
252 
253     public String getFormat() {
254         if (format==null)
255             return "";
256         else
257             return format;
258     }
259 
260     public void setFormat(String format) {
261         this.format = format;
262         if (!format.equals(this.format)) {
263             setMetaDataDirty(true);
264         }
265     }
266 
267     public String getAuthor() {
268         if (author==null)
269             return "";
270         else
271             return author.trim();
272     }
273 
274     public void setAuthor(String author) {
275         if (!getAuthor().equals(this.author)) {
276             setMetaDataDirty(true);
277         }
278         this.author = author;
279     }
280 
281     public String getCreator() {
282         if (creator==null)
283             return "";
284         else
285             return creator.trim();
286     }
287 
288     public void setCreator(String creator) {
289         if (!getCreator().equals(this.creator)) {
290             setMetaDataDirty(true);
291         }
292         this.creator = creator;
293     }
294 
295     public Date getDate() {
296         if (updateDate==null)
297             return new Date();
298         else
299             return updateDate;
300     }
301 
302     public void setDate(Date date) {
303         if (!date.equals(this.updateDate)) {
304             setMetaDataDirty(true);
305         }
306         this.updateDate = date;
307     }
308 
309     public Date getCreationDate() {
310         if (creationDate == null)
311             return new Date();
312         else
313             return creationDate;
314     }
315 
316     public void setCreationDate(Date date) {
317         if (!creationDate.equals(this.creationDate)) {
318             setMetaDataDirty(true);
319         }
320         this.creationDate = date;
321     }
322 
323     public String getMeta() {
324         return meta;
325     }
326 
327     public void setMeta(String meta) {
328         if (meta==null) {
329             if (this.meta!=null)
330                 setMetaDataDirty(true);
331         } else if (!meta.equals(this.meta)) {
332             setMetaDataDirty(true);
333         }
334         this.meta = meta;
335     }
336 
337     public void appendMeta(String meta) {
338         StringBuffer buf = new StringBuffer(this.meta);
339         buf.append(meta);
340         buf.append("\n");
341         this.meta = buf.toString();
342         setMetaDataDirty(true);
343     }
344 
345     public boolean isContentDirty() {
346         return isContentDirty;
347     }
348 
349     public void incrementVersion() {
350         if (version==null)
351             version = new Version("1.1");
352         else {
353             version = version.next();
354         }
355     }
356 
357     public void setContentDirty(boolean contentDirty) {
358         isContentDirty = contentDirty;
359     }
360 
361     public boolean isMetaDataDirty() {
362         return isMetaDataDirty;
363     }
364 
365     public void setMetaDataDirty(boolean metaDataDirty) {
366         isMetaDataDirty = metaDataDirty;
367     }
368 
369     public String getAttachmentURL(String filename, XWikiContext context) {
370         return getAttachmentURL(filename, "download", context);
371     }
372 
373     public String getAttachmentURL(String filename, String action, XWikiContext context) {
374         URL url = context.getURLFactory().createAttachmentURL(filename, getWeb(), getName(), action, context);
375         return context.getURLFactory().getURL(url, context);
376     }
377 
378     public String getURL(String action, boolean redirect, XWikiContext context) {
379         URL url = context.getURLFactory().createURL(getWeb(), getName(), action, redirect, context);
380         if (redirect) {
381             if (url==null)
382                 return null;
383             else
384                 return url.toString();
385         }
386         else
387             return context.getURLFactory().getURL(url, context);
388     }
389 
390     public String getURL(String action, XWikiContext context) {
391         return getURL(action, false, context);
392     }
393 
394     public String getURL(String action, String querystring, XWikiContext context) {
395         URL url = context.getURLFactory().createURL(getWeb(), getName(), action,
396                 querystring, null, context);
397         return context.getURLFactory().getURL(url, context);
398     }
399 
400     public String getExternalURL(String action, XWikiContext context) {
401         URL url = context.getURLFactory().createExternalURL(getWeb(), getName(), action,
402                 null , null, context);
403         return url.toString();
404     }
405 
406     public String getExternalURL(String action, String querystring, XWikiContext context) {
407         URL url = context.getURLFactory().createExternalURL(getWeb(), getName(), action,
408                 querystring, null, context);
409         return url.toString();
410     }
411 
412 
413     public String getParentURL(XWikiContext context) throws XWikiException {
414         XWikiDocument doc = new XWikiDocument();
415         doc.setFullName(getParent(), context);
416         URL url = context.getURLFactory().createURL(doc.getWeb(), doc.getName(), context);
417         return context.getURLFactory().getURL(url, context);
418     }
419 
420     public Version[] getRevisions(XWikiContext context) throws XWikiException {
421         return getStore().getXWikiDocVersions(this, context);
422     }
423 
424     public String[] getRecentRevisions(int nb, XWikiContext context) throws XWikiException {
425         try {
426             Version[] revisions = getStore().getXWikiDocVersions(this, context);
427             int length = nb;
428 
429             // 0 means all revisions
430             if (nb==0)
431                 length = revisions.length;
432 
433             if (revisions.length<length)
434                 length = revisions.length;
435 
436             String[] recentrevs = new String[length];
437             for (int i = 1; i <= length; i++)
438                 recentrevs[i-1
439                         ] = revisions[revisions.length-i].toString();
440             return recentrevs;
441         } catch (Exception e) {
442             return new String[0];
443         }
444     }
445 
446     public Archive getRCSArchive() {
447         return archive;
448     }
449 
450     public void setRCSArchive(Archive archive) {
451         this.archive = archive;
452     }
453 
454     public String getArchive() throws XWikiException {
455         return getArchive(null);
456     }
457 
458     public String getArchive(XWikiContext context) throws XWikiException {
459         if ((content==null)||(content.equals("")))
460             setContent("\n");
461         if (archive==null)
462             updateArchive(toXML(context));
463         if (archive==null)
464             return "";
465         else {
466             StringBuffer buffer = new StringBuffer();
467             archive.toString(buffer);
468             return buffer.toString();
469         }
470     }
471 
472     public void setArchive(String text) throws XWikiException {
473         try {
474             StringInputStream is = new StringInputStream(text);
475             archive = new Archive(getFullName(), is);
476         }
477         catch (Exception e) {
478             Object[] args = { getFullName() };
479             throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_STORE_ARCHIVEFORMAT,
480                     "Exception while manipulating the archive for doc {0}", e, args);
481         }
482     }
483 
484     public void updateArchive(String text) throws XWikiException {
485         try {
486             Lines lines = new Lines(text);
487             if (archive!=null)
488                 archive.addRevision(lines.toArray(),"");
489             else
490                 archive = new Archive(lines.toArray(),getFullName(),getVersion());
491         }
492         catch (Exception e) {
493             Object[] args = { getFullName() };
494             throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_STORE_ARCHIVEFORMAT,
495                     "Exception while manipulating the archive for doc {0}", e, args);
496         }
497     }
498 
499     public boolean isMostRecent() {
500         return mostRecent;
501     }
502 
503     public void setMostRecent(boolean mostRecent) {
504         this.mostRecent = mostRecent;
505     }
506 
507     public BaseClass getxWikiClass() {
508         if (xWikiClass==null) {
509             xWikiClass = new BaseClass();
510             xWikiClass.setName(getFullName());
511         }
512         return xWikiClass;
513     }
514 
515     public void setxWikiClass(BaseClass xWikiClass) {
516         this.xWikiClass = xWikiClass;
517     }
518 
519     public Map getxWikiObjects() {
520         return xWikiObjects;
521     }
522 
523     public void setxWikiObjects(Map xWikiObjects) {
524         this.xWikiObjects = xWikiObjects;
525     }
526 
527     public BaseObject getxWikiObject() {
528         return getObject(getFullName());
529     }
530 
531     public List getxWikiClasses(XWikiContext context) {
532         List list = new ArrayList();
533         for (Iterator it=getxWikiObjects().keySet().iterator();it.hasNext();) {
534             String classname = (String) it.next();
535             BaseClass bclass = null;
536             Vector objects = getObjects(classname);
537             for (int i=0;i<objects.size();i++) {
538                 BaseObject obj = (BaseObject) objects.get(i);
539                 if (obj!=null) {
540                     bclass = obj.getxWikiClass(context);
541                     if (bclass!=null)
542                         break;
543                 }
544             }
545             if (bclass!=null)
546                 list.add(bclass);
547         }
548         return list;
549     }
550 
551     public int createNewObject(String classname, XWikiContext context) throws XWikiException {
552         BaseObject object = new BaseObject();
553         object.setName(getFullName());
554         object.setClassName(classname);
555         Vector objects = getObjects(classname);
556         if (objects==null) {
557             objects = new Vector();
558             setObjects(classname, objects);
559         }
560         objects.add(object);
561         int nb = objects.size()-1;
562         object.setNumber(nb);
563         return nb;
564     }
565 
566     public int getObjectNumbers(String classname) {
567         try {
568             return ((Vector)getxWikiObjects().get(classname)).size();
569         } catch (Exception e) {
570             return 0;
571         }
572     }
573 
574     public Vector getObjects(String classname) {
575         return (Vector) getxWikiObjects().get(classname);
576     }
577 
578     public void setObjects(String classname, Vector objects) {
579         getxWikiObjects().put(classname, objects);
580     }
581 
582     public BaseObject getObject(String classname) {
583         Vector objects = (Vector)getxWikiObjects().get(classname);
584         if (objects==null)
585             return null;
586         for (int i=0;i<objects.size();i++) {
587             BaseObject obj = (BaseObject) objects.get(i);
588             if (obj!=null)
589                 return obj;
590         }
591         return null;
592     }
593 
594     public BaseObject getObject(String classname, int nb) {
595         try {
596             return (BaseObject) ((Vector)getxWikiObjects().get(classname)).get(nb);
597         } catch (Exception e) {
598             return null;
599         }
600     }
601 
602     public BaseObject getObject(String classname, String key, String value) {
603         return getObject(classname, key, value, false);
604     }
605 
606     public BaseObject getObject(String classname, String key, String value, boolean failover) {
607         try {
608             if (value==null) {
609                 if (failover)
610                     return getObject(classname);
611                 else
612                     return null;
613             }
614 
615             Vector objects = (Vector)getxWikiObjects().get(classname);
616             if ((objects==null)||(objects.size()==0))
617                 return null;
618             for (int i=0;i<objects.size();i++) {
619                 BaseObject obj = (BaseObject) objects.get(i);
620                 if (obj!=null) {
621                     if (value.equals(obj.getStringValue(key)))
622                         return obj;
623                 }
624             }
625 
626             if (failover)
627                 return getObject(classname);
628             else
629                 return null;
630         } catch (Exception e) {
631             if (failover)
632                 return getObject(classname);
633 
634             e.printStackTrace();
635             return null;
636         }
637     }
638 
639 
640     public void addObject(String classname, BaseObject object) {
641         Vector vobj = getObjects(classname);
642         if (vobj==null)
643             setObject(classname, 0, object);
644         else
645             setObject(classname, vobj.size(), object);
646     }
647 
648     public void setObject(String classname, int nb, BaseObject object) {
649         Vector objects = null;
650         objects = getObjects(classname);
651         if (objects==null) {
652             objects = new Vector();
653             setObjects(classname, objects);
654         }
655         if (nb >= objects.size()) {
656             objects.setSize(nb+1);
657         }
658         objects.set(nb, object);
659         object.setNumber(nb);
660     }
661 
662     public boolean isNew() {
663         return isNew;
664     }
665 
666     public void setNew(boolean aNew) {
667         isNew = aNew;
668     }
669 
670     public void mergexWikiClass(XWikiDocument templatedoc) {
671         BaseClass bclass = getxWikiClass();
672         BaseClass tbclass = templatedoc.getxWikiClass();
673         if (tbclass!=null) {
674             if (bclass==null) {
675                 setxWikiClass((BaseClass)tbclass.clone());
676             } else {
677                 getxWikiClass().merge((BaseClass)tbclass.clone());
678             }
679         }
680     }
681 
682     public void mergexWikiObjects(XWikiDocument templatedoc) {
683         // TODO: look for each object if it already exist and add it if it doesn't
684         Iterator itobjects = templatedoc.getxWikiObjects().keySet().iterator();
685         while (itobjects.hasNext()) {
686             String name = (String) itobjects.next();
687             Vector objects = (Vector) getxWikiObjects().get(name);
688 
689             if (objects!=null) {
690                 Vector tobjects = (Vector) templatedoc.getxWikiObjects().get(name);
691                 for (int i=0;i<tobjects.size();i++) {
692                     {
693                         BaseObject bobj = (BaseObject) ((BaseObject) tobjects.get(i)).clone();
694                         objects.add(bobj);
695                         bobj.setNumber(objects.size()-1);
696                     }
697                 }
698             } else {
699                 Vector tobjects = (Vector) templatedoc.getObjects(name);
700                 objects = new Vector();
701                 for (int i=0;i<tobjects.size();i++)
702                 {
703                     BaseObject bobj1 = (BaseObject) tobjects.get(i);
704                     if (bobj1!=null) {
705                         BaseObject bobj = (BaseObject)bobj1.clone();
706                         objects.add(bobj);
707                         bobj.setNumber(objects.size()-1);
708                     }
709                 }
710                 getxWikiObjects().put(name, objects);
711             }
712         }
713     }
714 
715     public String getTemplate() {
716         return template;
717     }
718 
719     public void setTemplate(String template) {
720         this.template = template;
721     }
722 
723     public String display(String fieldname, String type, BaseObject obj, XWikiContext context) {
724         try {
725             type = type.toLowerCase();
726             StringBuffer result = new StringBuffer();
727             PropertyClass pclass = (PropertyClass) obj.getxWikiClass(context).get(fieldname);
728             String prefix = obj.getxWikiClass(context).getName() + "_" + obj.getNumber() + "_";
729 
730             if (type.equals("view")) {
731                 pclass.displayView(result, fieldname, prefix, obj, context);
732             }
733             else if (type.equals("rendered")) {
734                 String fcontent = pclass.displayView(fieldname, prefix, obj, context);
735                 result.append(getRenderedContent(fcontent, context));
736             }
737             else if (type.equals("edit")) {
738                 result.append("{pre}");
739                 pclass.displayEdit(result, fieldname, prefix, obj, context);
740                 result.append("{/pre}");
741             }
742             else if (type.equals("hidden")) {
743                 result.append("{pre}");
744                 pclass.displayHidden(result, fieldname, prefix, obj, context);
745                 result.append("{/pre}");
746             }
747             else if (type.equals("search")) {
748                 result.append("{pre}");
749                 pclass.displaySearch(result, fieldname, prefix, obj, context);
750                 result.append("{/pre}");
751             }
752             else {
753                 pclass.displayView(result, fieldname, prefix, obj, context);
754             }
755             return result.toString();
756         }
757         catch (Exception e) {
758             return "";
759             // return "||Exception showing field " + fieldname + ": " + e.getMessage() + "||";
760         }
761     }
762 
763     public String display(String fieldname, BaseObject obj, XWikiContext context) {
764         String type = null;
765         try { type = (String) context.get("display"); }
766         catch (Exception e) {
767         };
768         if (type==null)
769             type = "view";
770         return display(fieldname, type, obj, context);
771     }
772 
773     public String display(String fieldname, XWikiContext context) {
774         try {
775             BaseObject object = getxWikiObject();
776             if (object==null)
777                 object = getFirstObject(fieldname);
778             return display(fieldname, object, context);
779         } catch (Exception e) {
780             return "";
781         }
782     }
783 
784     public String display(String fieldname, String mode, XWikiContext context) {
785         try {
786             BaseObject object = getxWikiObject();
787             if (object==null)
788                 object = getFirstObject(fieldname);
789             if (object==null)
790                 return "";
791             else
792                 return display(fieldname, mode, object, context);
793         } catch (Exception e) {
794             return "";
795         }
796     }
797 
798     public String displayForm(String className,String header, String format, XWikiContext context) {
799         return displayForm(className, header, format, true, context);
800     }
801 
802     public String displayForm(String className,String header, String format, boolean linebreak, XWikiContext context) {
803         Vector objects = getObjects(className);
804         if (format.endsWith("\\n"))
805             linebreak = true;
806 
807         BaseObject firstobject = null;
808         Iterator foit = objects.iterator();
809         while ((firstobject==null)&&foit.hasNext()) {
810             firstobject = (BaseObject) foit.next();
811         }
812 
813         if (firstobject==null)
814             return "";
815 
816         BaseClass bclass = firstobject.getxWikiClass(context);
817         Collection fields = bclass.getFieldList();
818         if (fields.size()==0)
819             return "";
820 
821         StringBuffer result = new StringBuffer();
822         XWikiVelocityRenderer renderer = new XWikiVelocityRenderer();
823         VelocityContext vcontext = new VelocityContext();
824         vcontext.put("formatter", new VelocityFormatter(vcontext));
825         for (Iterator it = fields.iterator();it.hasNext();) {
826             PropertyClass pclass = (PropertyClass) it.next();
827             vcontext.put(pclass.getName(), pclass.getPrettyName());
828         }
829         result.append(renderer.evaluate(header, context.getDoc().getFullName(), vcontext, context));
830         if (linebreak)
831             result.append("\n");
832 
833         // display each line
834         for (int i=0;i<objects.size();i++) {
835             vcontext.put("id", new Integer(i+1));
836             BaseObject object = (BaseObject) objects.get(i);
837             if (object!=null) {
838                 for (Iterator it = bclass.getPropertyList().iterator();it.hasNext();) {
839                     String name = (String) it.next();
840                     vcontext.put(name, display(name, object, context));
841                 }
842                 result.append(renderer.evaluate(format, context.getDoc().getFullName(), vcontext, context));
843                 if (linebreak)
844                     result.append("\n");
845             }
846         }
847         return result.toString();
848     }
849 
850     public String displayForm(String className, XWikiContext context) {
851         Vector objects = getObjects(className);
852         if (objects==null)
853             return "";
854 
855         BaseObject firstobject = null;
856         Iterator foit = objects.iterator();
857         while ((firstobject==null)&&foit.hasNext()) {
858             firstobject = (BaseObject) foit.next();
859         }
860 
861         if (firstobject==null)
862             return "";
863 
864         BaseClass bclass = firstobject.getxWikiClass(context);
865         Collection fields = bclass.getFieldList();
866         if (fields.size()==0)
867             return "";
868 
869         StringBuffer result = new StringBuffer();
870         result.append("{table}\n");
871         boolean first = true;
872         for (Iterator it = fields.iterator();it.hasNext();) {
873             if (first==true)
874                 first = false;
875             else
876                 result.append("|");
877             PropertyClass pclass = (PropertyClass) it.next();
878             result.append(pclass.getPrettyName());
879         }
880         result.append("\n");
881         for (int i=0;i<objects.size();i++) {
882             BaseObject object = (BaseObject) objects.get(i);
883             if (object!=null) {
884                 first = true;
885                 for (Iterator it = bclass.getPropertyList().iterator();it.hasNext();) {
886                     if (first==true)
887                         first = false;
888                     else
889                         result.append("|");
890                     String data = display((String)it.next(), object, context);
891                     if (data.trim().equals(""))
892                         result.append("&nbsp;");
893                     else
894                         result.append(data);
895                 }
896                 result.append("\n");
897             }
898         }
899         result.append("{table}\n");
900         return result.toString();
901     }
902 
903 
904     public boolean isFromCache() {
905         return fromCache;
906     }
907 
908     public void setFromCache(boolean fromCache) {
909         this.fromCache = fromCache;
910     }
911 
912     public void readFromForm(EditForm eform, XWikiContext context) throws XWikiException {
913         String content = eform.getContent();
914         if ((content!=null)&&(!content.equals(""))) {
915             // Cleanup in case we use HTMLAREA
916             // content = context.getUtil().substitute("s/<br class=\\\"htmlarea\\\"\\/>/\\r\\n/g", content);
917             content = context.getUtil().substitute("s/<br class=\"htmlarea\" \\/>/\r\n/g", content);
918             setContent(content);
919         }
920         String parent = eform.getParent();
921         if (parent!=null)
922             setParent(parent);
923 
924         String creator = eform.getCreator();
925         if ((creator!=null)&&(!creator.equals(getCreator()))) {
926             if ((getCreator().equals(context.getUser()))
927                     ||(context.getWiki().getRightService().hasAdminRights(context)))
928                 setCreator(creator);
929         }
930 
931         String defaultLanguage = eform.getDefaultLanguage();
932         if (defaultLanguage!=null)
933             setDefaultLanguage(defaultLanguage);
934 
935         // This is now done before
936         // readFromTemplate(eform, context);
937 
938         Iterator itobj = getxWikiObjects().keySet().iterator();
939         while (itobj.hasNext()) {
940             String name = (String) itobj.next();
941             Vector bobjects = getObjects(name);
942             Vector newobjects = new Vector();
943             newobjects.setSize(bobjects.size());
944             for (int i=0;i<bobjects.size();i++) {
945                 BaseObject oldobject = (BaseObject) getObject(name, i);
946                 if (oldobject!=null)
947                 {
948                     BaseClass baseclass = oldobject.getxWikiClass(context);
949                     BaseObject newobject = (BaseObject) baseclass.fromMap(eform.getObject(baseclass.getName() + "_" + i), oldobject);
950                     newobject.setNumber(oldobject.getNumber());
951                     newobject.setName(getFullName());
952                     newobjects.set(newobject.getNumber(), newobject);
953                 }
954             }
955             getxWikiObjects().put(name, newobjects);
956         }
957     }
958 
959     /*
960     public void readFromTemplate(EditForm eform, XWikiContext context) throws XWikiException {
961     // Get the class from the template
962     String template = eform.getTemplate();
963     if ((template!=null)&&(!template.equals(""))) {
964     if (template.indexOf('.')==-1) {
965     template = getWeb() + "." + template;
966     }
967     XWiki xwiki = context.getWiki();
968     XWikiDocument templatedoc = xwiki.getDocument(template, context);
969     if (templatedoc.isNew()) {
970     Object[] args = { template, getFullName() };
971     throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_APP_TEMPLATE_DOES_NOT_EXIST,
972     "Template document {0} does not exist when adding to document {1}", null, args);
973     } else {
974     setTemplate(template);
975     mergexWikiObjects(templatedoc);
976     }
977     }
978     }
979     */
980 
981     public void readFromTemplate(PrepareEditForm eform, XWikiContext context) throws XWikiException {
982         String template = eform.getTemplate();
983         readFromTemplate(template, context);
984     }
985 
986     public void readFromTemplate(String template, XWikiContext context) throws XWikiException {
987         if ((template!=null)&&(!template.equals(""))) {
988             String content = getContent();
989             if ((!content.equals("\n"))&&(!content.equals(""))&&!isNew()) {
990                 Object[] args = { getFullName() };
991                 throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_APP_DOCUMENT_NOT_EMPTY,
992                         "Cannot add a template to document {0} because it already has content", null, args);
993             } else {
994 
995                 if (template.indexOf('.')==-1) {
996                     template = getWeb() + "." + template;
997                 }
998                 XWiki xwiki = context.getWiki();
999                 XWikiDocument templatedoc = xwiki.getDocument(template, context);
1000                if (templatedoc.isNew()) {
1001                    Object[] args = { template, getFullName() };
1002                    throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_APP_TEMPLATE_DOES_NOT_EXIST,
1003                            "Template document {0} does not exist when adding to document {1}", null, args);
1004                } else {
1005                    setTemplate(template);
1006                    setContent(templatedoc.getContent());
1007                    if ((getParent()==null)||(getParent().equals(""))) {
1008                        String tparent = templatedoc.getParent();
1009                        if (tparent!=null)
1010                            setParent(tparent);
1011                    }
1012
1013                    if (isNew()) {
1014                        // We might have received the object from the cache
1015                        // and the templace objects might have been copied already
1016                        // we need to remove them
1017                        setxWikiObjects(new HashMap());
1018                    }
1019                    // Merge the external objects
1020                    // Currently the choice is not to merge the base class and object because it is not
1021                    // the prefered way of using external classes and objects.
1022                    mergexWikiObjects(templatedoc);
1023                }
1024            }
1025        }
1026    }
1027
1028    public void notify(XWikiNotificationRule rule, XWikiDocument newdoc, XWikiDocument olddoc, int event, XWikiContext context) {
1029        // Do nothing for the moment..
1030        // A usefull thing here would be to look at any instances of a Notification Object
1031        // with email addresses and send an email to warn that the document has been modified..
1032
1033    }
1034
1035    public Object clone() {
1036        XWikiDocument doc = null;
1037        try {
1038            doc = (XWikiDocument) getClass().newInstance();
1039        } catch (Exception e) {
1040            // This should not happen
1041        }
1042
1043        doc.setRCSArchive(getRCSArchive());
1044        doc.setRCSVersion(getRCSVersion());
1045        doc.setAuthor(getAuthor());
1046        doc.setContent(getContent());
1047        doc.setContentDirty(isContentDirty());
1048        doc.setDate(getDate());
1049        doc.setFormat(getFormat());
1050        doc.setFromCache(isFromCache());
1051        doc.setId(getId());
1052        doc.setMeta(getMeta());
1053        doc.setMetaDataDirty(isMetaDataDirty());
1054        doc.setMostRecent(isMostRecent());
1055        doc.setName(getName());
1056        doc.setNew(isNew());
1057        doc.setStore(getStore());
1058        doc.setTemplate(getTemplate());
1059        doc.setWeb(getWeb());
1060        doc.setParent(getParent());
1061        doc.setCreator(getCreator());
1062        doc.setDefaultLanguage(getDefaultLanguage());
1063        doc.setLanguage(getLanguage());
1064        doc.setTranslation(getTranslation());
1065        doc.setxWikiClass((BaseClass)getxWikiClass().clone());
1066        doc.mergexWikiObjects(this);
1067        doc.copyAttachments(this);
1068        return doc;
1069    }
1070
1071    public void copyAttachments(XWikiDocument xWikiSourceDocument) {
1072        Iterator attit = xWikiSourceDocument.getAttachmentList().iterator();
1073        while (attit.hasNext()) {
1074            XWikiAttachment attachment = (XWikiAttachment) attit.next();
1075            XWikiAttachment newattachment = (XWikiAttachment) attachment.clone();
1076            newattachment.setDoc(this);
1077            getAttachmentList().add(newattachment);
1078        }
1079    }
1080
1081    public boolean equals(Object object) {
1082        XWikiDocument doc = (XWikiDocument) object;
1083        if (!getName().equals(doc.getName()))
1084            return false;
1085
1086        if (!getWeb().equals(doc.getWeb()))
1087            return false;
1088
1089        if (!getAuthor().equals(doc.getAuthor()))
1090            return false;
1091
1092        if (!getParent().equals(doc.getParent()))
1093            return false;
1094
1095        if (!getCreator().equals(doc.getCreator()))
1096            return false;
1097
1098        if (!getDefaultLanguage().equals(doc.getDefaultLanguage()))
1099            return false;
1100
1101        if (!getLanguage().equals(doc.getLanguage()))
1102            return false;
1103
1104        if (getTranslation()!=doc.getTranslation())
1105            return false;
1106
1107        if (getDate().getTime() != doc.getDate().getTime())
1108            return false;
1109
1110        if (getCreationDate().getTime() != doc.getCreationDate().getTime())
1111            return false;
1112
1113        if (!getFormat().equals(doc.getFormat()))
1114            return false;
1115
1116        if (!getContent().equals(doc.getContent()))
1117            return false;
1118
1119        if (!getVersion().equals(doc.getVersion()))
1120            return false;
1121
1122        try {
1123            if (!getArchive().equals(doc.getArchive()))
1124                return false;
1125        } catch (XWikiException e) {
1126            return false;
1127        }
1128
1129        if (!getxWikiClass().equals(doc.getxWikiClass()))
1130            return false;
1131
1132        Set list1 = getxWikiObjects().keySet();
1133        Set list2 = doc.getxWikiObjects().keySet();
1134        if (!list1.equals(list2))
1135            return false;
1136
1137        for (Iterator it = list1.iterator();it.hasNext();) {
1138            String name = (String) it.next();
1139            Vector v1 = getObjects(name);
1140            Vector v2 = doc.getObjects(name);
1141            if (v1.size()!=v2.size())
1142                return false;
1143            for (int i=0;i<v1.size();i++) {
1144                if ((v1.get(i)==null)&&(v2.get(i)!=null))
1145                    return false;
1146                if (!v1.get(i).equals(v2.get(i)))
1147                    return false;
1148            }
1149        }
1150
1151
1152        return true;
1153    }
1154
1155    public String toXML(Document doc, XWikiContext context) {
1156        OutputFormat outputFormat = new OutputFormat("", true);
1157        if ((context==null)||(context.getWiki()==null))
1158            outputFormat.setEncoding("UTF-8");
1159        else
1160            outputFormat.setEncoding(context.getWiki().getEncoding());
1161        StringWriter out = new StringWriter();
1162        XMLWriter writer = new XMLWriter( out, outputFormat );
1163        try {
1164            writer.write(doc);
1165            return out.toString();
1166        } catch (IOException e) {
1167            e.printStackTrace();
1168            return "";
1169        }
1170    }
1171
1172    public String getXMLContent(XWikiContext context) throws XWikiException {
1173        XWikiDocument tdoc = getTranslatedDocument(context);
1174        Document doc =  tdoc.toXMLDocument(true, true, false, false, context);
1175        return toXML(doc, context);
1176    }
1177
1178    public String toXML(XWikiContext context) {
1179        Document doc = toXMLDocument(context);
1180        return toXML(doc, context);
1181    }
1182
1183    public String toFullXML(XWikiContext context) {
1184        return toXML(true, false, true, true, context);
1185    }
1186
1187
1188    public void addToZip(ZipOutputStream zos, boolean withVersions, XWikiContext context) throws IOException {
1189        try  {
1190            String zipname = getWeb() + "/" + getName();
1191            String language = getLanguage();
1192            if ((language!=null)&&(!language.equals("")))
1193                zipname += "." + language;
1194            ZipEntry zipentry = new ZipEntry(zipname);
1195            zos.putNextEntry(zipentry);
1196            zos.write(toXML(true, false, true, withVersions, context).getBytes());
1197            zos.closeEntry();
1198        } catch (Exception e) {
1199            e.printStackTrace();
1200        }
1201    }
1202
1203
1204    public void addToZip(ZipOutputStream zos, XWikiContext context) throws IOException {
1205        addToZip(zos, true, context);
1206    }
1207
1208
1209    public String toXML(boolean bWithObjects, boolean bWithRendering,
1210                        boolean bWithAttachmentContent,
1211                        boolean bWithVersions,
1212                        XWikiContext context) {
1213        Document doc = toXMLDocument(bWithObjects, bWithRendering,
1214                bWithAttachmentContent, bWithVersions ,context);
1215        return toXML(doc, context);
1216    }
1217
1218    public Document toXMLDocument(XWikiContext context) {
1219        return toXMLDocument(true, false, false, false, context);
1220    }
1221
1222    public Document toXMLDocument(boolean bWithObjects, boolean bWithRendering,
1223                                  boolean bWithAttachmentContent,
1224                                  boolean bWithVersions,
1225                                  XWikiContext context) {
1226        Document doc = new DOMDocument();
1227        Element docel = new DOMElement("xwikidoc");
1228        doc.setRootElement(docel);
1229
1230        Element el = new DOMElement("web");
1231        el.addText(getWeb());
1232        docel.add(el);
1233
1234        el = new DOMElement("name");
1235        el.addText(getName());
1236        docel.add(el);
1237
1238        el = new DOMElement("language");
1239        el.addText(getLanguage());
1240        docel.add(el);
1241
1242        el = new DOMElement("defaultLanguage");
1243        el.addText(getDefaultLanguage());
1244        docel.add(el);
1245
1246        el = new DOMElement("translation");
1247        el.addText("" + getTranslation());
1248        docel.add(el);
1249
1250        el = new DOMElement("parent");
1251        el.addText(getParent());
1252        docel.add(el);
1253
1254        el = new DOMElement("author");
1255        el.addText(getAuthor());
1256        docel.add(el);
1257
1258        long d = getCreationDate().getTime();
1259        el = new DOMElement("creationDate");
1260        el.addText("" + d);
1261        docel.add(el);
1262
1263        d = getDate().getTime();
1264        el = new DOMElement("date");
1265        el.addText("" + d);
1266        docel.add(el);
1267
1268        el = new DOMElement("version");
1269        el.addText(getVersion());
1270        docel.add(el);
1271
1272        List alist = getAttachmentList();
1273        for (int ai=0;ai<alist.size();ai++) {
1274            XWikiAttachment attach = (XWikiAttachment) alist.get(ai);
1275            docel.add(attach.toXML(bWithAttachmentContent, bWithVersions));
1276        }
1277
1278        if (bWithObjects) {
1279            // Add Class
1280            BaseClass bclass = getxWikiClass();
1281            if (bclass.getFieldList().size()>0) {
1282                docel.add(bclass.toXML(null));
1283            }
1284
1285            // Add Objects
1286            Iterator it = getxWikiObjects().values().iterator();
1287            while (it.hasNext()) {
1288                Vector objects = (Vector) it.next();
1289                for (int i=0;i<objects.size();i++) {
1290                    BaseObject obj = (BaseObject)objects.get(i);
1291                    if (obj!=null) {
1292                        BaseClass objclass = null;
1293