1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 package com.sun.star.wizards.web.data;
24 
25 import java.io.File;
26 import java.io.FileNotFoundException;
27 
28 import org.w3c.dom.Node;
29 
30 import com.sun.star.beans.PropertyValue;
31 import com.sun.star.document.MacroExecMode;
32 import com.sun.star.document.UpdateDocMode;
33 import com.sun.star.document.XDocumentProperties;
34 import com.sun.star.document.XDocumentPropertiesSupplier;
35 import com.sun.star.frame.XComponentLoader;
36 import com.sun.star.frame.XDesktop;
37 import com.sun.star.lang.XComponent;
38 import com.sun.star.lang.XMultiServiceFactory;
39 import com.sun.star.uno.UnoRuntime;
40 import com.sun.star.util.DateTime;
41 import com.sun.star.wizards.common.Desktop;
42 import com.sun.star.wizards.common.FileAccess;
43 import com.sun.star.wizards.common.JavaTools;
44 import com.sun.star.wizards.common.Properties;
45 import com.sun.star.wizards.common.PropertyNames;
46 import com.sun.star.wizards.common.XMLHelper;
47 import com.sun.star.wizards.common.XMLProvider;
48 import com.sun.star.wizards.document.OfficeDocument;
49 import com.sun.star.wizards.ui.event.Task;
50 
51 /**
52  * About the member fields Title, Decription and Author:
53  * There is an ambiguicy in handling these fields.
54  * On the one hand, the user can set those fields to a custom value,
55  * relevant only for the web-wizard.
56  * On the other-hand, the web-wizard can read those fields automatically
57  * from SO documents.
58  * In order to avoid conflict by saving, I use two fields: "cp_title", which
59  * should be read from the configuratin (saved session), and "title" which is
60  * the value read from the document.
61  * The *cp_title* "overrides" *title*, if exists. if not, *title* is used.
62  * The same is valid for *description* and *author*.
63  * @author  rpiterman
64  */
65 public class CGDocument extends ConfigSetItem implements XMLProvider
66 {
67 
68     public static final int PAGE_TYPE_UNKNOWN = 0;
69     public static final int PAGE_TYPE_PAGE = 1;
70     public static final int PAGE_TYPE_SLIDE = 2;
71     public String cp_Title = PropertyNames.EMPTY_STRING;
72     public String cp_Description = PropertyNames.EMPTY_STRING;
73     public String cp_URL;
74     public String cp_Author = PropertyNames.EMPTY_STRING;
75     public String cp_Exporter;
76     /**
77      * the destination filename to which this
78      * document will be exported to.
79      */
80     public String localFilename = PropertyNames.EMPTY_STRING;
81     public String urlFilename = PropertyNames.EMPTY_STRING;
82     public String title = PropertyNames.EMPTY_STRING;
83     public String description = PropertyNames.EMPTY_STRING;
84     public String author = PropertyNames.EMPTY_STRING;
85     public DateTime createDate;
86     public DateTime updateDate;
87     public int sizeBytes = -1;
88     public int pages = -1;
89     /**
90      * The contents subdirectory name in which the document is in.
91      * This subdirectory will be created in the content's "docs"
92      * subdirectory.
93      */
94     public String dirName;
95     /**
96      * contains an identifier of the type of this document.
97      */
98     public String appType;
99     public PropertyValue[] mediaDescriptor;
100     /**
101      * Is this document an original SO Document (different versions).
102      */
103     public boolean isSODocument;
104     /**
105      * can this document be opend through SO?
106      */
107     public boolean isSOOpenable;
108     /**
109      * This flag is set to true after the validate method is called.
110      */
111     public boolean valid = false;
112     public String targetTypeName;
113 
CGDocument()114     public CGDocument()
115     {
116     }
117 
CGDocument(String url, XMultiServiceFactory xmsf, Task task)118     public CGDocument(String url, XMultiServiceFactory xmsf, Task task) throws Exception
119     {
120         cp_URL = getSettings().getFileAccess(xmsf).getURL(url);
121         if (task == null)
122         {
123             task = new Task(PropertyNames.EMPTY_STRING, PropertyNames.EMPTY_STRING, 5);
124         }
125         validate(xmsf, task);
126     }
127 
128     /**
129      * the task will advance 5 times during validate.
130      * @param xmsf
131      * @param task
132      * @throws Exception
133      */
validate(XMultiServiceFactory xmsf, Task task)134     public void validate(XMultiServiceFactory xmsf, Task task)
135             throws FileNotFoundException,
136             IllegalArgumentException,
137             Exception
138     {
139 
140         if (!getSettings().getFileAccess(xmsf).exists(cp_URL, false))
141         {
142             throw new FileNotFoundException("The given URL does not point to a file");
143         }
144         if (getSettings().getFileAccess(xmsf).isDirectory(cp_URL))
145         {
146             throw new IllegalArgumentException("The given URL points to a directory");        //create a TypeDetection service
147         }
148         mediaDescriptor = OfficeDocument.getFileMediaDecriptor(xmsf, cp_URL);
149 
150         task.advance(true); //1
151 
152         //System.out.println(Properties.getPropertyValue(mediaDescriptor,"UIName"));
153 
154         analyzeFileType(mediaDescriptor);
155 
156         task.advance(true); //2
157 
158         String path = getSettings().getFileAccess(xmsf).getPath(cp_URL, PropertyNames.EMPTY_STRING);
159         localFilename = FileAccess.getFilename(path, File.separator);
160 
161         /* if the type is a star office convertable document
162          * We try to open the document to get some properties
163          */
164 
165         XDocumentProperties xProps = null;
166 
167         task.advance(true); //3
168 
169         if (isSOOpenable)
170         { // for documents which are openable through SO, use DocumentProperties service.
171             XDesktop desktop = Desktop.getDesktop(xmsf);
172             PropertyValue[] props = new PropertyValue[3];
173             props[0] = Properties.createProperty("Hidden", Boolean.TRUE);
174             props[1] = Properties.createProperty("MacroExecutionMode", new Short(MacroExecMode.NEVER_EXECUTE));
175             props[2] = Properties.createProperty("UpdateDocMode", new Short(UpdateDocMode.NO_UPDATE));
176             XComponent component = UnoRuntime.queryInterface(XComponentLoader.class, desktop).loadComponentFromURL(cp_URL, "_default", 0, props);
177             xProps = UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, component).getDocumentProperties();
178         }
179 
180         task.advance(true); //4
181 
182         //now use the object to read some document properties.
183         if (xProps != null)
184         {
185             title = xProps.getTitle();
186             description = xProps.getDescription();
187             author = xProps.getAuthor();
188             createDate = xProps.getCreationDate();
189             updateDate = xProps.getModificationDate();
190         }
191         else
192         { //get some information from OS.
193             title = localFilename;
194             updateDate = getSettings().getFileAccess(xmsf).getLastModified(cp_URL);
195         }
196 
197         task.advance(true); //5
198 
199         valid = true;
200 
201         if (cp_Title.equals(PropertyNames.EMPTY_STRING))
202         {
203             cp_Title = title;
204         }
205         if (cp_Title.equals(PropertyNames.EMPTY_STRING))
206         {
207             cp_Title = localFilename;
208         }
209         if (cp_Description.equals(PropertyNames.EMPTY_STRING))
210         {
211             cp_Description = description;
212         }
213         if (cp_Author.equals(PropertyNames.EMPTY_STRING))
214         {
215             cp_Author = author;
216         }
217         if (cp_Exporter == null || cp_Exporter.equals(PropertyNames.EMPTY_STRING))
218         {
219             cp_Exporter = (String) getSettings().cp_Exporters.getKey(
220                     getSettings().getExporters(appType)[0]);
221         }
222     }
223 
224     /**
225      * Analyzes a type-detection string, returned from the TypeDetection service,
226      * and sets the appType, isSOOpenable and isSODocument members.
227      */
analyzeFileType(PropertyValue[] mediaDesc)228     private void analyzeFileType(PropertyValue[] mediaDesc)
229     {
230 
231         if (mediaDesc == null)
232         {
233         }
234 
235         String media = (mediaDesc == null)
236                 ? PropertyNames.EMPTY_STRING : (String) Properties.getPropertyValue(mediaDescriptor, PropertyNames.PROPERTY_NAME);
237         appType = getDocType(media);
238 
239         //System.out.println(appType);
240 
241         isSOOpenable =
242                 (appType.equals(TypeDetection.WRITER_DOC) || appType.equals(TypeDetection.CALC_DOC) || appType.equals(TypeDetection.IMPRESS_DOC) || appType.equals(TypeDetection.DRAW_DOC)) || appType.equals(TypeDetection.HTML_DOC);
243 
244 //        String[] parts = media.split("_");    // line removed because of compatibility to JDK13
245         String[] parts = JavaTools.ArrayoutofString(media, "_");
246 
247 
248         isSODocument = parts.length >= 2 && isSOOpenable && (parts[1].startsWith("Star"));
249 
250     }
251 
252     /**
253      * @param media is the media description string returned by an UNO TypeDetection object.
254      * @return one of the constants in the interface TypeDetection.
255      *
256      */
getDocType(String media)257     private String getDocType(String media)
258     {
259         if (media.equals(PropertyNames.EMPTY_STRING))
260         {
261             return TypeDetection.NO_TYPE;
262         }
263         if (media.startsWith("writer"))
264         {
265             if (media.startsWith("writer_web_HTML"))
266             {
267                 return TypeDetection.HTML_DOC;
268             }
269             else
270             {
271                 return TypeDetection.WRITER_DOC;
272             }
273         }
274         else if (media.startsWith("calc"))
275         {
276             return TypeDetection.CALC_DOC;
277         }
278         else if (media.startsWith("draw"))
279         {
280             return TypeDetection.DRAW_DOC;
281         }
282         else if (media.startsWith("impress"))
283         {
284             return TypeDetection.IMPRESS_DOC;
285         }
286         else if (media.startsWith("pdf"))
287         {
288             return TypeDetection.PDF_DOC;
289         }
290         else if (media.startsWith("gif") || media.startsWith("jpg"))
291         {
292             return TypeDetection.WEB_GRAPHICS;
293         }
294         else if (media.startsWith("wav"))
295         {
296             return TypeDetection.SOUND_FILE;
297         }
298         else
299         {
300             return TypeDetection.NO_TYPE;
301         }
302     }
303 
createDOM(Node parent)304     public Node createDOM(Node parent)
305     {
306         CGDesign d = getSettings().cp_DefaultSession.cp_Design;
307         CGExporter exp = (CGExporter) getSettings().cp_Exporters.getElement(cp_Exporter);
308 
309         return XMLHelper.addElement(parent, "document",
310                 new String[]
311                 {
312                     "title", "description", "author", "format", "filename", "create-date", "update-date", "pages", "size", "icon", "dir", "fn"
313                 },
314                 new String[]
315                 {
316                     d.cp_DisplayTitle ? cp_Title : PropertyNames.EMPTY_STRING,
317                     d.cp_DisplayDescription ? cp_Description : PropertyNames.EMPTY_STRING,
318                     d.cp_DisplayAuthor ? cp_Author : PropertyNames.EMPTY_STRING,
319                     d.cp_DisplayFileFormat ? getTargetTypeName(exp) : PropertyNames.EMPTY_STRING,
320                     d.cp_DisplayFilename ? localFilename : PropertyNames.EMPTY_STRING,
321                     d.cp_DisplayCreateDate ? createDate() : PropertyNames.EMPTY_STRING,
322                     d.cp_DisplayUpdateDate ? updateDate() : PropertyNames.EMPTY_STRING,
323                     d.cp_DisplayPages && (pages > -1) ? PropertyNames.EMPTY_STRING + pages() : PropertyNames.EMPTY_STRING, //TODO when do i calculate pages?
324                     d.cp_DisplaySize ? sizeKB() : PropertyNames.EMPTY_STRING,//TODO when do i calculate size?
325                     d.cp_DisplayFormatIcon ? getIcon(exp) : PropertyNames.EMPTY_STRING,
326                     dirName, urlFilename
327                 });
328     }
329 
updateDate()330     private String updateDate()
331     {
332         if (this.updateDate == null)
333         {
334             return PropertyNames.EMPTY_STRING;
335         }
336         return getSettings().formatter.formatCreated(this.updateDate);
337     }
338 
createDate()339     private String createDate()
340     {
341         if (this.createDate == null)
342         {
343             return PropertyNames.EMPTY_STRING;
344         }
345         return getSettings().formatter.formatCreated(this.createDate);
346     }
347 
sizeKB()348     private String sizeKB()
349     {
350         if (sizeBytes == -1)
351         {
352             return PropertyNames.EMPTY_STRING;
353         }
354         else
355         {
356             return getSettings().formatter.formatFileSize(sizeBytes);
357         }
358     }
359 
pages()360     private String pages()
361     {
362         return pages == -1 ? PropertyNames.EMPTY_STRING
363                 : JavaTools.replaceSubString(pagesTemplate(), PropertyNames.EMPTY_STRING + pages, "%NUMBER");
364     }
365 
pagesTemplate()366     private String pagesTemplate()
367     {
368         int pagesType = ((CGExporter) getSettings().cp_Exporters.getElement(cp_Exporter)).cp_PageType;
369         switch (pagesType)
370         {
371             case PAGE_TYPE_UNKNOWN:
372                 return PropertyNames.EMPTY_STRING;
373             case PAGE_TYPE_PAGE:
374                 return getSettings().resources[CGSettings.RESOURCE_PAGES_TEMPLATE];
375             case PAGE_TYPE_SLIDE:
376                 return getSettings().resources[CGSettings.RESOURCE_SLIDES_TEMPLATE];
377             default:
378                 return PropertyNames.EMPTY_STRING;
379         }
380     }
381 
getTargetTypeName(CGExporter exp)382     private String getTargetTypeName(CGExporter exp)
383     {
384         return (exp.targetTypeName.equals(PropertyNames.EMPTY_STRING))
385                 ? (String) Properties.getPropertyValue(mediaDescriptor, "UIName")
386                 : exp.targetTypeName;
387     }
388 
getIcon(CGExporter exporter)389     private String getIcon(CGExporter exporter)
390     {
391         return exporter.cp_Icon.equals(PropertyNames.EMPTY_STRING) ? getIcon(this.appType) : exporter.cp_Icon;
392     }
393 
getIcon(String appType)394     private String getIcon(String appType)
395     {
396         //System.out.println("Getting Icon for: " + appType);
397         return appType + ".gif";
398     }
399 
400     /**
401      * This method is used by the DataAware model
402      * and returns the index of the exporter of
403      * this document, <b>in the list of the
404      * exporters available for this type of document</b>
405      * @return
406      */
getExporter()407     public short[] getExporter()
408     {
409         return new short[]
410                 {
411                     getExporterIndex()
412                 };
413     }
414 
415     /**
416      * @see getExporter()
417      */
setExporter(short[] exporter_)418     public void setExporter(short[] exporter_)
419     {
420         Object exp = getSettings().getExporters(appType)[exporter_[0]];
421         cp_Exporter = (String) getSettings().cp_Exporters.getKey(exp);
422     }
423 
424     /**
425      * @see getExporter()
426      * @return
427      */
getExporterIndex()428     private short getExporterIndex()
429     {
430         if (cp_Exporter == null)
431         {
432             return 0;
433         }
434         Object exporter = getSettings().cp_Exporters.getElement(cp_Exporter);
435         Object[] exporters = getSettings().getExporters(appType);
436         for (short i = 0; i < exporters.length; i++)
437         {
438             if (exporters[i] == exporter)
439             {
440                 return i;
441             }
442         }
443         return -1;
444     }
445 
toString()446     public String toString()
447     {
448         return localFilename;
449     }
450 }
451