001/* 002 * (C) Copyright 2006-2012 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019package org.nuxeo.ecm.platform.scanimporter.service; 020 021import java.io.File; 022import java.io.IOException; 023import java.io.Serializable; 024import java.text.ParseException; 025import java.util.ArrayList; 026import java.util.HashMap; 027import java.util.List; 028import java.util.Map; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.dom4j.Document; 033import org.dom4j.DocumentException; 034import org.dom4j.DocumentHelper; 035import org.dom4j.tree.DefaultElement; 036import org.jaxen.JaxenException; 037import org.jaxen.XPath; 038import org.jaxen.dom4j.Dom4jXPath; 039import org.nuxeo.common.utils.FileUtils; 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<String, Serializable>(); 078 079 if (mappingDesc == null) { 080 return null; 081 } 082 083 String xmlData = FileUtils.readFile(xmlFile); 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 try { 096 XPath xpath = new Dom4jXPath(fieldMap.getSourceXPath()); 097 nodes = xpath.selectNodes(xmlDoc); 098 } catch (JaxenException e) { 099 throw new IOException(e); 100 } 101 if (nodes.size() == 1) { 102 DefaultElement elem = (DefaultElement) nodes.get(0); 103 String value = null; 104 if ("TEXT".equals(fieldMap.getSourceAttribute())) { 105 value = elem.getText(); 106 } else { 107 value = elem.attribute(fieldMap.getSourceAttribute()).getValue(); 108 } 109 110 String target = fieldMap.getTargetXPath(); 111 if ("string".equalsIgnoreCase(fieldMap.getTargetType())) { 112 data.put(target, value); 113 continue; 114 } else if ("integer".equalsIgnoreCase(fieldMap.getTargetType())) { 115 data.put(target, Integer.parseInt(value)); 116 continue; 117 } else if ("double".equalsIgnoreCase(fieldMap.getTargetType())) { 118 data.put(target, Double.parseDouble(value)); 119 continue; 120 } else if ("date".equalsIgnoreCase(fieldMap.getTargetType())) { 121 try { 122 data.put(target, fieldMap.getDateFormat().parse(value)); 123 } catch (ParseException e) { 124 throw new IOException(e); 125 } 126 continue; 127 } else if ("boolean".equalsIgnoreCase(fieldMap.getTargetType())) { 128 data.put(target, Boolean.parseBoolean(value)); 129 continue; 130 } 131 log.error("Unknown target type, please look the scan importer configuration: " 132 + fieldMap.getTargetType()); 133 } 134 log.error("Mulliple or no element(s) found for: " + fieldMap.sourceXPath + " for " 135 + xmlFile.getAbsolutePath()); 136 137 } 138 139 List<Blob> blobs = new ArrayList<Blob>(); 140 141 for (ScanFileBlobMapping blobMap : mappingDesc.getBlobMappings()) { 142 List<?> nodes; 143 try { 144 XPath xpath = new Dom4jXPath(blobMap.getSourceXPath()); 145 nodes = xpath.selectNodes(xmlDoc); 146 } catch (JaxenException e) { 147 throw new IOException(e); 148 } 149 for (Object node : nodes) { 150 DefaultElement elem = (DefaultElement) node; 151 String filePath = elem.attributeValue(blobMap.getSourcePathAttribute()); 152 String fileName = elem.attributeValue(blobMap.getSourceFilenameAttribute()); 153 154 // Mainly for tests 155 if (filePath.startsWith("$TMP")) { 156 filePath = filePath.replace("$TMP", Framework.getProperty("nuxeo.import.tmpdir")); 157 } 158 159 File file = new File(filePath); 160 if (file.exists()) { 161 Blob blob = Blobs.createBlob(file); 162 if (fileName != null) { 163 blob.setFilename(fileName); 164 } else { 165 blob.setFilename(file.getName()); 166 } 167 String target = blobMap.getTargetXPath(); 168 if (target == null) { 169 blobs.add(blob); 170 } else { 171 data.put(target, (Serializable) blob); 172 } 173 } else { 174 log.error("File " + file.getAbsolutePath() + " is referenced by " + xmlFile.getAbsolutePath() 175 + " but was not found"); 176 } 177 } 178 } 179 180 String targetType = getTargetLeafType(); 181 DocumentTypeMapper mapper = mappingDesc.getTargetLeafTypeMapper(); 182 if (mapper != null) { 183 targetType = mapper.getTargetDocumentType(xmlDoc, xmlFile); 184 } 185 ScanFileBlobHolder bh = new ScanFileBlobHolder(blobs, data, targetType); 186 return bh; 187 } 188 189 public ScanFileMappingDescriptor getMappingDesc() { 190 return mappingDesc; 191 } 192 193 @Override 194 public String getTargetContainerType() { 195 if (mappingDesc == null) { 196 return ScanFileMappingDescriptor.DEFAULT_CONTAINER_TYPE; 197 } 198 return mappingDesc.getTargetContainerType(); 199 } 200 201 @Override 202 public String getTargetLeafType() { 203 if (mappingDesc == null) { 204 return ScanFileMappingDescriptor.DEFAULT_LEAF_TYPE; 205 } 206 return mappingDesc.getTargetLeafType(); 207 } 208 209 @Override 210 public ImporterConfig getImporterConfig() { 211 return config; 212 } 213}