package com.smash.revolance.ui.server.controller;
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ui-monitoring-server
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Copyright (C) 2012 - 2014 RevoLance
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
import com.smash.revolance.ui.comparator.application.ApplicationComparison;
import com.smash.revolance.ui.comparator.application.IApplicationComparator;
import com.smash.revolance.ui.comparator.element.ElementDifferency;
import com.smash.revolance.ui.comparator.element.IElementComparator;
import com.smash.revolance.ui.comparator.page.IPageComparator;
import com.smash.revolance.ui.comparator.page.PageComparison;
import com.smash.revolance.ui.database.IStorage;
import com.smash.revolance.ui.database.StorageException;
import com.smash.revolance.ui.model.element.ElementNotFound;
import com.smash.revolance.ui.model.element.api.ElementBean;
import com.smash.revolance.ui.model.page.api.PageBean;
import com.smash.revolance.ui.model.sitemap.SiteMap;
import com.smash.revolance.ui.server.renderable.ApplicationDetailsRenderable;
import com.smash.revolance.ui.server.renderable.DetailedPageComparisonRenderable;
import com.smash.revolance.ui.server.renderable.PageComparisonRenderable;
import org.rendersnake.HtmlCanvas;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.rendersnake.HtmlAttributesFactory.*;
/**
* Created by ebour on 12/01/14.
*/
@Controller
public class ComparisonController
{
IStorage applications;
@Autowired
public void setApplications(IStorage applications)
{
this.applications = applications;
}
IApplicationComparator applicationComparator;
@Autowired
public void setApplicationComparator(IApplicationComparator applicationComparator)
{
this.applicationComparator = applicationComparator;
}
IPageComparator pageComparator;
@Autowired
public void setPageComparator(IPageComparator pageComparator)
{
this.pageComparator = pageComparator;
}
IElementComparator elementComparator;
@Autowired
public void setElementComparator(IElementComparator elementComparator)
{
this.elementComparator = elementComparator;
}
@RequestMapping(value = "/compare/{contentTagRef}/{contentTagNew}", method = RequestMethod.GET)
public ModelAndView renderComparison(@PathVariable String contentTagRef, @PathVariable String contentTagNew, @RequestParam(value="reviewId", defaultValue="") String reviewId, @ModelAttribute("model") ModelMap model) throws StorageException, IOException
{
if(contentTagNew.contentEquals(contentTagRef))
{
List<PageBean> pages = new ArrayList<PageBean>();
for ( PageBean page : SiteMap.fromJson( applications.retrieve( contentTagRef ) ).getPages() )
{
pages.add(page);
if ( page.hasVariants() )
{
pages.addAll(page.getVariants());
}
}
model.addAttribute( "applicationId", contentTagRef );
model.addAttribute("pagesCount", pages.size());
HtmlCanvas canvas = new HtmlCanvas();
new ApplicationDetailsRenderable(reviewId, pages).renderOn(canvas);
model.addAttribute( "pages", canvas.toHtml() );
return new ModelAndView( "ApplicationDetail", model );
}
else
{
model.addAttribute( "refAppTag", contentTagRef );
model.addAttribute( "newAppTag", contentTagNew );
SiteMap refSitemap = SiteMap.fromJson(applications.retrieve(contentTagRef));
SiteMap newSitemap = SiteMap.fromJson( applications.retrieve( contentTagNew ) );
ApplicationComparison comparison = applicationComparator.compare( refSitemap, newSitemap );
model.addAttribute( "pageComparisons", renderComparisonsWithRenderables( reviewId, contentTagRef, contentTagNew, comparison.getPageComparisons() ) );
model.addAttribute( "pageAdded", comparison.getAddedPages() );
model.addAttribute( "pageRemoved", comparison.getRemovedPages() );
return new ModelAndView( "ApplicationComparison", model );
}
}
@RequestMapping(value = "/compare/{contentTagRef}/{contentTagNew}/{pageRefId}/{pageNewId}", method = RequestMethod.GET)
public ModelAndView renderMergeView(@PathVariable String contentTagRef, @PathVariable String contentTagNew, @PathVariable String pageRefId, @PathVariable String pageNewId, @RequestParam(value="reviewId", defaultValue="") final String reviewId, @ModelAttribute("model") ModelMap model) throws StorageException, IOException
{
PageBean refPage = SiteMap.fromJson( applications.retrieve( contentTagRef ) ).findPageByInternalId(pageRefId);
PageBean newPage = SiteMap.fromJson( applications.retrieve( contentTagNew ) ).findPageByInternalId(pageNewId);
HtmlCanvas canvas = new HtmlCanvas();
if ( refPage != null && newPage != null )
{
PageComparison comparison = pageComparator.compare( newPage, refPage );
DetailedPageComparisonRenderable merge = new DetailedPageComparisonRenderable( reviewId, comparison, contentTagRef, contentTagNew );
merge.renderOn(canvas);
}
else
{
canvas.h1().content("Oups! An Internal error occurred. Unable to do this comparison.");
}
model.addAttribute( "content", canvas.toHtml() );
model.addAttribute( "refAppTag", contentTagRef );
model.addAttribute( "newAppTag", contentTagNew );
return new ModelAndView( "DetailedApplicationComparison", model );
}
@ResponseBody
@RequestMapping(value = "/compare/{contentTagRef}/{contentTagNew}/{pageRefId}/{pageNewId}/{refElementId}/{elementId}", method = RequestMethod.GET, headers="Accept=application/json")
public Collection<ElementDifferency> renderMergeView(@PathVariable String contentTagRef, @PathVariable String contentTagNew, @PathVariable String pageRefId, @PathVariable String pageNewId, @PathVariable String refElementId, @PathVariable String elementId) throws StorageException, IOException, ElementNotFound
{
ElementBean refElement = retrievePageElement(contentTagRef, pageRefId, refElementId);
ElementBean element = retrievePageElement(contentTagNew, pageNewId, elementId);
return elementComparator.compare(refElement, element);
}
private ElementBean retrievePageElement(String applicationId, String pageId, String elementId) throws StorageException, IOException, ElementNotFound
{
SiteMap sitemap = SiteMap.fromJson( applications.retrieve( applicationId ) );
PageBean page = sitemap.findPageByInternalId(pageId);
for(ElementBean e : page.getContent())
{
if(e.getInternalId().contentEquals(elementId))
{
return e;
}
}
throw new ElementNotFound("Element with id: '"+elementId+"' could not be found in page: '"+pageId+"' of application: '"+applicationId+"'.");
}
private List<String> renderComparisonsWithRenderables(String reviewId, String contentTagRef, String contentTagNew, List<PageComparison> pageComparisons) throws IOException
{
List<String> values = new ArrayList<String>();
int idx = 0;
for ( PageComparison comparison : pageComparisons )
{
StringWriter html = new StringWriter();
HtmlCanvas canvas = new HtmlCanvas( html );
canvas.tr( data( "id", String.valueOf( idx ) ).data( "variant-idx", "0" ) )
.td( colspan( "2" ) );
new PageComparisonRenderable(reviewId, comparison).renderOn(canvas);
if ( !comparison.getPageDifferencies().isEmpty() )
{
canvas.div( class_( "span2" ) )
.a( type( "button" )
.class_( "btn btn-info btn-small" )
.data( "row-id", String.valueOf( idx ) )
.data( "new-page-id", comparison.getMatch().getId() )
.data( "ref-page-id", comparison.getReference().getId() )
.href( "/ui-monitoring-server/compare/" + contentTagRef + "/" + contentTagNew + "/" + comparison.getReference().getId() + "/" + comparison.getMatch().getId() + "?reviewId="+reviewId ) )
.content( "Inspect" )
._div();
}
canvas._td()._tr();
idx++;
values.add( canvas.toHtml() );
}
return values;
}
}