001: /*
002: * Copyright 2007 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.tools.importexport.export.tm;
017:
018: import org.outerj.daisy.tools.importexport.docset.DocumentSet;
019: import org.outerj.daisy.tools.importexport.export.fs.ExportFile;
020: import org.outerj.daisy.tools.importexport.export.config.ExportOptions;
021: import org.outerj.daisy.tools.importexport.export.ExportListener;
022: import org.outerj.daisy.tools.importexport.model.ImpExpVariantKey;
023: import org.outerj.daisy.tools.importexport.model.namespace.ImpExpNamespaces;
024: import org.outerj.daisy.tools.importexport.model.namespace.ImpExpNamespacesXmlizer;
025: import org.outerj.daisy.tools.importexport.model.meta.ImpExpMeta;
026: import org.outerj.daisy.tools.importexport.model.meta.ImpExpMetaXmlizer;
027: import org.outerj.daisy.tools.importexport.model.document.*;
028: import org.outerj.daisy.tools.importexport.ImportExportException;
029: import org.outerj.daisy.tools.importexport.tm.TMConfig;
030: import org.outerj.daisy.tools.importexport.util.XmlizerUtil;
031: import org.outerj.daisy.repository.*;
032: import org.outerj.daisy.repository.namespace.NamespaceNotFoundException;
033: import org.outerj.daisy.repository.namespace.Namespace;
034: import org.outerj.daisy.util.Constants;
035:
036: import java.util.*;
037: import java.util.regex.Matcher;
038: import java.io.OutputStream;
039:
040: /**
041: * An alternative for {@link org.outerj.daisy.tools.importexport.export.Exporter} which
042: * produces a format suitable for translation management purposes (i.e. for exchange
043: * with translation agencies).
044: */
045: public class TMExporter {
046: private DocumentSet documentSet;
047: private ExportFile exportFile;
048: private Repository repository;
049: private ExportOptions options;
050: private ExportListener listener;
051: private Date exportTime;
052: private TMConfig tmConfig;
053: private ImpExpNamespaces impExpNamespaces;
054:
055: public static void run(DocumentSet documentSet,
056: ExportFile exportFile, Date exportTime,
057: Repository repository, ExportOptions options,
058: ExportListener listener, TMConfig tmConfig)
059: throws Exception {
060: new TMExporter(documentSet, exportFile, exportTime, repository,
061: options, listener, tmConfig).run();
062: }
063:
064: private TMExporter(DocumentSet documentSet, ExportFile exportFile,
065: Date exportTime, Repository repository,
066: ExportOptions options, ExportListener listener,
067: TMConfig tmConfig) {
068: this .documentSet = documentSet;
069: this .exportFile = exportFile;
070: this .exportTime = exportTime;
071: this .repository = repository;
072: this .options = options;
073: this .listener = listener;
074: this .tmConfig = tmConfig;
075: this .impExpNamespaces = new ImpExpNamespaces();
076: }
077:
078: private void run() throws Exception {
079: listener.info("Determing set of documents to export.");
080: VariantKey[] variantKeys = documentSet.getDocuments().toArray(
081: new VariantKey[0]);
082: checkInterrupted();
083:
084: // Check all documents belong to same language variant
085: if (variantKeys.length > 0) {
086: long firstLangId = variantKeys[0].getLanguageId();
087: for (int i = 1; i < variantKeys.length; i++) {
088: if (variantKeys[i].getLanguageId() != firstLangId)
089: throw new ImportExportException(
090: "Not all documents in the export set belong to the same language variant.");
091: }
092: }
093: checkInterrupted();
094:
095: // Write documents
096: exportDocuments(variantKeys);
097: checkInterrupted();
098:
099: // Write namespaces
100: try {
101: exportNamespaces();
102: } catch (Throwable e) {
103: throw new ImportExportException(
104: "Error exporting namespaces.", e);
105: }
106: checkInterrupted();
107:
108: // Write meta
109: try {
110: exportMeta();
111: } catch (Throwable e) {
112: throw new ImportExportException(
113: "Error writing export metadata.", e);
114: }
115: }
116:
117: private void exportDocuments(VariantKey[] variantKeys)
118: throws Exception {
119: listener
120: .info("Exporting " + variantKeys.length + " documents.");
121: listener.startDocumentProgress(variantKeys.length);
122: try {
123: for (int i = 0; i < variantKeys.length; i++) {
124: checkInterrupted();
125: listener.updateDocumentProgress(i);
126: exportDocument(variantKeys[i]);
127: }
128: } finally {
129: listener.endDocumentProgress();
130: }
131: }
132:
133: private void exportDocument(VariantKey variantKey) throws Exception {
134: //listener.info("Exporting " + formatVariantKey(variantKey) + " [" + (i + 1) + "/" + variantKeys.length + "]");
135:
136: String branch = repository.getVariantManager().getBranch(
137: variantKey.getBranchId(), false).getName();
138: String language = repository.getVariantManager().getLanguage(
139: variantKey.getLanguageId(), false).getName();
140: ImpExpVariantKey impExpVariantKey = new ImpExpVariantKey(
141: variantKey.getDocumentId(), branch, language);
142:
143: try {
144: // Get the document
145: Document document = repository.getDocument(variantKey,
146: false);
147:
148: // Make sure we have this namespace of this document
149: needNamespaceOfDocId(document.getId(), true);
150:
151: // Check if document is retired
152: if (document.isRetired()) {
153: listener.skippedBecauseRetired(impExpVariantKey);
154: return;
155: }
156:
157: // Get last or live version according to export options
158: Version version;
159: if (options.getExportLastVersion())
160: version = document.getLastVersion();
161: else
162: version = document.getLiveVersion();
163:
164: if (version == null) {
165: listener.skippedBecauseNoLiveVersion(impExpVariantKey);
166: return;
167: }
168:
169: ImpExpDocument impExpDoc = ImpExpDocumentFactory
170: .fromDocument(document, version, repository);
171:
172: // Filter document
173: options.getDocumentExportCustomizer().preExportFilter(
174: impExpDoc);
175:
176: // Write document
177: OutputStream os = null;
178: try {
179: String path = impExpDoc.getId() + "~"
180: + impExpDoc.getBranch() + ".xml";
181: os = exportFile.getOutputStream(path);
182: TMDocumentXmlizer.toXml(impExpDoc, version, os,
183: repository, tmConfig);
184: } finally {
185: if (os != null)
186: os.close();
187: }
188:
189: listener.success(impExpVariantKey);
190: } catch (Throwable e) {
191: listener.failed(impExpVariantKey, e);
192: }
193: }
194:
195: private void exportMeta() throws Exception {
196: listener.info("Writing export meta information.");
197:
198: ImpExpMeta meta = new ImpExpMeta();
199: meta.setDaisyServerVersion(repository.getServerVersion());
200: meta.setExportTime(XmlizerUtil.formatValue(exportTime,
201: ValueType.DATETIME, null));
202: meta.setExportFormat("tm");
203:
204: OutputStream os = null;
205: try {
206: os = exportFile.getOutputStream("info/meta.xml");
207: ImpExpMetaXmlizer.toXml(meta, os);
208: } finally {
209: if (os != null)
210: os.close();
211: }
212: }
213:
214: private void exportNamespaces() throws Exception {
215: listener.info("Exporting namespaces.");
216: OutputStream os = null;
217: try {
218: os = exportFile.getOutputStream("info/namespaces.xml");
219: ImpExpNamespacesXmlizer.toXml(impExpNamespaces, os);
220: } finally {
221: if (os != null)
222: os.close();
223: }
224: }
225:
226: /**
227: * Registers that the namespace of the provided document ID should be
228: * added to the export.
229: *
230: * @param required if true, the namespace is marked as required, i.e. if it is
231: * not present in the target repository upon import,
232: * the import will fail.
233: */
234: protected void needNamespaceOfDocId(String documentId,
235: boolean required) throws NamespaceNotFoundException {
236: Matcher matcher = Constants.DAISY_DOCID_PATTERN
237: .matcher(documentId);
238: if (matcher.matches()) {
239: String namespaceName = matcher.group(2);
240: if (namespaceName != null) {
241: Namespace namespace;
242: try {
243: namespace = repository.getNamespaceManager()
244: .getNamespace(namespaceName);
245: } catch (NamespaceNotFoundException e) {
246: if (required) {
247: throw e;
248: } else {
249: // ignore silently
250: return;
251: }
252: }
253: impExpNamespaces.addNamespace(namespace.getName(),
254: namespace.getFingerprint(), required);
255: }
256: }
257: }
258:
259: private void checkInterrupted() throws ImportExportException {
260: if (listener.isInterrupted()) {
261: throw new ImportExportException(
262: "Export was interrupted on user's request.");
263: }
264: }
265: }
|