1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one *
3 * or more contributor license agreements. See the NOTICE file *
4 * distributed with this work for additional information *
5 * regarding copyright ownership. The ASF licenses this file *
6 * to you under the Apache License, Version 2.0 (the *
7 * "License"); you may not use this file except in compliance *
8 * with the License. You may obtain a copy of the License at *
9 * *
10 * http://www.apache.org/licenses/LICENSE-2.0 *
11 * *
12 * Unless required by applicable law or agreed to in writing, *
13 * software distributed under the License is distributed on an *
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
15 * KIND, either express or implied. See the License for the *
16 * specific language governing permissions and limitations *
17 * under the License. *
18 */
19 package org.apache.rat.api;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.io.Reader;
25 import java.nio.charset.Charset;
26 import java.util.SortedSet;
27
28 import org.apache.rat.analysis.TikaProcessor;
29 import org.apache.rat.document.DocumentName;
30 import org.apache.rat.document.DocumentNameMatcher;
31
32 /**
33 * The representation of a document being scanned.
34 */
35 public abstract class Document implements Comparable<Document> {
36
37 /**
38 * An enumeration of document types.
39 */
40 public enum Type {
41 /** An archive type document. */
42 ARCHIVE,
43 /** A binary file. */
44 BINARY,
45 /** A generated document that is ignored. */
46 IGNORED,
47 /** A notice document (e.g. LICENSE file). */
48 NOTICE,
49 /** A standard document. */
50 STANDARD,
51 /** An unknown document type. */
52 UNKNOWN
53 }
54
55 /** The path matcher used by this document */
56 protected final DocumentNameMatcher nameMatcher;
57 /** The metadata for this document */
58 private final MetaData metaData;
59 /** The fully qualified name of this document */
60 protected final DocumentName name;
61
62 /**
63 * Creates an instance.
64 * @param name the native NameSet of the resource.
65 * @param nameMatcher the document name matcher to filter directories/files.
66 */
67 protected Document(final DocumentName name, final DocumentNameMatcher nameMatcher) {
68 this.name = name;
69 this.nameMatcher = nameMatcher;
70 this.metaData = new MetaData();
71 }
72
73 /**
74 * Gets the name of the current document.
75 * @return the name of the current document.
76 */
77 public final DocumentName getName() {
78 return name;
79 }
80
81 /**
82 * Gets the file filter this document was created with.
83 * @return the file filter this document was created with.
84 */
85 public final DocumentNameMatcher getNameMatcher() {
86 return nameMatcher;
87 }
88
89 @Override
90 public int compareTo(final Document doc) {
91 return name.compareTo(doc.name);
92 }
93
94 @Override
95 public int hashCode() {
96 return name.hashCode();
97 }
98
99 @Override
100 public boolean equals(final Object obj) {
101 if (!(obj instanceof Document)) {
102 return false;
103 }
104 return name.equals(((Document) obj).name);
105 }
106
107 /**
108 * Reads the contents of this document and
109 * relies on the charset detection of the underlying Tika processor.
110 *
111 * @return <code>Reader</code> not null
112 * @throws IOException if this document cannot be read.
113 */
114 public Reader reader() throws IOException {
115 final Charset charset = getMetaData().getCharset();
116 if (charset == null) {
117 throw new IOException(
118 String.format(
119 "No charset detected for document `%s`",
120 getName()));
121 }
122
123 return new InputStreamReader(
124 TikaProcessor.markSupportedInputStream(inputStream()),
125 charset);
126 }
127
128 /**
129 * Streams the document's contents.
130 * @return a non-null input stream of the document.
131 * @throws IOException when stream could not be opened.
132 */
133 public abstract InputStream inputStream() throws IOException;
134
135 /**
136 * Gets data describing this resource.
137 * @return a non-null MetaData object.
138 */
139 public final MetaData getMetaData() {
140 return metaData;
141 }
142
143 /**
144 * Checks if document is ignored or not.
145 * @return {@code true} if the document is of type {@code IGNORED}.
146 */
147 public final boolean isIgnored() {
148 return Type.IGNORED == metaData.getDocumentType();
149 }
150
151 /**
152 * Representations suitable for logging.
153 * @return a <code>String</code> representation
154 * of this object.
155 */
156 @Override
157 public String toString() {
158 return String.format("%s( name = %s metaData = %s )", this.getClass().getSimpleName(), getName().localized(), getMetaData());
159 }
160
161 /**
162 * Determines if this document is a directory type.
163 * @return {@code true} if this is a directory.
164 */
165 public abstract boolean isDirectory();
166
167 /**
168 * Gets a sorted set of documents that are children of this document.
169 * @return A sorted set of child Documents. May be empty.
170 */
171 public abstract SortedSet<Document> listChildren();
172 }