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(" ");
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