/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo 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. * * OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.generator; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.TargetType; import org.openflexo.foundation.cg.GenerationRepository; import org.openflexo.foundation.cg.templates.CGTemplate; import org.openflexo.foundation.cg.templates.CGTemplateRepository; import org.openflexo.foundation.cg.templates.CGTemplateSet; import org.openflexo.foundation.cg.templates.CGTemplates; import org.openflexo.foundation.cg.templates.CustomCGTemplateRepository; import org.openflexo.foundation.rm.FlexoMemoryResource; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.rm.FlexoProjectBuilder; import org.openflexo.foundation.rm.ResourceType; import org.openflexo.generator.exception.TemplateNotFoundException; import org.openflexo.generator.rm.GenerationAvailableFileResource; import org.openflexo.logging.FlexoLogger; /** * This class is intended to be used by generators. As template status are involved in dependancies computation, this class is declared as a * MemoryResource. * * @author Guillaume Polet, Sylvain Guerin * */ public class TemplateLocator extends FlexoMemoryResource { private static final Logger logger = FlexoLogger.getLogger(TemplateLocator.class.getPackage().getName()); private FlexoProject project; private TargetType target; private Vector<CGTemplateSet> _templateDirectories; private Hashtable<String, CGTemplate> _templateTable; private CGTemplates _templates; private AbstractProjectGenerator _projectGenerator; /** * Constructor used for XML Serialization: never try to instanciate resource from this constructor * * @param builder */ public TemplateLocator(FlexoProjectBuilder builder) { super(builder.project); } public TemplateLocator(CGTemplates templates, AbstractProjectGenerator projectGenerator) { super(templates.getProject()); _templateDirectories = null; _templateTable = new Hashtable<String, CGTemplate>(); _templates = templates; _projectGenerator = projectGenerator; rebuildDependancies(); } public void notifyTemplateModified() { logger.info("********* Clear TemplateLocator cache !!!!!!!!!!! for " + getFullyQualifiedName()); _templateTable.clear(); _templateDirectories = null; lastUpdate = new Date(); } public CGTemplate templateWithName(String templateRelativePath) throws TemplateNotFoundException { if (templateRelativePath.startsWith("/")) { templateRelativePath = templateRelativePath.substring(1); } CGTemplate returned = _templateTable.get(templateRelativePath); if (returned == null) { returned = searchForTemplate(templateRelativePath); if (logger.isLoggable(Level.INFO)) { logger.info(templateRelativePath + "=" + returned.getRelativePath() + "[" + returned.getSet().getName() + "]"); } _templateTable.put(templateRelativePath, returned); } return returned; } @SuppressWarnings("unchecked") private CGTemplate searchForTemplate(String templateRelativePath) throws TemplateNotFoundException { Enumeration<CGTemplateSet> en = templateDirectories().elements(); CGTemplateSet set = null; while (en.hasMoreElements()) { set = en.nextElement(); // logger.info("search in "+set.getDirectory().getAbsolutePath()); CGTemplate answer = set.getTemplate(templateRelativePath); if (answer != null) { return answer; } } // Template not found : build explicit error message. en = templateDirectories().elements(); StringBuffer buffer = new StringBuffer(); buffer.append("Searched directories are:\n"); logger.info("Templates not found :" + templateRelativePath); throw new TemplateNotFoundException(templateRelativePath, buffer.toString(), _projectGenerator); } /** * search order is : - prj/Templates/GENERATION_TARGET - prj/Templates - Flexo/Config/Generator/Templates/GENERATION_TARGET - * Flexo/Config/Generator/Templates/ */ private Vector<CGTemplateSet> templateDirectories() { if (_templateDirectories == null || this.project != _projectGenerator.getProject() || this.target != _projectGenerator.getTarget()) { this.project = _projectGenerator.getProject(); this.target = _projectGenerator.getTarget(); _templateDirectories = new Vector<CGTemplateSet>(); CustomCGTemplateRepository customRepository = _projectGenerator.getRepository() != null ? _projectGenerator.getRepository() .getPreferredTemplateRepository() : null; if (customRepository != null) { if (target != null && customRepository.getTemplateSetForTarget(target) != null) { _templateDirectories.add(customRepository.getTemplateSetForTarget(target)); } _templateDirectories.add(customRepository.getCommonTemplates()); } CGTemplateRepository applicationRepository = _templates.getApplicationRepository(); if (target != null && applicationRepository.getTemplateSetForTarget(target) != null) { _templateDirectories.add(applicationRepository.getTemplateSetForTarget(target)); } _templateDirectories.add(applicationRepository.getCommonTemplates()); } return _templateDirectories; } private Date lastUpdate = new Date(); @Override public Date getLastUpdate() { return lastUpdate; } @Override public String getName() { if (_projectGenerator == null || _projectGenerator.getRepository() == null) { return null; } if (_projectGenerator.getTarget() != null) { return _projectGenerator.getTarget().getName() + "." + _projectGenerator.getRepository().getName(); } return _projectGenerator.getRepository().getName(); } @Override public ResourceType getResourceType() { return ResourceType.CG_TEMPLATES; } @SuppressWarnings("unchecked") public boolean needsUpdateForResource(GenerationAvailableFileResource resource) { Date requestDate = resource.getLastUpdate(); return needsUpdateForGenerator(requestDate, (Generator<? extends FlexoModelObject, ? extends GenerationRepository>) resource.getGenerator()); } /** * @param requestDate * @param generator * @return */ public boolean needsUpdateForGenerator(Date requestDate, Generator<? extends FlexoModelObject, ? extends GenerationRepository> generator) { if (generator == null) { return false; } for (CGTemplate template : generator.getUsedTemplates()) { if (template.getLastUpdate().after(requestDate)) { if (logger.isLoggable(Level.FINE)) { logger.fine("template " + template + "/" + template.getLastUpdate() + " AFTER " + requestDate); } return true; } } return false; } public boolean needsRegenerationBecauseOfTemplateChange(Generator<? extends FlexoModelObject, ? extends GenerationRepository> generator) { if (generator == null) { return false; } for (CGTemplate template : generator.getUsedTemplates()) { try { CGTemplate file = searchForTemplate(template.getRelativePathWithoutSetPrefix()); if (file != template) { return true; } } catch (TemplateNotFoundException e) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Template not found: " + template.getTemplateName()); } } } return false; } }