package org.nocket.gen.domain.visitor.html.merge; import gengui.domain.AbstractDomainReference; import gengui.util.SevereGUIException; import java.io.File; import java.io.IOException; import java.util.ArrayDeque; import java.util.Deque; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.ecs.Element; import org.apache.ecs.html.FieldSet; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; import org.nocket.gen.domain.DMDWebGenContext; import org.nocket.gen.domain.element.ButtonElement; import org.nocket.gen.domain.element.CheckboxPropertyElement; import org.nocket.gen.domain.element.ChoicerPropertyElement; import org.nocket.gen.domain.element.DomainElementI; import org.nocket.gen.domain.element.HeadlineElement; import org.nocket.gen.domain.element.HiddenPropertyElement; import org.nocket.gen.domain.element.MultivaluePropertyElement; import org.nocket.gen.domain.element.ResourceElement; import org.nocket.gen.domain.element.SimplePropertyElement; import org.nocket.gen.domain.visitor.html.AbstractHtmlVisitor; import org.nocket.gen.domain.visitor.html.styling.common.StylingStrategyI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MergeHtmlVisitor<E extends AbstractDomainReference> extends AbstractHtmlVisitor<E> { final private static Logger log = LoggerFactory.getLogger(MergeHtmlVisitor.class); private final Deque<AbstractMergeLayer<?>> panelStack = new ArrayDeque<AbstractMergeLayer<?>>(); private final StylingStrategyI componentBuilder; protected final Document document; private String originalHtml; public MergeHtmlVisitor(DMDWebGenContext<E> context, StylingStrategyI componentBuilder) { super(context); this.componentBuilder = componentBuilder; try { String html = FileUtils.readFileToString(getHtmlFile()); this.document = Jsoup.parse(html); // Store original html to compare to during finishing process this.originalHtml = toHtml(document); org.jsoup.nodes.Element rootElement = determineRootElement(); panelStack.add(new DomElementMergeLayer(rootElement)); } catch (IOException e) { throw new SevereGUIException(e); } } protected org.jsoup.nodes.Element determineRootElement() { Elements forms = document.getElementsByTag("form"); if (forms.size() > 0) { return forms.get(forms.size() - 1); } Elements wicketExtends = document.getElementsByTag("wicket:extend"); if (wicketExtends.size() > 0) { return wicketExtends.get(wicketExtends.size() - 1); } Elements wicketPanels = document.getElementsByTag("wicket:panel"); if (wicketPanels.size() > 0) { return wicketPanels.get(wicketPanels.size() - 1); } Elements bodies = document.getElementsByTag("body"); if (bodies.size() > 0) { return bodies.get(bodies.size() - 1); } return document; } protected void maybeAdd(DomainElementI<E> e, Element... components) { if (document.getElementsByAttributeValue("wicket:id", e.getWicketId()).isEmpty()) { for (Element component : components) { panelStack.getLast().addElement(component); } } } @Override public void visitSimpleProperty(SimplePropertyElement<E> e) { Element input = componentBuilder.createSimpleProperty(e); maybeAdd(e, input); } @Override public void visitChoicerProperty(ChoicerPropertyElement<E> e) { Element select = componentBuilder.createChoicerProperty(e); maybeAdd(e, select); } @Override public void visitCheckboxProperty(CheckboxPropertyElement<E> e) { Element checkbox = componentBuilder.createCheckboxProperty(e); maybeAdd(e, checkbox); } @Override public void visitButton(ButtonElement<E> e) { Element button = componentBuilder.createButton(e); maybeAdd(e, button); } @Override public void visitResource(ResourceElement<E> e) { Element resource = componentBuilder.createResource(e); maybeAdd(e, resource); } @Override public void visitFieldsetOpen(HeadlineElement<E> e) { FieldSet fieldset = componentBuilder.createFieldset(e); panelStack.add(new MultiPartElementMergeLayer(fieldset)); } @Override public void visitMultivalueProperty(MultivaluePropertyElement<E> e) { Element table = componentBuilder.createMultivalueProperty(e); maybeAdd(e, table); } @Override public void visitFieldsetClose() { // on close there should always be a fieldset on top of stack MultiPartElementMergeLayer fieldset = (MultiPartElementMergeLayer) panelStack.removeLast(); if (fieldset == null) { throw new IllegalStateException("PanelStack improperly implemented, it should never become empty!"); } if (fieldset.getCountElements() > 0) { // this fieldset has elements, so we don't just throw it away AbstractMergeLayer<?> previousFieldset = panelStack.getLast(); previousFieldset.addElement(fieldset.getPanel()); } } @Override public void visitHiddenProperty(HiddenPropertyElement<E> e) { // ignore } @Override public void finish() { checkAndAddGroupTabbedPanel(document); String gen = toHtml(document); File file = getHtmlFile(); // Only save files with changes if (StringUtils.equals(gen, originalHtml)) { writeStatics(file.getName(), false, false, null); log.debug("No changes in file = " + file.getName()); return; } try { FileUtils.forceMkdir(file.getParentFile()); FileUtils.writeStringToFile(file, gen); writeStatics(file.getName(), false, true, null); } catch (IOException e) { writeStatics(file.getName(), false, false, e.getMessage()); throw new SevereGUIException(e); } } }