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