001/* 002 * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others. 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 * Contributors: 017 * pierre 018 */ 019package org.nuxeo.ecm.platform.csv.export.io; 020 021import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 022import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 023import static org.nuxeo.ecm.platform.csv.export.io.DocumentModelCSVHelper.getList; 024 025import java.io.IOException; 026import java.io.OutputStream; 027import java.util.ArrayList; 028import java.util.Calendar; 029import java.util.Comparator; 030import java.util.List; 031 032import org.apache.commons.csv.CSVPrinter; 033import org.apache.commons.lang3.StringUtils; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.Lock; 036import org.nuxeo.ecm.core.api.model.Property; 037import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 038import org.nuxeo.ecm.core.io.marshallers.csv.AbstractCSVWriter; 039import org.nuxeo.ecm.core.io.marshallers.csv.OutputStreamWithCSVWriter; 040import org.nuxeo.ecm.core.io.registry.Writer; 041import org.nuxeo.ecm.core.io.registry.reflect.Setup; 042import org.nuxeo.ecm.core.schema.types.Field; 043import org.nuxeo.ecm.core.schema.types.Schema; 044 045/** 046 * @since 10.3 047 */ 048@Setup(mode = SINGLETON, priority = REFERENCE) 049public class DocumentModelCSVWriter extends AbstractCSVWriter<DocumentModel> { 050 051 public static final String SCHEMAS_CTX_DATA = "schemas"; 052 053 public static final String XPATHS_CTX_DATA = "xpaths"; 054 055 public DocumentModelCSVWriter() { 056 super(); 057 } 058 059 @Override 060 protected void write(DocumentModel entity, CSVPrinter printer) throws IOException { 061 writeSystem(entity, printer); 062 for (String schemaName : getList(ctx, SCHEMAS_CTX_DATA)) { 063 Schema schema = schemaManager.getSchema(schemaName); 064 if (schema != null) { 065 writeSchema(entity, schema, printer); 066 } 067 } 068 for (String xpath : getList(ctx, XPATHS_CTX_DATA)) { 069 Field field = schemaManager.getField(xpath); 070 if (field != null) { 071 writeProperty(entity, xpath, printer); 072 } 073 } 074 } 075 076 @Override 077 protected void writeHeader(DocumentModel entity, CSVPrinter printer) throws IOException { 078 DocumentModelCSVHelper.printSystemPropertiesHeader(printer); 079 List<String> schemas = getList(ctx, SCHEMAS_CTX_DATA); 080 List<String> xpaths = getList(ctx, XPATHS_CTX_DATA); 081 DocumentModelCSVHelper.printPropertiesHeader(schemas, xpaths, printer); 082 printer.println(); 083 } 084 085 /* Make sure this is kept in sync with DocumentModelCSVHelper.SYSTEM_PROPERTIES_HEADER_FIELDS */ 086 protected void writeSystem(DocumentModel doc, CSVPrinter printer) throws IOException { 087 printer.print(doc.getRepositoryName()); 088 printer.print(doc.getId()); 089 printer.print(doc.getPathAsString()); 090 printer.print(doc.getType()); 091 printer.print(doc.getRef() != null ? doc.getCurrentLifeCycleState() : null); 092 printer.print(doc.getParentRef() != null ? doc.getParentRef().toString() : null); 093 printer.print(doc.isCheckedOut()); 094 095 boolean isVersion = doc.isVersion(); 096 boolean isProxy = doc.isProxy(); 097 098 printer.print(doc.isVersion()); 099 printer.print(isProxy); 100 printer.print(isProxy ? doc.getSourceId() : null); 101 printer.print(isVersion || isProxy ? doc.getVersionSeriesId() : null); 102 printer.print(doc.getChangeToken()); 103 printer.print(doc.getRef() != null && doc.isTrashed()); 104 printer.print(doc.getTitle()); 105 printer.print(doc.getVersionLabel()); 106 Lock lock = doc.getLockInfo(); 107 if (lock != null) { 108 printer.print(lock.getOwner()); 109 printCalendar(lock.getCreated(), printer); 110 } else { 111 printer.print(null); 112 printer.print(null); 113 } 114 if (doc.hasSchema("dublincore")) { 115 Calendar cal = (Calendar) doc.getPropertyValue("dc:modified"); 116 printCalendar(cal, printer); 117 } else { 118 printer.print(null); 119 } 120 Calendar retainUntil = doc.getRetainUntil(); 121 printer.print(doc.isRecord()); 122 if (retainUntil != null) { 123 printCalendar(retainUntil, printer); 124 } else { 125 printer.print(null); 126 } 127 printer.print(doc.hasLegalHold()); 128 printer.print(doc.isUnderRetentionOrLegalHold()); 129 } 130 131 protected void writeSchema(DocumentModel entity, Schema schema, CSVPrinter printer) throws IOException { 132 // provides the current document to the property writer 133 List<Field> fields = new ArrayList<>(schema.getFields()); 134 // fields are sorted for reproducibility 135 fields.sort(Comparator.comparing(o -> o.getName().getLocalName())); 136 String prefix = schema.getNamespace().prefix; 137 if (StringUtils.isBlank(prefix)) { 138 prefix = schema.getName(); 139 } 140 prefix += ":"; 141 for (Field field : fields) { 142 writeProperty(entity, prefix + field.getName().getLocalName(), printer); 143 } 144 } 145 146 protected void writeProperty(DocumentModel entity, String xpath, CSVPrinter printer) throws IOException { 147 Writer<Property> propertyWriter = registry.getWriter(ctx, Property.class, TEXT_CSV_TYPE); 148 Property property = null; 149 try { 150 property = entity.getProperty(xpath); 151 } catch (PropertyNotFoundException e) { 152 // ignore 153 } 154 try (OutputStream out = new OutputStreamWithCSVWriter(printer)) { 155 propertyWriter.write(property, Property.class, Property.class, TEXT_CSV_TYPE, out); 156 } 157 } 158}