/* * Copyright (C) 2012 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package com.bc.ceres.metadata; import com.bc.ceres.core.Assert; import com.bc.ceres.resource.ReaderResource; import com.bc.ceres.resource.Resource; import com.bc.ceres.resource.ResourceEngine; import org.apache.velocity.VelocityContext; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.HashMap; import java.util.Map; import java.util.SortedMap; /** * A engine for processing text resources using velocity. It supports: * <ul> * <li>reading resources in XML or property format</li> * <li>reading of resources belonging to source(s)</li> * <li>allows to manipulate the used velocity context</li> * <li>writing the context using given templates</li> * </ul> * * @author MarcoZ * @author Bettina * @since Ceres 0.13.2 */ public class MetadataResourceEngine { private final ResourceEngine resourceEngine; private final MetadataResourceResolver metadataResourceResolver; private final SimpleFileSystem simpleFileSystem; /** * Creates the metadata engine. * * @param simpleFileSystem A abstraction of the used filesystem. */ public MetadataResourceEngine(SimpleFileSystem simpleFileSystem) { this(simpleFileSystem, new MetadataResourceResolver(simpleFileSystem)); } /** * Creates the metadata engine. * * @param simpleFileSystem A abstraction of the used filesystem. * @param metadataResourceResolver A resolver for metadata resource names.. */ public MetadataResourceEngine(SimpleFileSystem simpleFileSystem, MetadataResourceResolver metadataResourceResolver) { Assert.notNull(simpleFileSystem, "simpleFileSystem"); Assert.notNull(metadataResourceResolver, "metadataResourceResolver"); this.resourceEngine = new ResourceEngine(); this.simpleFileSystem = simpleFileSystem; this.metadataResourceResolver = metadataResourceResolver; } /** * Return the used velocity context. * * @return the velocity context */ public VelocityContext getVelocityContext() { return resourceEngine.getVelocityContext(); } /** * Reads the resource with the given path and stores its content in the velocity * context using the given key. If evaluate is set to {@code true}. The content will be evaluated * using the current state of the velocity context. * * @param name The name under which the metadata are placed into the velocity context * @param path The path name of the metadata resource * @return The resource * @throws IOException If an I/O error occurs */ public Resource readResource(String name, String path) throws IOException { Reader reader = simpleFileSystem.createReader(path); return resourceEngine.processAndAddResource(name, new ReaderResource(path, reader)); } /** * Reads the all metadata file belonging to the given source item and places them into a map registered as * 'sourceMetadata' the velocity context. The 'sourceMetadata'-map contains the processed metadata files as another map. * The map of metadata files can be retrieved using the key 'sourceId'. * <p/> * Metadata files belong to a source if they follow a naming pattern: * For a given {@code sourcePath} "chl_a.nc", e.g. "chl_a-metadata.xml" and "chl_a-report.html" are considered. * * @param sourceId The name under which the metadata are placed in the 'sourceMetadata'-map * @param sourcePath The path name of the source item * @throws IOException If an I/O error occurs */ public void readRelatedResource(String sourceId, String sourcePath) throws IOException { SortedMap<String, String> sourceNames = metadataResourceResolver.getSourceMetadataPaths(sourcePath); HashMap<String, Resource> resourceMap = new HashMap<String, Resource>(); for (Map.Entry<String, String> sourceEntries : sourceNames.entrySet()) { String metadataBaseName = sourceEntries.getKey(); String path = sourceEntries.getValue(); Reader reader = simpleFileSystem.createReader(path); Resource resource = new ReaderResource(path, reader); Resource processedResource = resourceEngine.processResource(resource); resourceMap.put(metadataBaseName.replace(".", "_"), processedResource); } getVelocityMapSafe("sourceMetadata").put(sourceId, resourceMap); } private Map<String, Map> getVelocityMapSafe(String name) { Object mapObject = resourceEngine.getVelocityContext().get(name); Map<String, Map> map; if (mapObject instanceof Map) { map = (Map<String, Map>) mapObject; } else { map = new HashMap<String, Map>(); resourceEngine.getVelocityContext().put(name, map); } return map; } /** * Writes metadata belonging to the given target item. For this the velocity template is evaluated * using the current context. * <p/> * The target metadata files follow a naming pattern: * For a given {@code templatePath} "report.xml.vm" and {@code targetPath} "chl_a.nc" * a target metadata file "chl_a-report.xml" gets written. * * @param templatePath The path name of the velocity template * @param targetPath The path name of the target item * @throws IOException If an I/O error occurs */ public void writeRelatedResource(String templatePath, String targetPath) throws IOException { MetadataResourceResolver.TargetResourceInfo targetResourceInfo = metadataResourceResolver.getTargetName(templatePath, targetPath); VelocityContext velocityContext = resourceEngine.getVelocityContext(); velocityContext.put("templateName", targetResourceInfo.templateName); velocityContext.put("templateBaseName", targetResourceInfo.templateBaseName); Reader templateReader = simpleFileSystem.createReader(templatePath); Resource processedResource = resourceEngine.processResource(new ReaderResource(templatePath, templateReader)); Writer writer = simpleFileSystem.createWriter(targetResourceInfo.targetName); try { writer.write(processedResource.getContent()); } finally { templateReader.close(); writer.close(); } } }