001/* 002 * (C) Copyright 2006-2012 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 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021package org.nuxeo.ecm.platform.scanimporter.service; 022 023import java.io.File; 024import java.io.IOException; 025import java.io.Serializable; 026import java.nio.charset.StandardCharsets; 027import java.text.ParseException; 028import java.util.ArrayList; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032 033import org.apache.commons.io.FileUtils; 034import org.apache.commons.logging.Log; 035import org.apache.commons.logging.LogFactory; 036import org.dom4j.Document; 037import org.dom4j.DocumentException; 038import org.dom4j.DocumentHelper; 039import org.dom4j.tree.DefaultElement; 040import org.nuxeo.ecm.core.api.Blob; 041import org.nuxeo.ecm.core.api.Blobs; 042import org.nuxeo.ecm.platform.scanimporter.processor.DocumentTypeMapper; 043import org.nuxeo.runtime.api.Framework; 044import org.nuxeo.runtime.model.ComponentInstance; 045import org.nuxeo.runtime.model.DefaultComponent; 046 047/** 048 * Component to provide service logic : - meta-data parsing - configuration management - extension points 049 * 050 * @author Thierry Delprat 051 */ 052public class ScannedFileMapperComponent extends DefaultComponent implements ScannedFileMapperService { 053 054 private static final Log log = LogFactory.getLog(ScannedFileMapperComponent.class); 055 056 public static final String MAPPING_EP = "mapping"; 057 058 public static final String CONFIG_EP = "config"; 059 060 protected ScanFileMappingDescriptor mappingDesc = null; 061 062 protected ImporterConfig config = null; 063 064 @Override 065 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 066 067 if (MAPPING_EP.equals(extensionPoint)) { 068 mappingDesc = (ScanFileMappingDescriptor) contribution; 069 } else if (CONFIG_EP.equals(extensionPoint)) { 070 config = (ImporterConfig) contribution; 071 } 072 } 073 074 @Override 075 public ScanFileBlobHolder parseMetaData(File xmlFile) throws IOException { 076 077 Map<String, Serializable> data = new HashMap<>(); 078 079 if (mappingDesc == null) { 080 return null; 081 } 082 083 String xmlData = FileUtils.readFileToString(xmlFile, StandardCharsets.UTF_8); 084 085 Document xmlDoc; 086 try { 087 xmlDoc = DocumentHelper.parseText(xmlData); 088 } catch (DocumentException e) { 089 throw new IOException(e); 090 } 091 092 for (ScanFileFieldMapping fieldMap : mappingDesc.getFieldMappings()) { 093 094 List<?> nodes; 095 nodes = xmlDoc.selectNodes(fieldMap.getSourceXPath()); 096 if (nodes.size() == 1) { 097 DefaultElement elem = (DefaultElement) nodes.get(0); 098 String value; 099 if ("TEXT".equals(fieldMap.getSourceAttribute())) { 100 value = elem.getText(); 101 } else { 102 value = elem.attribute(fieldMap.getSourceAttribute()).getValue(); 103 } 104 105 String target = fieldMap.getTargetXPath(); 106 if ("string".equalsIgnoreCase(fieldMap.getTargetType())) { 107 data.put(target, value); 108 continue; 109 } else if ("integer".equalsIgnoreCase(fieldMap.getTargetType())) { 110 data.put(target, Integer.valueOf(value)); 111 continue; 112 } else if ("double".equalsIgnoreCase(fieldMap.getTargetType())) { 113 data.put(target, Double.valueOf(value)); 114 continue; 115 } else if ("date".equalsIgnoreCase(fieldMap.getTargetType())) { 116 try { 117 data.put(target, fieldMap.getDateFormat().parse(value)); 118 } catch (ParseException e) { 119 throw new IOException(e); 120 } 121 continue; 122 } else if ("boolean".equalsIgnoreCase(fieldMap.getTargetType())) { 123 data.put(target, Boolean.valueOf(value)); 124 continue; 125 } 126 log.error("Unknown target type, please look the scan importer configuration: " 127 + fieldMap.getTargetType()); 128 } 129 log.error("Mulliple or no element(s) found for: " + fieldMap.sourceXPath + " for " 130 + xmlFile.getAbsolutePath()); 131 132 } 133 134 List<Blob> blobs = new ArrayList<>(); 135 136 for (ScanFileBlobMapping blobMap : mappingDesc.getBlobMappings()) { 137 List<?> nodes; 138 nodes = xmlDoc.selectNodes(blobMap.getSourceXPath()); 139 for (Object node : nodes) { 140 DefaultElement elem = (DefaultElement) node; 141 String filePath = elem.attributeValue(blobMap.getSourcePathAttribute()); 142 String fileName = elem.attributeValue(blobMap.getSourceFilenameAttribute()); 143 144 // Mainly for tests 145 if (filePath.startsWith("$TMP")) { 146 filePath = filePath.replace("$TMP", Framework.getProperty("nuxeo.import.tmpdir")); 147 } 148 149 File file = new File(filePath); 150 if (file.exists()) { 151 Blob blob = Blobs.createBlob(file); 152 if (fileName != null) { 153 blob.setFilename(fileName); 154 } else { 155 blob.setFilename(file.getName()); 156 } 157 String target = blobMap.getTargetXPath(); 158 if (target == null) { 159 blobs.add(blob); 160 } else { 161 data.put(target, (Serializable) blob); 162 } 163 } else { 164 log.error("File " + file.getAbsolutePath() + " is referenced by " + xmlFile.getAbsolutePath() 165 + " but was not found"); 166 } 167 } 168 } 169 170 String targetType = getTargetLeafType(); 171 DocumentTypeMapper mapper = mappingDesc.getTargetLeafTypeMapper(); 172 if (mapper != null) { 173 targetType = mapper.getTargetDocumentType(xmlDoc, xmlFile); 174 } 175 return new ScanFileBlobHolder(blobs, data, targetType); 176 } 177 178 public ScanFileMappingDescriptor getMappingDesc() { 179 return mappingDesc; 180 } 181 182 @Override 183 public String getTargetContainerType() { 184 if (mappingDesc == null) { 185 return ScanFileMappingDescriptor.DEFAULT_CONTAINER_TYPE; 186 } 187 return mappingDesc.getTargetContainerType(); 188 } 189 190 @Override 191 public String getTargetLeafType() { 192 if (mappingDesc == null) { 193 return ScanFileMappingDescriptor.DEFAULT_LEAF_TYPE; 194 } 195 return mappingDesc.getTargetLeafType(); 196 } 197 198 @Override 199 public ImporterConfig getImporterConfig() { 200 return config; 201 } 202}