blob: 4e6e53dabf8d60660be195a40f55fadcc9156595 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2008 The University of York.
*
* 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
**********************************************************************/
package org.eclipse.epsilon.picto;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.epsilon.picto.dom.Patch;
import org.eclipse.swt.graphics.Point;
public class ViewTree {
protected List<ViewTree> children = new ArrayList<>();
protected ContentPromise promise;
protected String name = "";
protected String format = "html";
protected String icon = "folder";
protected List<Patch> patches = new ArrayList<>();
protected ViewTree parent;
protected Point scrollPosition = new Point(0, 0);
protected ViewContent cachedContent = null;
protected List<Layer> layers = new ArrayList<>();
protected Set<java.net.URI> baseUris = new LinkedHashSet<>();
protected Integer position = null;
public ViewTree() {}
public ViewTree(String name) {
this.name = name;
}
public ViewTree(String content, String format) {
this.promise = new StaticContentPromise(content);
this.format = format;
}
public ViewTree(File file, String format) {
this.promise = new StaticContentPromise(file);
this.format = format;
}
public ViewTree(ContentPromise promise, String format, String icon, List<Patch> patches, List<Layer> layers) {
this(promise, format, icon, null, patches, layers);
}
public ViewTree(ContentPromise promise, String format, String icon, Integer position, List<Patch> patches, List<Layer> layers) {
this.promise = promise;
this.format = format;
this.icon = icon;
this.position = position;
this.patches = patches;
this.layers = layers;
}
public ViewTree add(List<String> path, ViewTree other) {
ViewTree child = null;
if (path.size() > 1) {
String name = path.get(0);
List<String> rest = path.subList(1, path.size());
for (ViewTree candidate : children) {
String candidateName = candidate.getName();
if (candidateName != null && candidateName.equals(name)) {
child = candidate;
break;
}
}
if (child == null) {
child = new ViewTree(name);
children.add(child);
}
child.add(rest, other);
}
else {
String firstPath = path.get(0);
for (ViewTree candidate : children) {
String candidateName = candidate.getName();
if (candidateName != null && candidateName.equals(firstPath)) {
child = candidate;
break;
}
}
if (child == null) {
child = other;
child.setName(firstPath);
children.add(child);
}
else {
child.setFormat(other.getFormat());
child.setPromise(other.getPromise());
child.setIcon(other.getIcon());
child.setPatches(other.getPatches());
child.setLayers(other.getLayers());
child.setPosition(other.getPosition());
}
}
return child;
}
public void ingest(ViewTree other) {
List<ViewTree> obsolete = new ArrayList<>();
List<ViewTree> fresh = new ArrayList<>(other.getChildren());
for (ViewTree child : getChildren()) {
ViewTree counterpart = null;
for (ViewTree otherChild : other.getChildren()) {
if (child.getName().equals(otherChild.getName())) {
counterpart = otherChild;
fresh.remove(counterpart);
if (counterpart.getPromise() == null) {
// there might be some content if programmatically defined
if (counterpart.getCachedContent() != null) {
child.setContent(counterpart.getCachedContent());
}
}
else {
child.setPromise(counterpart.getPromise());
}
child.setFormat(counterpart.getFormat());
child.setIcon(counterpart.getIcon());
preserveLayerState(child, counterpart);
child.setLayers(counterpart.getLayers());
child.setPatches(counterpart.getPatches());
child.setPosition(counterpart.getPosition());
child.ingest(counterpart);
}
}
if (counterpart == null) {
obsolete.add(child);
}
}
getChildren().removeAll(obsolete);
getChildren().addAll(fresh);
// maintain any base URIs aded in the new ViewTree
this.getBaseUris().addAll(other.getBaseUris());
}
protected void preserveLayerState(ViewTree existing, ViewTree _new) {
for (Layer newLayer : _new.getLayers()) {
Layer existingLayer = existing.getLayers().stream().filter(l -> l.getId().equals(newLayer.getId())).findFirst().orElse(null);
if (existingLayer != null) {
newLayer.setActive(existingLayer.isActive());
}
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ViewTree> getChildren() {
children.forEach(c -> c.setParent(this));
return children;
}
public void setParent(ViewTree parent) {
this.parent = parent;
}
public ViewTree getParent() {
return parent;
}
public ViewContent getContent() {
if (cachedContent == null) {
if (promise == null) {
cachedContent = new ViewContent(format, "", null, getLayers(), getPatches(), getBaseUris());
}
else {
try {
File file = promise instanceof StaticContentPromise ? ((StaticContentPromise) promise).getFile() : null;
cachedContent = new ViewContent(format, promise.getContent(), file, getLayers(), getPatches(), getBaseUris());
} catch (Exception e) {
cachedContent = new ViewContent("exception", e.getMessage(), null, getLayers(), getPatches(), getBaseUris());
}
}
}
return cachedContent;
}
public List<Patch> getPatches() {
return patches;
}
public void setPatches(List<Patch> patches) {
this.patches = patches;
}
public List<ViewContent> getContents(PictoView pictoView) {
List<ViewContent> viewContents = new ArrayList<>();
for (
ViewContent viewContent = getContent();
viewContent != null && viewContents.add(viewContent);
viewContent = viewContent.getNext(pictoView)
);
return viewContents;
}
/**
* Concatenates the result of {@link #getContents(PictoView)}
* where each {@link ViewContent#getText()}) is separated by a new line.
*
* @param pictoView
* @return
* @since 2.2
*/
public String getContentsText(PictoView pictoView) {
return getContents(pictoView).stream()
.map(ViewContent::getText)
.collect(Collectors.joining(System.lineSeparator()));
}
public void setPromise(ContentPromise promise) {
if (promise != this.promise) {
this.promise = promise;
cachedContent = null;
}
}
public ContentPromise getPromise() {
return promise;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getIcon() {
return icon;
}
public Point getScrollPosition() {
return scrollPosition;
}
public void setScrollPosition(Point scrollPosition) {
this.scrollPosition = scrollPosition;
}
public List<Layer> getLayers() {
return layers;
}
public void setLayers(List<Layer> layers) {
this.layers = layers;
}
@Override
public String toString() {
return render(this, "");
}
private static String render(ViewTree viewTree, String prefix) {
StringBuilder s = new StringBuilder();
String content = null;
if (viewTree.getPromise() != null) {
try {
content = viewTree.getPromise().getContent();
}
catch (Exception e) {
content = "ContentError";
}
if (content == null) {
content = "";
}
int preferredLength = 20;
if (content.length() > preferredLength) {
content = content.substring(0, preferredLength) + "...";
}
content = content.replace(System.lineSeparator(), " ");
}
s.append(String.format("%sViewTree(%s): %s\n", prefix, viewTree.getName(), content));
for (ViewTree child : viewTree.getChildren()) {
s.append(render(child, prefix + ">\t"));
}
return s.toString();
}
public List<String> getPath() {
List<String> path = new ArrayList<>();
if (parent != null) path.addAll(parent.getPath());
path.add(this.getName() + "");
return path;
}
public ViewTree forPath(List<String> path) {
if (path.get(0).equals(getName())) {
if (path.size() > 1) {
for (ViewTree child : getChildren()) {
ViewTree forPath = child.forPath(path.subList(1, path.size()));
if (forPath != null) return forPath;
}
}
else {
return this;
}
}
return null;
}
public ViewTree getFirstWithContent() {
if (promise != null) return this;
for (ViewTree child : getChildren()) {
ViewTree result = child.getFirstWithContent();
if (result != null) return result;
}
return null;
}
public void clearCache() {
cachedContent = null;
}
public Set<java.net.URI> getBaseUris() {
if (parent != null) {
return parent.getBaseUris();
}
return baseUris;
}
public void setContent(ViewContent content) {
cachedContent = content;
promise = null;
}
public ViewContent getCachedContent() {
return cachedContent;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
}