| /********************************************************************* |
| * Copyright (c) 2004, 2007 Boeing |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Boeing - initial API and implementation |
| **********************************************************************/ |
| |
| package org.eclipse.osee.framework.ui.skynet.render; |
| |
| import static org.eclipse.osee.framework.core.enums.CoreAttributeTypes.WordTemplateContent; |
| import static org.eclipse.osee.framework.core.enums.PresentationType.DEFAULT_OPEN; |
| import static org.eclipse.osee.framework.core.enums.PresentationType.GENERALIZED_EDIT; |
| import static org.eclipse.osee.framework.core.enums.PresentationType.GENERAL_REQUESTED; |
| import static org.eclipse.osee.framework.core.enums.PresentationType.PREVIEW; |
| import static org.eclipse.osee.framework.core.enums.PresentationType.SPECIALIZED_EDIT; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.InputStream; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import javax.xml.stream.XMLOutputFactory; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.osee.define.api.WordTemplateContentData; |
| import org.eclipse.osee.framework.core.client.ClientSessionManager; |
| import org.eclipse.osee.framework.core.data.ArtifactId; |
| import org.eclipse.osee.framework.core.data.AttributeTypeToken; |
| import org.eclipse.osee.framework.core.data.BranchId; |
| import org.eclipse.osee.framework.core.data.TransactionToken; |
| import org.eclipse.osee.framework.core.enums.CommandGroup; |
| import org.eclipse.osee.framework.core.enums.CoreAttributeTypes; |
| import org.eclipse.osee.framework.core.enums.CoreBranches; |
| import org.eclipse.osee.framework.core.enums.CoreRelationTypes; |
| import org.eclipse.osee.framework.core.enums.PresentationType; |
| import org.eclipse.osee.framework.core.model.type.LinkType; |
| import org.eclipse.osee.framework.core.operation.IOperation; |
| import org.eclipse.osee.framework.core.util.RendererOption; |
| import org.eclipse.osee.framework.core.util.WordMLProducer; |
| import org.eclipse.osee.framework.jdk.core.type.Pair; |
| import org.eclipse.osee.framework.jdk.core.util.xml.Jaxp; |
| import org.eclipse.osee.framework.logging.OseeLog; |
| import org.eclipse.osee.framework.skynet.core.artifact.Artifact; |
| import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery; |
| import org.eclipse.osee.framework.skynet.core.httpRequests.HttpWordUpdateRequest; |
| import org.eclipse.osee.framework.skynet.core.linking.OseeLinkBuilder; |
| import org.eclipse.osee.framework.skynet.core.word.WordUtil; |
| import org.eclipse.osee.framework.ui.skynet.MenuCmdDef; |
| import org.eclipse.osee.framework.ui.skynet.render.compare.IComparator; |
| import org.eclipse.osee.framework.ui.skynet.render.compare.WordTemplateCompare; |
| import org.eclipse.osee.framework.ui.skynet.render.word.WordTemplateProcessor; |
| import org.eclipse.osee.framework.ui.skynet.templates.TemplateManager; |
| import org.eclipse.osee.framework.ui.skynet.util.WordUiUtil; |
| import org.eclipse.osee.framework.ui.swt.Displays; |
| import org.eclipse.osee.framework.ui.swt.ImageManager; |
| import org.w3c.dom.Element; |
| |
| /** |
| * Renders WordML content. |
| * |
| * @author Jeff C. Phillips |
| */ |
| public class WordTemplateRenderer extends WordRenderer { |
| private static final String EMBEDDED_OBJECT_NO = "w:embeddedObjPresent=\"no\""; |
| private static final String EMBEDDED_OBJECT_YES = "w:embeddedObjPresent=\"yes\""; |
| private static final String STYLES = "<w:styles>.*?</w:styles>"; |
| private static final String STYLES_END = "</w:styles>"; |
| private static final String OLE_START = "<w:docOleData>"; |
| private static final String OLE_END = "</w:docOleData>"; |
| private static final String OPEN_IN_WORD = "MS Word"; |
| |
| private final WordTemplateProcessor templateProcessor; |
| private final IComparator comparator; |
| |
| public WordTemplateRenderer(Map<RendererOption, Object> options) { |
| super(options); |
| this.comparator = new WordTemplateCompare(this); |
| this.templateProcessor = new WordTemplateProcessor(this); |
| } |
| |
| public WordTemplateRenderer() { |
| this(new HashMap<RendererOption, Object>()); |
| } |
| |
| @Override |
| public WordTemplateRenderer newInstance() { |
| return new WordTemplateRenderer(new HashMap<RendererOption, Object>()); |
| } |
| |
| @Override |
| public WordTemplateRenderer newInstance(Map<RendererOption, Object> rendererOptions) { |
| return new WordTemplateRenderer(rendererOptions); |
| } |
| |
| public void publish(Artifact masterTemplateArtifact, Artifact slaveTemplateArtifact, List<Artifact> artifacts) { |
| templateProcessor.publishWithNestedTemplates(masterTemplateArtifact, slaveTemplateArtifact, artifacts); |
| } |
| |
| /** |
| * Displays a list of artifacts in the Artifact Explorer that could not be multi edited because they contained |
| * artifacts that had an OLEData attribute. |
| */ |
| private void displayNotMultiEditArtifacts(final Collection<Artifact> artifacts, final String warningString) { |
| if (!artifacts.isEmpty()) { |
| Displays.ensureInDisplayThread(new Runnable() { |
| @Override |
| public void run() { |
| WordUiUtil.displayUnhandledArtifacts(artifacts, warningString); |
| } |
| }); |
| } |
| } |
| |
| public static byte[] getFormattedContent(Element formattedItemElement) throws XMLStreamException { |
| ByteArrayOutputStream data = new ByteArrayOutputStream((int) Math.pow(2, 10)); |
| XMLStreamWriter xmlWriter = null; |
| try { |
| xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(data, "UTF-8"); |
| for (Element e : Jaxp.getChildDirects(formattedItemElement)) { |
| Jaxp.writeNode(xmlWriter, e, false); |
| } |
| } finally { |
| if (xmlWriter != null) { |
| xmlWriter.flush(); |
| xmlWriter.close(); |
| } |
| } |
| return data.toByteArray(); |
| } |
| |
| @Override |
| public int getApplicabilityRating(PresentationType presentationType, Artifact artifact, Map<RendererOption, Object> rendererOptions) { |
| int rating = NO_MATCH; |
| if (!presentationType.matches(GENERALIZED_EDIT, GENERAL_REQUESTED)) { |
| if (artifact.isAttributeTypeValid(CoreAttributeTypes.WordTemplateContent)) { |
| if (presentationType.matches(DEFAULT_OPEN, PREVIEW)) { |
| if (artifact.getAttributeCount(WordTemplateContent) > 0) { |
| rating = PRESENTATION_SUBTYPE_MATCH; |
| } else { |
| rating = SUBTYPE_TYPE_MATCH; |
| } |
| } else { |
| rating = PRESENTATION_SUBTYPE_MATCH; |
| } |
| } else if (presentationType.matches(PresentationType.DIFF) || (presentationType.matches( |
| PresentationType.PREVIEW) && !artifact.isAttributeTypeValid( |
| CoreAttributeTypes.WholeWordContent) && !artifact.isAttributeTypeValid( |
| CoreAttributeTypes.NativeContent))) { |
| if (OPEN_IN_WORD.equals(rendererOptions.get(RendererOption.OPEN_OPTION))) { |
| rating = PRESENTATION_TYPE_OPTION_MATCH; |
| } else { |
| rating = BASE_MATCH; |
| } |
| } |
| } |
| return rating; |
| } |
| |
| @Override |
| public void renderAttribute(AttributeTypeToken attributeType, Artifact artifact, PresentationType presentationType, WordMLProducer producer, String format, String label, String footer) { |
| WordMLProducer wordMl = producer; |
| |
| if (attributeType.equals(CoreAttributeTypes.WordTemplateContent)) { |
| String data = null; |
| LinkType linkType = (LinkType) getRendererOptionValue(RendererOption.LINK_TYPE); |
| |
| if (label.length() > 0) { |
| wordMl.addParagraph(label); |
| } |
| |
| TransactionToken txId = null; |
| if (artifact.isHistorical()) { |
| txId = artifact.getTransaction(); |
| } else { |
| txId = TransactionToken.SENTINEL; |
| } |
| |
| WordTemplateContentData wtcData = new WordTemplateContentData(); |
| wtcData.setArtId(artifact.getUuid()); |
| wtcData.setBranch(artifact.getBranch()); |
| wtcData.setFooter(presentationType != PresentationType.SPECIALIZED_EDIT ? footer : ""); |
| wtcData.setIsEdit(presentationType == PresentationType.SPECIALIZED_EDIT); |
| wtcData.setLinkType(linkType != null ? linkType.toString() : null); |
| wtcData.setTxId(txId); |
| wtcData.setPresentationType(presentationType); |
| ArtifactId view = (ArtifactId) getRendererOptionValue(RendererOption.VIEW); |
| wtcData.setViewId(view == null ? ArtifactId.SENTINEL : view); |
| wtcData.setPermanentLinkUrl( |
| String.format("http://%s:%s/", ClientSessionManager.getClientName(), ClientSessionManager.getClientPort())); |
| |
| Pair<String, Set<String>> content = null; |
| try { |
| content = HttpWordUpdateRequest.renderWordTemplateContent(wtcData); |
| } catch (Exception ex) { |
| WordUiUtil.displayErrorMessage(ex.toString()); |
| } |
| |
| if (content != null) { |
| data = content.getFirst(); |
| WordUiUtil.displayUnknownGuids(artifact, content.getSecond()); |
| } |
| |
| if (presentationType == PresentationType.SPECIALIZED_EDIT) { |
| OseeLinkBuilder linkBuilder = new OseeLinkBuilder(); |
| wordMl.addEditParagraphNoEscape(linkBuilder.getStartEditImage(artifact.getGuid())); |
| wordMl.addWordMl(data); |
| wordMl.addEditParagraphNoEscape(linkBuilder.getEndEditImage(artifact.getGuid())); |
| |
| } else if (data != null) { |
| wordMl.addWordMl(data); |
| } else if (footer != null) { |
| wordMl.addWordMl(footer); |
| } |
| wordMl.resetListValue(); |
| } else { |
| super.renderAttribute(attributeType, artifact, PresentationType.SPECIALIZED_EDIT, wordMl, format, label, |
| footer); |
| } |
| } |
| |
| @Override |
| public InputStream getRenderInputStream(PresentationType presentationType, List<Artifact> artifacts) { |
| final List<Artifact> notMultiEditableArtifacts = new LinkedList<>(); |
| Artifact template; |
| String templateContent = ""; |
| String templateOptions = ""; |
| String templateStyles = ""; |
| |
| if (artifacts.isEmpty()) { |
| // Still need to get a default template with a null artifact list |
| template = getTemplate(null, presentationType); |
| if (template != null) { |
| templateContent = template.getSoleAttributeValue(CoreAttributeTypes.WholeWordContent); |
| templateOptions = template.getSoleAttributeValue(CoreAttributeTypes.RendererOptions); |
| |
| List<Artifact> templateRelatedArtifacts = |
| template.getRelatedArtifacts(CoreRelationTypes.SupportingInfo_SupportingInfo); |
| |
| if (templateRelatedArtifacts.size() == 1) { |
| templateStyles = templateRelatedArtifacts.get(0).getSoleAttributeValueAsString( |
| CoreAttributeTypes.WholeWordContent, ""); |
| } else if (templateRelatedArtifacts.size() > 1) { |
| OseeLog.log(this.getClass(), Level.INFO, |
| "More than one style relation currently not supported. Defaulting to styles defined in the template."); |
| } |
| } |
| } else { |
| Artifact firstArtifact = artifacts.iterator().next(); |
| template = getTemplate(firstArtifact, presentationType); |
| if (template != null) { |
| templateContent = template.getSoleAttributeValue(CoreAttributeTypes.WholeWordContent); |
| templateOptions = template.getSoleAttributeValue(CoreAttributeTypes.RendererOptions); |
| |
| List<Artifact> templateRelatedArtifacts = |
| template.getRelatedArtifacts(CoreRelationTypes.SupportingInfo_SupportingInfo); |
| |
| if (templateRelatedArtifacts.size() == 1) { |
| templateStyles = templateRelatedArtifacts.get(0).getSoleAttributeValueAsString( |
| CoreAttributeTypes.WholeWordContent, ""); |
| } else if (templateRelatedArtifacts.size() > 1) { |
| OseeLog.log(this.getClass(), Level.INFO, |
| "More than one style relation currently not supported. Defaulting to styles defined in the template."); |
| } |
| } |
| |
| if (presentationType == PresentationType.SPECIALIZED_EDIT && artifacts.size() > 1) { |
| // currently we can't support the editing of multiple artifacts with OLE data |
| for (Artifact artifact : artifacts) { |
| if (!artifact.getSoleAttributeValue(CoreAttributeTypes.WordOleData, "").equals("")) { |
| notMultiEditableArtifacts.add(artifact); |
| } |
| } |
| displayNotMultiEditArtifacts(notMultiEditableArtifacts, |
| "Do not support editing of multiple artifacts with OLE data"); |
| artifacts.removeAll(notMultiEditableArtifacts); |
| } else { // support OLE data when appropriate |
| if (!firstArtifact.getSoleAttributeValue(CoreAttributeTypes.WordOleData, "").equals("")) { |
| templateContent = templateContent.replaceAll(EMBEDDED_OBJECT_NO, EMBEDDED_OBJECT_YES); |
| |
| //Add in new template styles now so OLE Data doesn't get lost |
| if (!templateStyles.isEmpty()) { |
| templateContent = templateContent.replace(STYLES, templateStyles); |
| templateStyles = ""; |
| } |
| |
| templateContent = templateContent.replaceAll(STYLES_END, |
| STYLES_END + OLE_START + firstArtifact.getSoleAttributeValue(CoreAttributeTypes.WordOleData, |
| "") + OLE_END); |
| } |
| } |
| } |
| |
| templateContent = WordUtil.removeGUIDFromTemplate(templateContent); |
| |
| return templateProcessor.applyTemplate(artifacts, templateContent, templateOptions, templateStyles, null, null, |
| (String) getRendererOptionValue(RendererOption.OUTLINE_TYPE), presentationType); |
| } |
| |
| protected Artifact getTemplate(Artifact artifact, PresentationType presentationType) { |
| // if USE_TEMPLATE_ONCE then only the first two artifacts will use the whole template (since they are diff'd with each other) |
| // The settings from the template are stored previously and will be used, just not the content of the Word template |
| |
| boolean useTemplateOnce = (boolean) getRendererOptionValue(RendererOption.USE_TEMPLATE_ONCE); |
| boolean firstTime = (boolean) getRendererOptionValue(RendererOption.FIRST_TIME); |
| boolean secondTime = (boolean) getRendererOptionValue(RendererOption.SECOND_TIME); |
| String option = (String) getRendererOptionValue(RendererOption.TEMPLATE_OPTION); |
| ArtifactId templateArt = (ArtifactId) getRendererOptionValue(RendererOption.TEMPLATE_ARTIFACT); |
| |
| if (option != null && option.toString().isEmpty()) { |
| option = null; |
| } |
| |
| if (templateArt != null && templateArt.isValid() && (!useTemplateOnce || useTemplateOnce && (firstTime || secondTime))) { |
| if (useTemplateOnce) { |
| if (secondTime) { |
| updateOption(RendererOption.SECOND_TIME, false); |
| } |
| if (firstTime) { |
| updateOption(RendererOption.FIRST_TIME, false); |
| updateOption(RendererOption.SECOND_TIME, true); |
| } |
| } |
| |
| if (templateArt instanceof Artifact) { |
| return (Artifact) templateArt; |
| } else { |
| return ArtifactQuery.getArtifactFromId(templateArt, CoreBranches.COMMON); |
| } |
| |
| } |
| if (useTemplateOnce && !firstTime && !secondTime) { |
| option = null; |
| } |
| return TemplateManager.getTemplate(this, artifact, presentationType, option); |
| } |
| |
| @Override |
| public IComparator getComparator() { |
| return comparator; |
| } |
| |
| @Override |
| protected IOperation getUpdateOperation(File file, List<Artifact> artifacts, BranchId branch, PresentationType presentationType) { |
| return new UpdateArtifactOperation(file, artifacts, branch, false); |
| } |
| |
| @Override |
| public void addMenuCommandDefinitions(ArrayList<MenuCmdDef> commands, Artifact artifact) { |
| Map<String, String> wordMenuSettings = new HashMap<String, String>(); |
| wordMenuSettings.put(RendererOption.OPEN_OPTION.getKey(), OPEN_IN_WORD); |
| ImageDescriptor imageDescriptor = ImageManager.getProgramImageDescriptor("doc"); |
| commands.add( |
| new MenuCmdDef(CommandGroup.EDIT, SPECIALIZED_EDIT, "MS Word Edit", imageDescriptor, wordMenuSettings)); |
| commands.add(new MenuCmdDef(CommandGroup.PREVIEW, PREVIEW, "MS Word Preview", imageDescriptor, wordMenuSettings)); |
| commands.add(new MenuCmdDef(CommandGroup.PREVIEW, PREVIEW, "MS Word Preview with children", imageDescriptor, |
| RendererOption.TEMPLATE_OPTION.getKey(), RendererOption.PREVIEW_WITH_RECURSE_VALUE.getKey(), |
| wordMenuSettings)); |
| commands.add(new MenuCmdDef(CommandGroup.PREVIEW, PREVIEW, "MS Word Preview (No Attr)", imageDescriptor, |
| RendererOption.TEMPLATE_OPTION.getKey(), RendererOption.PREVIEW_ALL_NO_ATTRIBUTES_VALUE.getKey(), |
| wordMenuSettings)); |
| commands.add(new MenuCmdDef(CommandGroup.PREVIEW, PREVIEW, "MS Word Preview with children (No Attr)", |
| imageDescriptor, RendererOption.TEMPLATE_OPTION.getKey(), |
| RendererOption.PREVIEW_WITH_RECURSE_NO_ATTRIBUTES_VALUE.getKey(), wordMenuSettings)); |
| } |
| |
| } |