package bluej.stride.framedjava.elements;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

import bluej.stride.framedjava.ast.HighlightedBreakpoint;
import bluej.stride.framedjava.ast.JavaContainerDebugHandler;
import bluej.stride.framedjava.ast.JavaFragment;
import bluej.stride.framedjava.ast.JavaSingleLineDebugHandler;
import bluej.stride.framedjava.ast.JavaSource;
import bluej.stride.framedjava.ast.Loader;
import bluej.stride.framedjava.frames.DebugInfo;
import bluej.stride.generic.Frame;
import bluej.stride.generic.Frame.ShowReason;
import bluej.stride.generic.InteractionManager;
import bluej.stride.generic.SandwichCanvasesFrame;
import bluej.utility.Utility;

import nu.xom.Element;
import nu.xom.Elements;
import threadchecker.OnThread;
import threadchecker.Tag;

public abstract class SandwichCanvasesElement
extends ContainerCodeElement implements JavaSingleLineDebugHandler{    
   private SandwichCanvasesFrame frame;

   
   private final String frameCaption;
   
   private final String intermediateCanvasElement;
   
   private final String intermediateCanvasJavaCaption;
   
   private final String tailCanvasCaption;

   
   private List<CodeElement> firstCanvasContents;
   
   private List<List<CodeElement>> intermediateCanvasContents;
   
   private List<CodeElement> tailCanvasContents;

   
   protected SandwichCanvasesElement(String frameCaption, String intermediateCanvasElement,
                                     
   String intermediateCanvasJavaCaption, String tailCanvasCaption)
   {        
      this.frameCaption = frameCaption;
       
      this.intermediateCanvasElement = intermediateCanvasElement;
       
      this.intermediateCanvasJavaCaption = intermediateCanvasJavaCaption;
       
      this.tailCanvasCaption = tailCanvasCaption;     
      }

   
   
| | @param frame | @param firstCanvasContents | @param intermediateCanvasContents | @param tailCanvasContents Note that passing null here means no tailCanvas, whereas passing | an empty list indicates that there is a tailCanvas, but it is empty. | protected SandwichCanvasesElement(SandwichCanvasesFrame frame, String frameCaption, List<CodeElement> firstCanvasContents, String intermediateCanvasElement, String intermediateCanvasJavaCaption, List<List<CodeElement>> intermediateCanvasContents, String tailCanvasCaption, List<CodeElement> tailCanvasContents, boolean enabled) { this(frameCaption, intermediateCanvasElement, intermediateCanvasJavaCaption, tailCanvasCaption); this.frame = frame; this.firstCanvasContents = firstCanvasContents; this.firstCanvasContents.forEach(c -> c.setParent(this)); this.intermediateCanvasContents = intermediateCanvasContents; this.intermediateCanvasContents.forEach(cs -> cs.forEach(c -> c.setParent(this))); this.tailCanvasContents = tailCanvasContents; if (this.tailCanvasContents != null) { this.tailCanvasContents.forEach(c -> c.setParent(this)); } this.enable = enabled; } public void loadElement(Element el) { loadMainAttributes(el); firstCanvasContents = new ArrayList<>(); Element firstStatementsEl = el.getChildElements(frameCaption + "Statements").get(0); for (int i = 0; i < firstStatementsEl.getChildElements().size(); i++) { final Element child = firstStatementsEl.getChildElements().get(i); CodeElement member = Loader.loadElement(child); firstCanvasContents.add(member); member.setParent(this); } intermediateCanvasContents = new ArrayList<>(); Elements intermediateCanvasElements = el.getChildElements(intermediateCanvasElement); for (int i = 0; i < intermediateCanvasElements.size(); i++) { final Element intermediateEl = intermediateCanvasElements.get(i); loadIntermediateAttributes(intermediateEl); List<CodeElement> body = new ArrayList<>(); for (int j = 0; j < intermediateEl.getChildElements().size(); j++) { CodeElement member = Loader.loadElement(intermediateEl.getChildElements().get(j)); body.add(member); member.setParent(this); } intermediateCanvasContents.add(body); } if (el.getChildElements(tailCanvasCaption).size() == 1) { tailCanvasContents = new ArrayList<>(); Element tailCanvasEl = el.getChildElements(tailCanvasCaption).get(0); for (int i = 0; i < tailCanvasEl.getChildElements().size(); i++) { final Element child = tailCanvasEl.getChildElements().get(i); CodeElement member = Loader.loadElement(child); tailCanvasContents.add(member); member.setParent(this); } } else if (el.getChildElements(tailCanvasCaption).size() == 0) { tailCanvasContents = null; } else { throw new IllegalArgumentException(); } enable = Boolean.valueOf(el.getAttributeValue("enable")); } protected abstract void loadMainAttributes(final Element element); protected abstract void loadIntermediateAttributes(final Element element); @Override public JavaSource toJavaSource() { JavaContainerDebugHandler firstCanvasHandler = debug -> frame.getFirstCanvasDebug().showDebugAtEnd(debug); JavaSource src = JavaSource.createCompoundStatement(frame, this, this, firstCanvasHandler, getFirstHeaderFragment(), CodeElement.toJavaCodes(firstCanvasContents)); for (int i = 0; i < intermediateCanvasContents.size(); i++) { final int iFinal = i; JavaContainerDebugHandler intermediateCanvasHandler = debug -> frame.getIntermediateCanvasDebug(iFinal).showDebugAtEnd(debug); src.append(JavaSource.createCompoundStatement(frame, this, this, intermediateCanvasHandler, getIntermediateHeaderFragment(i), CodeElement.toJavaCodes(intermediateCanvasContents.get(i)))); } if (tailCanvasContents != null) { JavaContainerDebugHandler tailCanvasHandler = debug -> frame.getTailCanvasDebug().showDebugAtEnd(debug); src.append(JavaSource.createCompoundStatement(frame, this, this, tailCanvasHandler, Arrays.asList(f(frame, tailCanvasCaption)), CodeElement.toJavaCodes(tailCanvasContents))); } return src; } protected List getFirstHeaderFragment() { return new ArrayList<>(Arrays.asList(f(frame, frameCaption))); } protected List getIntermediateHeaderFragment(int index) { return new ArrayList<>(Arrays.asList(f(frame, intermediateCanvasJavaCaption))); } @Override public LocatableElement toXML() { LocatableElement mainEl = new LocatableElement(this, frameCaption); addMainAttributes(mainEl); addEnableAttribute(mainEl); Element firstCanvasStatementsEl = new Element(frameCaption + "Statements"); firstCanvasContents.forEach(c -> firstCanvasStatementsEl.appendChild(c.toXML())); mainEl.appendChild(firstCanvasStatementsEl); for (int i = 0; i < intermediateCanvasContents.size(); i++) { LocatableElement intermediateCanvasEl = new LocatableElement(null, intermediateCanvasElement); addIntermediateAttributes(intermediateCanvasEl, i); intermediateCanvasContents.get(i).forEach(f -> intermediateCanvasEl.appendChild(f.toXML())); mainEl.appendChild(intermediateCanvasEl); } if (tailCanvasContents != null) { Element tailCanvasEl = new Element(tailCanvasCaption); tailCanvasContents.forEach(c -> tailCanvasEl.appendChild(c.toXML())); mainEl.appendChild(tailCanvasEl); } return mainEl; } protected abstract void addMainAttributes(LocatableElement element); protected abstract void addIntermediateAttributes(LocatableElement element, int index); @Override public Frame createFrame(InteractionManager editor) { Function<CodeElement, Frame> makeFrame = e -> e.createFrame(editor); frame = buildFrame(editor, Utility.mapList(firstCanvasContents, makeFrame), Utility.mapList(intermediateCanvasContents, cs -> Utility.mapList(cs, makeFrame)), tailCanvasContents == null ? null : Utility.mapList(tailCanvasContents, makeFrame), isEnable() ); return frame; } @OnThread(Tag.FX) protected abstract SandwichCanvasesFrame buildFrame(InteractionManager editor, List<Frame> firstCanvasFrames, List<List<Frame>> intermediateCanvasFrames, List<Frame> tailCanvasFrames, boolean enable); @Override public List childrenUpTo(CodeElement c) { if (firstCanvasContents.contains(c)) { return firstCanvasContents.subList(0, firstCanvasContents.indexOf(c)); } if (intermediateCanvasContents != null) { for (List<CodeElement> intermediateCanvasContent : intermediateCanvasContents) { if (intermediateCanvasContent.contains(c)) { return intermediateCanvasContent.subList(0, intermediateCanvasContent.indexOf(c)); } } } if (tailCanvasContents != null && tailCanvasContents.contains(c)) { return tailCanvasContents.subList(0, tailCanvasContents.indexOf(c)); } throw new IllegalArgumentException(); } @Override public HighlightedBreakpoint showDebugBefore(DebugInfo debug) { return frame.showDebugBefore(debug); } @Override public void show(ShowReason reason) { frame.show(reason); } @Override public Stream streamContained() { Stream<CodeElement> intermediateCanvasStream = intermediateCanvasContents.stream().flatMap(c -> streamContained(c)); return Utility.concat(streamContained(firstCanvasContents), intermediateCanvasStream, streamContained(tailCanvasContents)); }
| If the child is a direct member of an intermediate canvas, return its index, | otherwise return empty optional | protected Optional findDirectIntermediateChild(CodeElement child) { for (int i = 0; i < intermediateCanvasContents.size(); i++) { if (intermediateCanvasContents.get(i).stream().anyMatch(c -> c == child)) return Optional.of(i); } return Optional.empty(); } }
top, use, map, abstract class SandwichCanvasesElement

.   SandwichCanvasesElement
.   SandwichCanvasesElement
.   loadElement
.   loadMainAttributes
.   loadIntermediateAttributes
.   toJavaSource
.   getFirstHeaderFragment
.   getIntermediateHeaderFragment
.   toXML
.   addMainAttributes
.   addIntermediateAttributes
.   createFrame
.   buildFrame
.   childrenUpTo
.   showDebugBefore
.   show
.   streamContained
.   findDirectIntermediateChild




319 neLoCode + 7 LoComm