001/* 002 * (C) Copyright 2009-2016 Nuxeo SA (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 * Thomas Roger 018 */ 019package org.nuxeo.ecm.platform.importer.properties; 020 021import java.io.File; 022import java.io.FileOutputStream; 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.Calendar; 027import java.util.Collections; 028import java.util.List; 029import java.util.Map; 030import java.util.Properties; 031 032import org.apache.commons.logging.Log; 033import org.apache.commons.logging.LogFactory; 034import org.nuxeo.ecm.core.api.DataModel; 035import org.nuxeo.ecm.core.api.DocumentModel; 036import org.nuxeo.ecm.core.api.NuxeoException; 037import org.nuxeo.ecm.core.api.PropertyException; 038import org.nuxeo.ecm.core.schema.types.primitives.DateType; 039 040/** 041 * Handle properties file creation from a {@code DocumentModel}. 042 * <p> 043 * Only support the types that {@code MetadataCollector} knows. 044 * 045 * @author <a href="mailto:[email protected]">Thomas Roger</a> 046 */ 047public class MetadataFile { 048 049 private static final Log log = LogFactory.getLog(MetadataFile.class); 050 051 protected DocumentModel doc; 052 053 protected Properties metadataProperties = new Properties(); 054 055 /** 056 * Create a {@code MetadataFile} from a {@code DocumentModel}'s schemas. 057 * 058 * @return a new MetadataFile object 059 */ 060 public static MetadataFile createFromDocument(DocumentModel doc) { 061 MetadataFile mdFile = new MetadataFile(doc); 062 mdFile.load(); 063 return mdFile; 064 } 065 066 /** 067 * Create a {@code MetadataFile} from the listed schemas (with all properties) and the listed properties of a 068 * {@code DocumentModel} 069 * 070 * @return a new MetadataFile object 071 */ 072 public static MetadataFile createFromSchemasAndProperties(DocumentModel doc, List<String> allPropertiesSchemas, 073 List<String> properties) { 074 MetadataFile mdFile = new MetadataFile(doc); 075 mdFile.load(allPropertiesSchemas, properties); 076 return mdFile; 077 } 078 079 /** 080 * Create a {@code MetadataFile} from the listed schemas (with all properties) of a {@code DocumentModel} 081 * 082 * @return a new MetadataFile object 083 */ 084 public static MetadataFile createFromSchemas(DocumentModel doc, List<String> allPropertiesSchemas) { 085 return createFromSchemasAndProperties(doc, allPropertiesSchemas, Collections.<String> emptyList()); 086 } 087 088 /** 089 * Create a {@code MetadataFile} from the listed properties of a {@code DocumentModel} 090 * 091 * @return a new MetadataFile object 092 */ 093 public static MetadataFile createFromProperties(DocumentModel doc, List<String> properties) { 094 return createFromSchemasAndProperties(doc, Collections.<String> emptyList(), properties); 095 } 096 097 protected MetadataFile(DocumentModel doc) { 098 this.doc = doc; 099 } 100 101 protected void load(List<String> allPropertiesSchemas, List<String> properties) { 102 if (!metadataProperties.isEmpty()) { 103 return; 104 } 105 106 for (String schema : allPropertiesSchemas) { 107 addAllProperties(schema); 108 } 109 110 for (String property : properties) { 111 try { 112 addProperty(property, doc.getPropertyValue(property)); 113 } catch (PropertyException e) { 114 String message = String.format("Property '%s' not found on document type: %s. Skipping it.", property, 115 doc.getType()); 116 log.debug(message); 117 } 118 } 119 } 120 121 protected void addAllProperties(String schema) { 122 DataModel dm = doc.getDataModel(schema); 123 if (dm != null) { 124 for (Map.Entry<String, Object> entry : dm.getMap().entrySet()) { 125 Object value = entry.getValue(); 126 String propertyKey = entry.getKey(); 127 addProperty(computePropertyKey(propertyKey, schema), value); 128 } 129 } 130 } 131 132 public void addProperty(String propertyKey, Object value) { 133 if (value instanceof String) { 134 metadataProperties.put(propertyKey, value); 135 } else if (value instanceof List) { 136 try { 137 List<String> list = (List<String>) value; 138 if (!list.isEmpty()) { 139 if (list.size() == 1) { 140 list = new ArrayList<>(list); 141 list.add(""); 142 } 143 metadataProperties.put(propertyKey, String.join(MetadataCollector.LIST_SEPARATOR, list)); 144 } 145 } catch (ClassCastException e) { 146 // do nothing 147 } 148 } else if (value instanceof String[]) { 149 List<String> list = Arrays.asList((String[]) value); 150 if (!list.isEmpty()) { 151 if (list.size() == 1) { 152 list = new ArrayList<>(list); 153 list.add(""); 154 } 155 metadataProperties.put(propertyKey, String.join(MetadataCollector.ARRAY_SEPARATOR, list)); 156 } 157 } else if (value instanceof Calendar) { 158 metadataProperties.put(propertyKey, new DateType().encode(value)); 159 } else if (value instanceof Number) { 160 metadataProperties.put(propertyKey, value.toString()); 161 } 162 } 163 164 protected String computePropertyKey(String propertyKey, String schema) { 165 if (!propertyKey.contains(":")) { 166 propertyKey = schema + ":" + propertyKey; 167 } 168 return propertyKey; 169 } 170 171 protected void load() { 172 for (String schema : doc.getSchemas()) { 173 addAllProperties(schema); 174 } 175 } 176 177 /** 178 * Write the properties file to the given {@code file} 179 */ 180 public void writeTo(File file) { 181 FileOutputStream fos = null; 182 try { 183 fos = new FileOutputStream(file); 184 metadataProperties.store(fos, null); 185 } catch (IOException e) { 186 throw new NuxeoException("Unable to write the metadata properties to " + file.getAbsolutePath(), e); 187 } finally { 188 if (fos != null) { 189 try { 190 fos.close(); 191 } catch (IOException e) { 192 // nothing to do... 193 } 194 } 195 } 196 } 197 198}