Skip to content

Commit

Permalink
[Templates] Refactor templates and template manifest handling
Browse files Browse the repository at this point in the history
- De-duplicate lots of code and refactor

- Create the template manifest in one place in AbstractTemplate

- AbstractTemplate#save() just copies and updates the zip, it doesn't regenerate the thumbnail images
  • Loading branch information
Phillipus committed Dec 31, 2024
1 parent d66d442 commit 1fd45b6
Show file tree
Hide file tree
Showing 19 changed files with 333 additions and 514 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
*/
package com.archimatetool.canvas.templates.model;

import java.io.File;
import java.io.IOException;

import org.eclipse.swt.graphics.Image;

import com.archimatetool.canvas.ICanvasImages;
Expand All @@ -24,10 +27,10 @@ public class CanvasModelTemplate extends AbstractTemplate {
public CanvasModelTemplate() {
}

public CanvasModelTemplate(String id) {
super(id);
public CanvasModelTemplate(File file) throws IOException {
super(file);
}

@Override
public String getType() {
return XML_CANVAS_TEMPLATE_ATTRIBUTE_TYPE_MODEL;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,15 @@

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

import org.eclipse.swt.graphics.Image;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;

import com.archimatetool.canvas.CanvasEditorPlugin;
import com.archimatetool.canvas.ICanvasImages;
import com.archimatetool.editor.ArchiPlugin;
import com.archimatetool.editor.utils.ZipUtils;
import com.archimatetool.jdom.JDOMUtils;
import com.archimatetool.editor.Logger;
import com.archimatetool.templates.model.ITemplate;
import com.archimatetool.templates.model.ITemplateGroup;
import com.archimatetool.templates.model.ITemplateXMLTags;
import com.archimatetool.templates.model.TemplateGroup;
import com.archimatetool.templates.model.TemplateManager;

Expand All @@ -37,18 +30,20 @@
public class CanvasTemplateManager extends TemplateManager {

public static final String CANVAS_TEMPLATE_FILE_EXTENSION = ".archicanvas"; //$NON-NLS-1$
private File fUserTemplatesFile = new File(ArchiPlugin.INSTANCE.getWorkspaceFolder(), "canvasses.xml"); //$NON-NLS-1$


@Override
protected ITemplateGroup loadInbuiltTemplates() {
ITemplateGroup group = new TemplateGroup(Messages.CanvasTemplateManager_0);
File folder = CanvasEditorPlugin.INSTANCE.getTemplatesFolder();
if(folder.exists()) {
for(File file : folder.listFiles()) {
if(file.getName().toLowerCase().endsWith(CANVAS_TEMPLATE_FILE_EXTENSION)) {
ITemplate template = new CanvasModelTemplate();
template.setFile(file);
group.addTemplate(template);
try {
group.addTemplate(createTemplate(file));
}
catch(IOException ex) {
Logger.logError("Error loading template", ex); //$NON-NLS-1$
}
}
}
}
Expand All @@ -57,7 +52,7 @@ protected ITemplateGroup loadInbuiltTemplates() {

@Override
public File getUserTemplatesManifestFile() {
return fUserTemplatesFile;
return new File(ArchiPlugin.INSTANCE.getWorkspaceFolder(), "canvasses.xml"); //$NON-NLS-1$
}

@Override
Expand All @@ -67,53 +62,11 @@ public String getTemplateFileExtension() {

@Override
public ITemplate createTemplate(File file) throws IOException {
if(isValidTemplateFile(file)) {
return new CanvasModelTemplate(null);
}
else {
throw new IOException("Wrong template format."); //$NON-NLS-1$
}
return new CanvasModelTemplate(file);
}

@Override
protected ITemplate createTemplate(String type) {
if(CanvasModelTemplate.XML_CANVAS_TEMPLATE_ATTRIBUTE_TYPE_MODEL.equals(type)) {
return new CanvasModelTemplate();
}
return null;
}

@Override
public Image getMainImage() {
return ICanvasImages.ImageFactory.getImage(ICanvasImages.ICON_CANVAS_MODEL);
}

@Override
protected boolean isValidTemplateFile(File file) throws IOException {
if(file == null || !file.exists()) {
return false;
}

// Ensure the template is of the right kind
String xmlString = ZipUtils.extractZipEntry(file, ZIP_ENTRY_MANIFEST, Charset.forName("UTF-8")); //$NON-NLS-1$
if(xmlString == null) {
return false;
}

// If the attribute "type" exists then return true if its value is "canvas".
// If the attribute doesn't exist it was from an older version (before 2.1)
try {
Document doc = JDOMUtils.readXMLString(xmlString);
Element root = doc.getRootElement();
Attribute attType = root.getAttribute(ITemplateXMLTags.XML_TEMPLATE_ATTRIBUTE_TYPE);
if(attType != null) {
return CanvasModelTemplate.XML_CANVAS_TEMPLATE_ATTRIBUTE_TYPE_MODEL.equals(attType.getValue());
}
}
catch(JDOMException ex) {
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,21 @@
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.jdom2.Document;
import org.jdom2.Element;

import com.archimatetool.canvas.model.ICanvasModel;
import com.archimatetool.canvas.templates.model.CanvasModelTemplate;
import com.archimatetool.canvas.templates.model.CanvasTemplateManager;
import com.archimatetool.editor.diagram.commands.DiagramCommandFactory;
import com.archimatetool.editor.model.IArchiveManager;
import com.archimatetool.editor.utils.ZipUtils;
import com.archimatetool.jdom.JDOMUtils;
import com.archimatetool.model.IArchimateFactory;
import com.archimatetool.model.IArchimateModel;
import com.archimatetool.model.IDiagramModelReference;
import com.archimatetool.model.IFolder;
import com.archimatetool.model.ModelVersion;
import com.archimatetool.model.util.UUIDFactory;
import com.archimatetool.templates.model.ITemplate;
import com.archimatetool.templates.model.ITemplateGroup;
import com.archimatetool.templates.model.ITemplateXMLTags;
import com.archimatetool.templates.model.TemplateManager;
import com.archimatetool.templates.wizard.TemplateUtils;

Expand Down Expand Up @@ -134,82 +131,42 @@ public void run() {
}

private void createZipFile(File zipFile) throws IOException {
ZipOutputStream zOut = null;

try {
// Make sure parent folder exists
File parent = zipFile.getParentFile();
if(parent != null) {
parent.mkdirs();
}

// Delete any existing zip first
zipFile.delete();

// Start a zip stream
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(zipFile));
zOut = new ZipOutputStream(out);
// Make sure parent folder exists
File parent = zipFile.getParentFile();
if(parent != null) {
parent.mkdirs();
}

// Model File
File modelFile = saveModelToTempFile();
ZipUtils.addFileToZip(modelFile, TemplateManager.ZIP_ENTRY_MODEL, zOut);
if(modelFile != null) {
modelFile.delete();
}

try(ZipOutputStream zOut = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)))) {
// Manifest
String manifest = createManifest();
ZipUtils.addStringToZip(manifest, TemplateManager.ZIP_ENTRY_MANIFEST, zOut, Charset.forName("UTF-8")); //$NON-NLS-1$


// Model File
File tempFile = saveModelToTempFile();
ZipUtils.addFileToZip(tempFile, TemplateManager.ZIP_ENTRY_MODEL, zOut);
tempFile.delete();

// Thumbnail
if(fIncludeThumbnail) {
Image image = TemplateUtils.createThumbnailImage(fCanvasModel);
ZipUtils.addImageToZip(image, TemplateManager.ZIP_ENTRY_THUMBNAILS + "1.png", zOut, SWT.IMAGE_PNG, null); //$NON-NLS-1$
image.dispose();
}
}
finally {
if(zOut != null) {
try {
zOut.flush();
zOut.close();
}
catch(IOException ex) {
}
}
}
}

private String createManifest() throws IOException {
Document doc = new Document();
Element root = new Element(ITemplateXMLTags.XML_TEMPLATE_ELEMENT_MANIFEST);
doc.setRootElement(root);

// Type
root.setAttribute(ITemplateXMLTags.XML_TEMPLATE_ATTRIBUTE_TYPE, CanvasModelTemplate.XML_CANVAS_TEMPLATE_ATTRIBUTE_TYPE_MODEL);

// Timestamp
root.setAttribute(ITemplateXMLTags.XML_TEMPLATE_ATTRIBUTE_TIMESTAMP, Long.toString(System.currentTimeMillis()));
// Create a new template and create the manifest from that
ITemplate template = new CanvasModelTemplate();

// Name
Element elementName = new Element(ITemplateXMLTags.XML_TEMPLATE_ELEMENT_NAME);
elementName.setText(fTemplateName);
root.addContent(elementName);

// Description
Element elementDescription = new Element(ITemplateXMLTags.XML_TEMPLATE_ELEMENT_DESCRIPTION);
elementDescription.setText(fTemplateDescription);
root.addContent(elementDescription);

// Thumbnail
template.setName(fTemplateName);
template.setDescription(fTemplateDescription);
if(fIncludeThumbnail) {
String keyThumb = TemplateManager.ZIP_ENTRY_THUMBNAILS + "1.png"; //$NON-NLS-1$
Element elementKeyThumb = new Element(ITemplateXMLTags.XML_TEMPLATE_ELEMENT_KEY_THUMBNAIL);
elementKeyThumb.setText(keyThumb);
root.addContent(elementKeyThumb);
template.setKeyThumbnailPath(TemplateManager.ZIP_ENTRY_THUMBNAILS + "1.png"); //$NON-NLS-1$
}
return JDOMUtils.write2XMLString(doc);

return template.createManifest();
}

private File saveModelToTempFile() throws IOException {
Expand Down Expand Up @@ -245,19 +202,19 @@ private ICanvasModel createCanvasCopy(ICanvasModel canvasModel) {
ICanvasModel copyCanvas = EcoreUtil.copy(canvasModel);

// Gather up diagram model references
List<IDiagramModelReference> toRemove = new ArrayList<IDiagramModelReference>();
List<IDiagramModelReference> toRemove = new ArrayList<>();

for(Iterator<EObject> iter = copyCanvas.eAllContents(); iter.hasNext();) {
EObject eObject = iter.next();
// Diagram model references and their connections will be orphaned
if(eObject instanceof IDiagramModelReference) {
toRemove.add((IDiagramModelReference)eObject);
if(eObject instanceof IDiagramModelReference ref) {
toRemove.add(ref);
}
}

// Remove them
for(IDiagramModelReference eObject : toRemove) {
DiagramCommandFactory.createDeleteDiagramObjectCommand(eObject).execute();
for(IDiagramModelReference ref : toRemove) {
DiagramCommandFactory.createDeleteDiagramObjectCommand(ref).execute();
}

// Generate new IDs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.archimatetool.canvas.templates.model.CanvasTemplateManager;
import com.archimatetool.editor.ui.IArchiImages;
import com.archimatetool.editor.ui.UIUtils;
import com.archimatetool.editor.utils.PlatformUtils;
import com.archimatetool.editor.utils.StringUtils;
import com.archimatetool.templates.model.TemplateManager;
import com.archimatetool.templates.wizard.TemplateUtils;
Expand Down Expand Up @@ -246,7 +247,13 @@ public boolean includeThumbnail() {
private File chooseFile() {
FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
dialog.setText(Messages.SaveCanvasAsTemplateWizardPage_9);
dialog.setFilterExtensions(new String[] { "*" + fTemplateManager.getTemplateFileExtension(), "*.*" } ); //$NON-NLS-1$ //$NON-NLS-2$

// On Mac, the extension is appended to the file name again. This is because it's not a registered extension like *.png or *.xml
// Not setting filter extensions avoids this.
if(!PlatformUtils.isMac()) {
dialog.setFilterExtensions(new String[] { "*" + fTemplateManager.getTemplateFileExtension(), "*.*" } ); //$NON-NLS-1$ //$NON-NLS-2$
}

File file = new File(fFileTextField.getText());
dialog.setFileName(file.getName());

Expand Down
Loading

0 comments on commit 1fd45b6

Please sign in to comment.