Source Code Cross Referenced for JRXmlDataSource.java in  » Report » jasperreports-2.0.1 » net » sf » jasperreports » engine » data » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Report » jasperreports 2.0.1 » net.sf.jasperreports.engine.data 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ============================================================================
003:         * GNU Lesser General Public License
004:         * ============================================================================
005:         *
006:         * JasperReports - Free Java report-generating library.
007:         * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008:         * 
009:         * This library is free software; you can redistribute it and/or
010:         * modify it under the terms of the GNU Lesser General Public
011:         * License as published by the Free Software Foundation; either
012:         * version 2.1 of the License, or (at your option) any later version.
013:         * 
014:         * This library is distributed in the hope that it will be useful,
015:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
016:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
017:         * Lesser General Public License for more details.
018:         * 
019:         * You should have received a copy of the GNU Lesser General Public
020:         * License along with this library; if not, write to the Free Software
021:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
022:         * 
023:         * JasperSoft Corporation
024:         * 303 Second Street, Suite 450 North
025:         * San Francisco, CA 94107
026:         * http://www.jaspersoft.com
027:         */
028:
029:        /*
030:         * Contributors:
031:         * Tim Thomas - tthomas48@users.sourceforge.net 
032:         */
033:        package net.sf.jasperreports.engine.data;
034:
035:        import java.io.File;
036:        import java.io.FileInputStream;
037:        import java.io.InputStream;
038:        import java.math.BigDecimal;
039:        import java.math.BigInteger;
040:        import java.util.Date;
041:        import java.util.Locale;
042:        import java.util.TimeZone;
043:
044:        import net.sf.jasperreports.engine.JRException;
045:        import net.sf.jasperreports.engine.JRField;
046:        import net.sf.jasperreports.engine.JRRewindableDataSource;
047:        import net.sf.jasperreports.engine.design.JRDesignField;
048:        import net.sf.jasperreports.engine.util.JRDateLocaleConverter;
049:        import net.sf.jasperreports.engine.util.JRXmlUtils;
050:        import net.sf.jasperreports.engine.util.xml.JRXPathExecuter;
051:        import net.sf.jasperreports.engine.util.xml.JRXPathExecuterUtils;
052:
053:        import org.apache.commons.beanutils.locale.LocaleConvertUtilsBean;
054:        import org.w3c.dom.Document;
055:        import org.w3c.dom.Node;
056:        import org.w3c.dom.NodeList;
057:        import org.xml.sax.InputSource;
058:
059:        /**
060:         * XML data source implementation that allows to access the data from a xml
061:         * document using XPath expressions.
062:         * <p>
063:         * The data source is constructed around a node set (record set) selected
064:         * by an XPath expression from the xml document.
065:         * </p>
066:         * <p>
067:         * Each field can provide an additional XPath expresion that will be used to
068:         * select its value. This expression must be specified using the "fieldDescription"
069:         * element of the field. The expression is evaluated in the context of the current
070:         * node thus the expression should be relative to the current node.
071:         * </p>
072:         * <p>
073:         * To support subreports, sub data sources can be created. There are two different methods 
074:         * for creating sub data sources. The first one allows to create a sub data source rooted 
075:         * at the current node. The current node can be seen as a new document around which the 
076:         * sub data source is created. The second method allows to create a sub data source that
077:         * is rooted at the same document that is used by the data source but uses a different 
078:         * XPath select expression. 
079:         * </p>
080:         * <p>
081:         * Example:
082:         * <pre>
083:         * &lt;A&gt;
084:         * 	&lt;B id="0"&gt;
085:         * 		&lt;C&gt;
086:         * 		&lt;C&gt;
087:         * 	&lt;/B&gt;
088:         * 	&lt;B id="1"&gt;
089:         * 		&lt;C&gt;
090:         * 		&lt;C&gt;
091:         * 	&lt;/B&gt;
092:         * 	&lt;D id="3"&gt;
093:         * 		&lt;E&gt;
094:         * 		&lt;E&gt;
095:         * 	&lt;/D&gt;
096:         * &lt;/A&gt;
097:         * </pre>
098:         * <p>
099:         * Data source creation
100:         * <ul>
101:         * <li>new JRXmlDataSource(document, "/A/B") - creates a data source with two nodes of type /A/B
102:         * <li>new JRXmlDataSource(document, "/A/D") - creates a data source with two nodes of type /A/D
103:         * </ul>
104:         * Field selection
105:         * <ul>
106:         * <li>@id - will select the "id" attribute from the current node
107:         * <li>C - will select the value of the first node of type C under the current node. 
108:         * </ul>
109:         * Sub data source creation
110:         * <ul>
111:         * <li>"((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).subDataSource("/B/C")
112:         * 	- in the context of the node B, creates a data source with elements of type /B/C
113:         * <li>"((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURCE}).dataSource("/A/D")
114:         * 	- creates a data source with elements of type /A/D
115:         * </ul>
116:         * </p>
117:         * <p>
118:         * Generally the full power of XPath expression is available. As an example, "/A/B[@id > 0"] will select all the
119:         * nodes of type /A/B having the id greater than 0. 
120:         * You'll find a short XPath tutorial <a href="http://www.zvon.org/xxl/XPathTutorial/General/examples.html" target="_blank">here</a>.
121:         * 
122:         * </p>
123:         * <p>
124:         * Note on performance. Due to the fact that all the XPath expression are interpreted the
125:         * data source performance is not great. For the cases where more speed is required,
126:         * consider implementing a custom data source that directly accesses the Document through the DOM API. 
127:         * </p>
128:         * @author Peter Severin (peter_p_s@sourceforge.net, contact@jasperassistant.com)
129:         * @version $Id: JRXmlDataSource.java 1790 2007-07-26 10:45:46Z lucianc $
130:         * @see JRXPathExecuterUtils
131:         */
132:        public class JRXmlDataSource implements  JRRewindableDataSource {
133:
134:            // the xml document
135:            private Document document;
136:
137:            // the XPath select expression that gives the nodes to iterate
138:            private String selectExpression;
139:
140:            // the node list
141:            private NodeList nodeList;
142:
143:            // the node list length
144:            private int nodeListLength;
145:
146:            // the current node
147:            private Node currentNode;
148:
149:            // current node index
150:            private int currentNodeIndex = -1;
151:
152:            private final JRXPathExecuter xPathExecuter;
153:
154:            private LocaleConvertUtilsBean convertBean = null;
155:
156:            private Locale locale = null;
157:            private String datePattern = null;
158:            private String numberPattern = null;
159:            private TimeZone timeZone = null;
160:
161:            // -----------------------------------------------------------------
162:            // Constructors
163:
164:            /**
165:             * Creates the data source by parsing the xml document from the given file.
166:             * The data source will contain exactly one record consisting of the document node itself.
167:             * 
168:             * @param document the document
169:             * @throws JRException if the data source cannot be created
170:             */
171:            public JRXmlDataSource(Document document) throws JRException {
172:                this (document, ".");
173:            }
174:
175:            /**
176:             * Creates the data source by parsing the xml document from the given file.
177:             * An additional XPath expression specifies the select criteria that produces the 
178:             * nodes (records) for the data source.
179:             * 
180:             * @param document the document
181:             * @param selectExpression the XPath select expression
182:             * @throws JRException if the data source cannot be created
183:             */
184:            public JRXmlDataSource(Document document, String selectExpression)
185:                    throws JRException {
186:                this .document = document;
187:                this .selectExpression = selectExpression;
188:
189:                this .xPathExecuter = JRXPathExecuterUtils.getXPathExecuter();
190:
191:                moveFirst();
192:            }
193:
194:            /**
195:             * Creates the data source by parsing the xml document from the given input stream.
196:             *  
197:             * @param in the input stream
198:             * @see JRXmlDataSource#JRXmlDataSource(Document) 
199:             */
200:            public JRXmlDataSource(InputStream in) throws JRException {
201:                this (in, ".");
202:            }
203:
204:            /**
205:             * Creates the data source by parsing the xml document from the given input stream.
206:             * 
207:             * @see JRXmlDataSource#JRXmlDataSource(InputStream) 
208:             * @see JRXmlDataSource#JRXmlDataSource(Document, String) 
209:             */
210:            public JRXmlDataSource(InputStream in, String selectExpression)
211:                    throws JRException {
212:                this (JRXmlUtils.parse(new InputSource(in)), selectExpression);
213:            }
214:
215:            /**
216:             * Creates the data source by parsing the xml document from the given system identifier (URI).
217:             * <p>If the system identifier is a URL, it must be full resolved.</p>
218:             * 
219:             * @param uri the system identifier
220:             * @see JRXmlDataSource#JRXmlDataSource(Document) 
221:             */
222:            public JRXmlDataSource(String uri) throws JRException {
223:                this (uri, ".");
224:            }
225:
226:            /**
227:             * Creates the data source by parsing the xml document from the given system identifier (URI).
228:             * 
229:             * @see JRXmlDataSource#JRXmlDataSource(String) 
230:             * @see JRXmlDataSource#JRXmlDataSource(Document, String) 
231:             */
232:            public JRXmlDataSource(String uri, String selectExpression)
233:                    throws JRException {
234:                this (JRXmlUtils.parse(uri), selectExpression);
235:            }
236:
237:            /**
238:             * Creates the data source by parsing the xml document from the given file.
239:             * 
240:             * @param file the file
241:             * @see JRXmlDataSource#JRXmlDataSource(Document) 
242:             */
243:            public JRXmlDataSource(File file) throws JRException {
244:                this (file, ".");
245:            }
246:
247:            /**
248:             * Creates the data source by parsing the xml document from the given file.
249:             * 
250:             * @see JRXmlDataSource#JRXmlDataSource(File) 
251:             * @see JRXmlDataSource#JRXmlDataSource(Document, String) 
252:             */
253:            public JRXmlDataSource(File file, String selectExpression)
254:                    throws JRException {
255:                this (JRXmlUtils.parse(file), selectExpression);
256:            }
257:
258:            // -----------------------------------------------------------------
259:            // Implementation
260:
261:            /*
262:             * (non-Javadoc)
263:             * 
264:             * @see net.sf.jasperreports.engine.JRRewindableDataSource#moveFirst()
265:             */
266:            public void moveFirst() throws JRException {
267:                if (document == null)
268:                    throw new JRException("document cannot be null");
269:                if (selectExpression == null)
270:                    throw new JRException("selectExpression cannot be null");
271:
272:                currentNode = null;
273:                currentNodeIndex = -1;
274:                nodeListLength = 0;
275:                nodeList = xPathExecuter.selectNodeList(document,
276:                        selectExpression);
277:                nodeListLength = nodeList.getLength();
278:            }
279:
280:            /*
281:             * (non-Javadoc)
282:             * 
283:             * @see net.sf.jasperreports.engine.JRDataSource#next()
284:             */
285:            public boolean next() {
286:                if (currentNodeIndex == nodeListLength - 1)
287:                    return false;
288:
289:                currentNode = nodeList.item(++currentNodeIndex);
290:                return true;
291:            }
292:
293:            /*
294:             * (non-Javadoc)
295:             * 
296:             * @see net.sf.jasperreports.engine.JRDataSource#getFieldValue(net.sf.jasperreports.engine.JRField)
297:             */
298:            public Object getFieldValue(JRField jrField) throws JRException {
299:                if (currentNode == null)
300:                    return null;
301:
302:                String expression = jrField.getDescription();
303:                if (expression == null || expression.length() == 0)
304:                    return null;
305:
306:                Object value = null;
307:
308:                Class valueClass = jrField.getValueClass();
309:
310:                if (Object.class != valueClass) {
311:                    Object selectedObject = xPathExecuter.selectObject(
312:                            currentNode, expression);
313:
314:                    if (selectedObject != null) {
315:                        if (selectedObject instanceof  Node) {
316:                            String text = getText((Node) selectedObject);
317:                            value = convertStringValue(text, valueClass);
318:                        } else if (selectedObject instanceof  Boolean
319:                                && valueClass.equals(Boolean.class)) {
320:                            value = selectedObject;
321:                        } else if (selectedObject instanceof  Number
322:                                && Number.class.isAssignableFrom(valueClass)) {
323:                            value = convertNumber((Number) selectedObject,
324:                                    valueClass);
325:                        } else {
326:                            String text = selectedObject.toString();
327:                            value = convertStringValue(text, valueClass);
328:                        }
329:                    }
330:                }
331:                return value;
332:            }
333:
334:            protected Object convertStringValue(String text, Class valueClass) {
335:                Object value = null;
336:                if (String.class.equals(valueClass)) {
337:                    value = text;
338:                } else if (Number.class.isAssignableFrom(valueClass)) {
339:                    value = getConvertBean().convert(text.trim(), valueClass,
340:                            locale, numberPattern);
341:                } else if (Date.class.isAssignableFrom(valueClass)) {
342:                    value = getConvertBean().convert(text.trim(), valueClass,
343:                            locale, datePattern);
344:                } else if (Boolean.class.equals(valueClass)) {
345:                    value = Boolean.valueOf(text);
346:                }
347:                return value;
348:            }
349:
350:            protected Object convertNumber(Number number, Class valueClass)
351:                    throws JRException {
352:                Number value = null;
353:                if (valueClass.equals(Byte.class)) {
354:                    value = new Byte(number.byteValue());
355:                } else if (valueClass.equals(Short.class)) {
356:                    value = new Short(number.shortValue());
357:                } else if (valueClass.equals(Integer.class)) {
358:                    value = new Integer(number.intValue());
359:                } else if (valueClass.equals(Long.class)) {
360:                    value = new Long(number.longValue());
361:                } else if (valueClass.equals(Float.class)) {
362:                    value = new Float(number.floatValue());
363:                } else if (valueClass.equals(Double.class)) {
364:                    value = new Double(number.doubleValue());
365:                } else if (valueClass.equals(BigInteger.class)) {
366:                    value = BigInteger.valueOf(number.longValue());
367:                } else if (valueClass.equals(BigDecimal.class)) {
368:                    value = new BigDecimal(Double
369:                            .toString(number.doubleValue()));
370:                } else {
371:                    throw new JRException("Unknown number class "
372:                            + valueClass.getName());
373:                }
374:                return value;
375:            }
376:
377:            /**
378:             * Creates a sub data source using the current node (record) as the root
379:             * of the document. An additional XPath expression specifies the select criteria applied to
380:             * this new document and that produces the nodes (records) for the data source.
381:             * 
382:             * @param selectExpr the XPath select expression
383:             * @return the xml sub data source
384:             * @throws JRException if the sub data source couldn't be created
385:             * @see JRXmlDataSource#JRXmlDataSource(Document, String)
386:             */
387:            public JRXmlDataSource subDataSource(String selectExpr)
388:                    throws JRException {
389:                // create a new document from the current node
390:                Document doc = subDocument();
391:                JRXmlDataSource subDataSource = new JRXmlDataSource(doc,
392:                        selectExpr);
393:                subDataSource.setLocale(locale);
394:                subDataSource.setDatePattern(datePattern);
395:                subDataSource.setNumberPattern(numberPattern);
396:                subDataSource.setTimeZone(timeZone);
397:                return subDataSource;
398:            }
399:
400:            /**
401:             * Creates a sub data source using the current node (record) as the root
402:             * of the document. The data source will contain exactly one record consisting 
403:             * of the document node itself.
404:             * 
405:             * @return the xml sub data source
406:             * @throws JRException if the data source cannot be created
407:             * @see JRXmlDataSource#subDataSource(String)
408:             * @see JRXmlDataSource#JRXmlDataSource(Document)
409:             */
410:            public JRXmlDataSource subDataSource() throws JRException {
411:                return subDataSource(".");
412:            }
413:
414:            /**
415:             * Creates a document using the current node as root.
416:             * 
417:             * @return a document having the current node as root
418:             * @throws JRException
419:             */
420:            public Document subDocument() throws JRException {
421:                if (currentNode == null) {
422:                    throw new JRException(
423:                            "No node available. Iterate or rewind the data source.");
424:                }
425:
426:                // create a new document from the current node
427:                Document doc = JRXmlUtils.createDocument(currentNode);
428:                return doc;
429:            }
430:
431:            /**
432:             * Creates a sub data source using as root document the document used by "this" data source.
433:             * An additional XPath expression specifies the select criteria applied to
434:             * this document and that produces the nodes (records) for the data source.
435:             * 
436:             * @param selectExpr the XPath select expression
437:             * @return the xml sub data source
438:             * @throws JRException if the sub data source couldn't be created
439:             * @see JRXmlDataSource#JRXmlDataSource(Document, String)
440:             */
441:            public JRXmlDataSource dataSource(String selectExpr)
442:                    throws JRException {
443:                JRXmlDataSource subDataSource = new JRXmlDataSource(document,
444:                        selectExpr);
445:                subDataSource.setLocale(locale);
446:                subDataSource.setDatePattern(datePattern);
447:                subDataSource.setNumberPattern(numberPattern);
448:                subDataSource.setTimeZone(timeZone);
449:                return subDataSource;
450:            }
451:
452:            /**
453:             * Creates a sub data source using as root document the document used by "this" data source.
454:             * The data source will contain exactly one record consisting  of the document node itself.
455:             * 
456:             * @return the xml sub data source
457:             * @throws JRException if the data source cannot be created
458:             * @see JRXmlDataSource#dataSource(String)
459:             * @see JRXmlDataSource#JRXmlDataSource(Document)
460:             */
461:            public JRXmlDataSource dataSource() throws JRException {
462:                return dataSource(".");
463:            }
464:
465:            /**
466:             * Return the text that a node contains. This routine:
467:             * <ul>
468:             * <li>Ignores comments and processing instructions.
469:             * <li>Concatenates TEXT nodes, CDATA nodes, and the results of recursively
470:             * processing EntityRef nodes.
471:             * <li>Ignores any element nodes in the sublist. (Other possible options
472:             * are to recurse into element sublists or throw an exception.)
473:             * </ul>
474:             * 
475:             * @param node a DOM node
476:             * @return a String representing node contents or null
477:             */
478:            public String getText(Node node) {
479:                if (!node.hasChildNodes())
480:                    return node.getNodeValue();
481:
482:                StringBuffer result = new StringBuffer();
483:
484:                NodeList list = node.getChildNodes();
485:                for (int i = 0; i < list.getLength(); i++) {
486:                    Node subnode = list.item(i);
487:                    if (subnode.getNodeType() == Node.TEXT_NODE) {
488:                        String value = subnode.getNodeValue();
489:                        if (value != null)
490:                            result.append(value);
491:                    } else if (subnode.getNodeType() == Node.CDATA_SECTION_NODE) {
492:                        String value = subnode.getNodeValue();
493:                        if (value != null)
494:                            result.append(value);
495:                    } else if (subnode.getNodeType() == Node.ENTITY_REFERENCE_NODE) {
496:                        // Recurse into the subtree for text
497:                        // (and ignore comments)
498:                        String value = getText(subnode);
499:                        if (value != null)
500:                            result.append(value);
501:                    }
502:                }
503:
504:                return result.toString();
505:            }
506:
507:            public static void main(String[] args) throws Exception {
508:                JRXmlDataSource ds = new JRXmlDataSource(new FileInputStream(
509:                        "northwind.xml"), "/Northwind/Customers");
510:                JRDesignField field = new JRDesignField();
511:                field.setDescription("CustomerID");
512:                field.setValueClass(String.class);
513:
514:                ds.next();
515:                String v = (String) ds.getFieldValue(field);
516:                System.out.println(field.getDescription() + "=" + v);
517:
518:                JRXmlDataSource subDs = ds.dataSource("/Northwind/Orders");
519:
520:                JRDesignField field1 = new JRDesignField();
521:                field1.setDescription("OrderID");
522:                field1.setValueClass(String.class);
523:
524:                subDs.next();
525:                String v1 = (String) subDs.getFieldValue(field1);
526:                System.out.println(field1.getDescription() + "=" + v1);
527:
528:            }
529:
530:            protected LocaleConvertUtilsBean getConvertBean() {
531:                if (convertBean == null) {
532:                    convertBean = new LocaleConvertUtilsBean();
533:                    if (locale != null) {
534:                        convertBean.setDefaultLocale(locale);
535:                        convertBean.deregister();
536:                        //convertBean.lookup();
537:                    }
538:                    convertBean.register(new JRDateLocaleConverter(timeZone),
539:                            java.util.Date.class, locale);
540:                }
541:                return convertBean;
542:            }
543:
544:            public Locale getLocale() {
545:                return locale;
546:            }
547:
548:            public void setLocale(Locale locale) {
549:                this .locale = locale;
550:                convertBean = null;
551:            }
552:
553:            public String getDatePattern() {
554:                return datePattern;
555:            }
556:
557:            public void setDatePattern(String datePattern) {
558:                this .datePattern = datePattern;
559:                convertBean = null;
560:            }
561:
562:            public String getNumberPattern() {
563:                return numberPattern;
564:            }
565:
566:            public void setNumberPattern(String numberPattern) {
567:                this .numberPattern = numberPattern;
568:                convertBean = null;
569:            }
570:
571:            public TimeZone getTimeZone() {
572:                return timeZone;
573:            }
574:
575:            public void setTimeZone(TimeZone timeZone) {
576:                this.timeZone = timeZone;
577:                convertBean = null;
578:            }
579:
580:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.