/*
* (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.dg.docx;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.Vector;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import org.openflexo.dg.ProjectDocGenerator;
import org.openflexo.dg.rm.GeneratedFileResourceFactory;
import org.openflexo.dg.rm.ProjectDocxXmlFileResource;
import org.openflexo.docxparser.flexotag.FlexoContentTag;
import org.openflexo.docxparser.flexotag.FlexoDescriptionTag;
import org.openflexo.docxparser.flexotag.FlexoEPITag;
import org.openflexo.docxparser.flexotag.FlexoNameTag;
import org.openflexo.docxparser.flexotag.FlexoTitleTag;
import org.openflexo.foundation.DataModification;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.FlexoObservable;
import org.openflexo.foundation.cg.CGFile;
import org.openflexo.foundation.cg.DGRepository;
import org.openflexo.foundation.cg.dm.CustomTemplateRepositoryChanged;
import org.openflexo.foundation.cg.templates.CGTemplate;
import org.openflexo.foundation.cg.templates.CGTemplates;
import org.openflexo.foundation.cg.templates.TemplateFileNotification;
import org.openflexo.foundation.ontology.EditionPatternInstance;
import org.openflexo.foundation.rm.FlexoCopiedResource;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.ResourceType;
import org.openflexo.foundation.rm.ScreenshotResource;
import org.openflexo.foundation.rm.cg.CGRepositoryFileResource;
import org.openflexo.foundation.toc.TOCEntry;
import org.openflexo.foundation.utils.FlexoModelObjectReference;
import org.openflexo.foundation.utils.FlexoProjectFile;
import org.openflexo.generator.PackagedResourceToCopyGenerator;
import org.openflexo.generator.exception.GenerationException;
import org.openflexo.generator.exception.TemplateNotFoundException;
import org.openflexo.generator.rm.FlexoCopyOfFileResource;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.logging.FlexoLogger;
import org.openflexo.toolbox.FileFormat;
import org.openflexo.toolbox.FileResource;
import org.openflexo.toolbox.FileUtils;
import org.openflexo.toolbox.FileUtils.CopyStrategy;
public class ProjectDocDocxGenerator extends ProjectDocGenerator {
private static final String DOCX_MACRO_LIBRARY_NAME = "docx_macro_library.vm";
public static final String DOCXEXTRA_DIRECTORY_NAME = "DocxExtras";
protected static final Logger logger = FlexoLogger.getLogger(ProjectDocDocxGenerator.class.getPackage().getName());
protected boolean hasBeenInitialized = false;
private final Hashtable<String, DGDocxXMLGenerator<FlexoProject>> generators = new Hashtable<String, DGDocxXMLGenerator<FlexoProject>>();
protected static final Vector<FileResource> fileResourceToCopy = new Vector<FileResource>();
static {
FileResource directory = new FileResource(DOCXEXTRA_DIRECTORY_NAME);
if (directory != null) {
for (String fileName : directory.list(FileUtils.CVSFileNameFilter)) {
fileResourceToCopy.add(new FileResource(DOCXEXTRA_DIRECTORY_NAME + "/" + fileName));
}
}
}
public ProjectDocDocxGenerator(FlexoProject project, DGRepository repository) throws GenerationException {
super(project, repository);
}
@Override
public CGTemplates getDefaultTemplates() {
return getProject().getGeneratedDoc().getTemplates();
}
@Override
public Logger getGeneratorLogger() {
return logger;
}
@Override
public String getFileExtension() {
return "";
}
/**
* Overrides buildResourcesAndSetGenerators
*
* @see org.openflexo.dg.DGGenerator#buildResourcesAndSetGenerators(DGRepository, java.util.Vector)
*/
@Override
public void buildResourcesAndSetGenerators(DGRepository repository, Vector<CGRepositoryFileResource> resources) {
hasBeenInitialized = true;
for (String nameGenerator : DocxTemplatesEnum.getOrderedTemplateListGroupedPerGenerator().keySet()) {
DGDocxXMLGenerator<FlexoProject> generator = getGenerator(nameGenerator);
for (DocxTemplatesEnum docxTemplate : DocxTemplatesEnum.getOrderedTemplateListGroupedPerGenerator().get(nameGenerator)) {
refreshSecondaryProgressWindow(FlexoLocalization.localizedForKey("generating") + " " + docxTemplate.getFilePath(), false);
ProjectDocxXmlFileResource res = GeneratedFileResourceFactory.createNewProjectDocxXmlFileResource(repository, generator,
docxTemplate);
resources.add(res);
}
}
buildResourcesAndSetGeneratorsForCopyOfPackagedResources(resources);
// Useless as they are copied in copyAdditionalFiles, should be used instead but the images imported in the wysiwyg are not in the
// resources currently (and thus not copied by buildResourcesAndSetGeneratorsForCopiedResources)
// buildResourcesAndSetGeneratorsForCopiedResources(resources);
screenshotsGenerator.buildResourcesAndSetGenerators(repository, resources);
}
private DGDocxXMLGenerator<FlexoProject> getGenerator(String nameGenerator) {
DGDocxXMLGenerator<FlexoProject> returned = generators.get(nameGenerator);
if (returned == null) {
generators.put(nameGenerator, returned = new DGDocxXMLGenerator<FlexoProject>(this, getProject(), nameGenerator));
}
return returned;
}
@Override
protected String getCopiedResourcesRelativePath(FlexoProjectFile flexoFile) {
int lastIndexOfSlash = flexoFile.getRelativePath().lastIndexOf('/');
String relativeDirectoryPath = "";
if (lastIndexOfSlash != -1) {
relativeDirectoryPath = flexoFile.getRelativePath().substring(0, lastIndexOfSlash);
}
return relativeDirectoryPath;
}
private void buildResourcesAndSetGeneratorsForCopyOfPackagedResources(Vector<CGRepositoryFileResource> resources) {
for (FileResource fileResource : fileResourceToCopy) {
PackagedResourceToCopyGenerator<DGRepository> generator = getFileResourceGenerator(fileResource);
generator.buildResourcesAndSetGenerators(getRepository(), resources);
}
}
@Override
public PackagedResourceToCopyGenerator<DGRepository> getFileResourceGenerator(FileResource r) {
PackagedResourceToCopyGenerator<DGRepository> returned = packagedResourceToCopyGenerator.get(r);
if (returned == null) {
// String extension = r.getName().substring(r.getName().lastIndexOf(".")+1);
// FileFormat format = FileFormat.getFileFormatByExtension(extension);
FileFormat format;
if (r.getName().endsWith(".png")) {
format = FileFormat.PNG;
} else if (r.getName().endsWith(".jpg")) {
format = FileFormat.JPG;
} else if (r.getName().endsWith(".sty")) {
format = FileFormat.LATEX;
} else if (r.getName().endsWith(".def")) {
format = FileFormat.LATEX;
} else if (r.isDirectory()) {
format = FileFormat.UNKNOWN_DIRECTORY;
} else {
format = FileFormat.UNKNOWN_BINARY_FILE;
}
int lastIndexOfSlash = r.getInternalPath().lastIndexOf('/');
String relativeDirectoryPath = "";
if (lastIndexOfSlash != -1) {
relativeDirectoryPath = r.getInternalPath().substring(0, lastIndexOfSlash);
}
packagedResourceToCopyGenerator.put(r, returned = new PackagedResourceToCopyGenerator<DGRepository>(this, format,
ResourceType.COPIED_FILE, r, getRepository().getResourcesSymbolicDirectory(), relativeDirectoryPath));
}
return returned;
}
@Override
public void copyAdditionalFiles() throws IOException {
super.copyAdditionalFiles();
FileUtils.copyContentDirToDir(getProject().getImportedImagesDir(), new File(getRootOutputDirectory(), "word/media/"
+ getProject().getImportedImagesDir().getName()), CopyStrategy.REPLACE_OLD_ONLY);
FileUtils.copyContentDirToDir(getProject().getDocxToEmbedDirectory(), getRootOutputDirectory(), CopyStrategy.REPLACE_OLD_ONLY);
}
@Override
public boolean hasBeenInitialized() {
return hasBeenInitialized;
}
/**
* Overrides update
*
* @see org.openflexo.dg.DGGenerator#update(org.openflexo.foundation.FlexoObservable, org.openflexo.foundation.DataModification)
*/
@Override
public void update(FlexoObservable observable, DataModification dataModification) {
if (dataModification.propertyName() != null && dataModification.propertyName().equals("docType")) {
getTemplateLocator().notifyTemplateModified();
}
if (dataModification instanceof TemplateFileNotification) {
getTemplateLocator().notifyTemplateModified();
} else if (dataModification instanceof CustomTemplateRepositoryChanged) {
getTemplateLocator().notifyTemplateModified();
}
super.update(observable, dataModification);
}
public List<CGRepositoryFileResource> getAllMediaResources() {
List<CGRepositoryFileResource> mediaResources = new ArrayList<CGRepositoryFileResource>();
for (CGFile file : getRepository().getFiles()) {
if (file.getResource() instanceof FlexoCopiedResource
|| (CGRepositoryFileResource) file.getResource() instanceof FlexoCopyOfFileResource) {
mediaResources.add(file.getResource());
}
}
Collections.sort(mediaResources, new Comparator<CGRepositoryFileResource>() {
@Override
public int compare(CGRepositoryFileResource o1, CGRepositoryFileResource o2) {
if (o1.getResourceFile() != null) {
if (o2.getResourceFile() != null) {
if (o1.getResourceFile().getRelativePath() == null) {
if (o2.getResourceFile().getRelativePath() == null) {
return 0;
} else {
return -1;
}
} else {
if (o2.getResourceFile().getRelativePath() == null) {
return 1;
} else {
return o1.getResourceFile().getRelativePath().compareTo(o2.getResourceFile().getRelativePath());
}
}
} else {
return 1;
}
} else {
if (o2.getResourceFile() == null) {
return 0;
} else {
return -1;
}
}
}
});
return mediaResources;
}
public String getRIdForResource(CGRepositoryFileResource resource) {
return getRIdForString(getMediaResourceRelativePath(resource));
}
public String getRIdForString(String value) {
return "rId" + value.replaceAll("\\W", "_");
}
/**
* {@inheritDoc}
*/
@Override
public List<CGTemplate> getVelocityMacroTemplates() {
List<CGTemplate> result = new ArrayList<CGTemplate>();
try {
result.add(templateWithName(DOCX_MACRO_LIBRARY_NAME));
} catch (TemplateNotFoundException e) {
logger.warning("Should include velocity macro template for project generator but template is not found '"
+ DOCX_MACRO_LIBRARY_NAME + "'");
e.printStackTrace();
}
return result;
}
public ImageIcon getImageIconForImportedImageNamed(String imagePath) {
File importedImageDir = getProject().getImportedImagesDir();
if (!imagePath.startsWith("/") && !imagePath.startsWith("\\")) {
imagePath = "/" + imagePath;
}
File imageFile = new File(importedImageDir.getAbsolutePath() + imagePath);
if (!imageFile.exists()) {
// Try to make this image path relative to the imported image directory
imagePath = imagePath.replace('\\', '/');
String importedImageDirName = '/' + importedImageDir.getName() + '/';
int indexOfImportedImageDir = imagePath.indexOf(importedImageDirName);
if (indexOfImportedImageDir != -1 && imagePath.length() > indexOfImportedImageDir + importedImageDirName.length()) {
imageFile = new File(importedImageDir.getAbsolutePath() + '/'
+ imagePath.substring(indexOfImportedImageDir + importedImageDirName.length()));
}
}
if (imageFile.exists()) {
return new ImageIcon(imageFile.getAbsolutePath());
}
return null;
}
public DocxVelocityXmlFromHtml convertHTML2DocxVelocityXml(String htmlString, Integer currentUniqueID) {
return new DocxVelocityXmlFromHtml(htmlString, currentUniqueID, false, this);
}
public DocxVelocityXmlFromHtml convertHTML2DocxVelocityXmlWithinP(String htmlString, Integer currentUniqueID) {
return new DocxVelocityXmlFromHtml(htmlString, currentUniqueID, true, this);
}
public String getFlexoDescriptionTag(FlexoModelObject object, String target) {
return FlexoDescriptionTag.buildFlexoDescriptionTag(String.valueOf(object.getFlexoID()), object.getUserIdentifier(), target);
}
public String getFlexoNameTag(FlexoModelObject object) {
if (object == null) {
return null;
}
return FlexoNameTag.buildFlexoNameTag(String.valueOf(object.getFlexoID()), object.getUserIdentifier());
}
public String getEPITag(EditionPatternInstance object, String bindingPath) {
if (object == null) {
return null;
}
TreeMap<String, FlexoModelObject> treeMap = new TreeMap<String, FlexoModelObject>(object.getActors());
String modelObjectReference = null;
for (Entry<String, FlexoModelObject> e : treeMap.entrySet()) {
if (e.getValue().getXMLResourceData() != null) {
modelObjectReference = new FlexoModelObjectReference<FlexoModelObject>(e.getValue()).getStringRepresentation();
break;
}
}
return FlexoEPITag.buildFlexoEPITag(String.valueOf(object.getInstanceId()), object.getPattern().getURI(), bindingPath,
modelObjectReference);
}
public String getTocEntryContentTag(TOCEntry tocEntry) {
return FlexoContentTag.buildFlexoContentTag(String.valueOf(tocEntry.getFlexoID()), tocEntry.getUserIdentifier());
}
public String getTocEntryTitleTag(TOCEntry tocEntry) {
if (tocEntry == null) {
return null;
}
return FlexoTitleTag.buildFlexoTitleTag(String.valueOf(tocEntry.getFlexoID()), tocEntry.getUserIdentifier());
}
public String getMediaResourceRelativePath(CGRepositoryFileResource mediaResource) {
return getMediaRelativePath(mediaResource.getFile().getPath());
}
public String getMediaRelativePath(String filePath) {
filePath = filePath.replace('\\', '/');
int index = filePath.lastIndexOf("word/");
if (index != -1 && filePath.length() > index + "word/".length()) {
return filePath.substring(index + "word/".length());
}
return "media/" + filePath;
}
public Icon getScreenshotImageIcon(FlexoModelObject o) {
FlexoCopiedResource r = getScreenshot(o);
if (r != null) {
if (r.getFile().exists()) {
return new ImageIcon(r.getFile().getAbsolutePath());
}
if (r.getResourceToCopy() != null) {
return new ImageIcon(r.getResourceToCopy().getFile().getAbsolutePath());
}
}
ScreenshotResource screenshotResource = o.getProject().getScreenshotResource(o, true);
if (screenshotResource == null) {
logger.warning("Cannot find screenshot for " + o + " of " + o.getClass().getSimpleName());
return null;
} else {
return new ImageIcon(screenshotResource.getFile().getAbsolutePath());
}
}
}