package com.smash.revolance.ui.model.sitemap;
/*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Revolance-UI-Model
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Copyright (C) 2012 - 2013 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.materials.JsonHelper;
import com.smash.revolance.ui.model.element.api.ElementBean;
import com.smash.revolance.ui.model.helper.BotHelper;
import com.smash.revolance.ui.model.helper.UrlHelper;
import com.smash.revolance.ui.model.page.IPage;
import com.smash.revolance.ui.model.page.api.Page;
import com.smash.revolance.ui.model.page.api.PageBean;
import com.smash.revolance.ui.model.user.UserBean;
import org.apache.commons.io.FileUtils;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.kohsuke.graphviz.Edge;
import org.kohsuke.graphviz.Graph;
import org.kohsuke.graphviz.Node;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* User: wsmash
* Date: 20/02/13
* Time: 10:43
*/
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
public class SiteMap
{
private long date = 0;
private HashMap<String, PageBean> sitemap = null;
@JsonIgnore
private static final String RED = "#FF0000";
@JsonIgnore
private static final String BLUE = "#0000FF";
@JsonIgnore
private static final String GRAY = "#222222";
@JsonIgnore
private static final String GREEN = "#00FF00";
@JsonIgnore
private static final String BLACK = "#000000";
private UserBean user;
/*
public File getSitemapDotFile() throws IOException
{
String sitemapDotFileName = "sitemap.dot";
return new File( user.getSitemapFolder(), sitemapDotFileName );
}
public File getSitemapImgFile() throws IOException
{
String sitemapImgFileName = "sitemap.svg";
return new File( user.getSitemapFolder(), sitemapImgFileName );
}
*/
private SiteMap()
{
sitemap = new HashMap();
}
public SiteMap(UserBean user)
{
this();
setUser( user );
}
private void setUser(UserBean user)
{
this.user = user;
}
/**
* Retrieve all the original pages of the application
*
* @return
*/
public Collection<PageBean> getPages()
{
return sitemap.values();
}
/**
* Retrieve the number of pages in the sitemap
*/
public int getPagesCount()
{
return getPages().size();
}
/**
* Retrieve a page. Either it's an original if first time asked for this page
* Or a variant of the original page when the url hasn't changed.
*
* @return
* @throws Exception
*/
public PageBean getPage(String url, boolean generate) throws Exception
{
PageBean page = findPageByUrl( url );
if ( page == null )
{
if ( generate )
{
page = Page.createPage( getUser().getInstance(), url, getUser().getInstance().getBot().getCurrentTitle() );
}
}
return page;
}
/**
* Only register pages that are original and not variant
*
* @param page
* @throws Exception
*/
public void addPage(Page page)
{
if ( page.isOriginal() )
{
sitemap.put( page.getUrl(), page.getBean() );
}
}
public PageBean findPageByUrl(String url)
{
if ( sitemap.isEmpty() )
{
return null;
} else
{
PageBean page = getPage( url );
if ( page != null )
{
if ( UrlHelper.containsHash( url ) )
{
String hash = UrlHelper.getHash( url );
return page.getInstance().findVariantByHash( hash );
}
}
return page;
}
}
private PageBean getPage(String url)
{
PageBean page = null;
for ( String urlRegistered : sitemap.keySet() )
{
if ( UrlHelper.areEquivalent(urlRegistered, url) )
{
return sitemap.get( urlRegistered );
}
}
return page;
}
public List<PageBean> getBrokenPages()
{
List<PageBean> brokenPages = new ArrayList<PageBean>();
for ( PageBean page : getPages() )
{
if ( page.isBroken() )
{
brokenPages.add( page );
}
}
return brokenPages;
}
public List<String> getBrokenLinks()
{
List<String> brokenLinks = new ArrayList<String>();
for ( PageBean page : getBrokenPages() )
{
brokenLinks.add( page.getSource().getContent() );
}
return brokenLinks;
}
public Graph convertToGraph(String title) throws Exception
{
Graph graph = new Graph();
graph.attr( "label", title );
graph.attr( "mindist", "15" );
graph.attr( "ratio", "auto" );
graph.attr( "overlap", "false" );
graph.attr( "ranksep", "15" );
graph.attr( "weight", "2" );
graph.attr( "splines", "true" );
graph.attr( "margin", "10" );
List<Edge> edges = new ArrayList<Edge>();
Map<String, Node> nodes = new HashMap<String, Node>();
for ( PageBean page : getPages() )
{
Node node = createNode( page );
graph.node( node );
nodes.put( page.getUrl(), node );
}
for ( PageBean page : getPages() )
{
for ( ElementBean link : page.getLinks() )
{
Edge edge = new Edge( nodes.get( page.getUrl() ), nodes.get( link.getHref() ) );
edge.attr( "label", link.getHref() );
if ( !isAlreadyDefined( edge, edges ) )
{
// if( Link.containsLink( page.getBrokenLinks(), link.getHref(), element.getLocation(), element.getSize()) )
// {
edge.attr( "color", RED );
// }
graph.edge( edge );
edges.add( edge );
}
}
}
/*
Map<Node, Integer> countsPos = new HashMap<Node, Integer>();
Map<Node, Integer> countsNeg = new HashMap<Node, Integer>();
for(Edge edge : edges)
{
if(!countsPos.containsKey(edge.dst))
{
countsPos.put( edge.dst, new Integer(0) );
}
countsPos.put(edge.dst, countsPos.get(edge.dst) + 1);
if(!countsNeg.containsKey(edge.src))
{
countsNeg.put( edge.src, new Integer(0) );
}
countsPos.put(edge.src, countsPos.get(edge.src) + 1);
}
Node nodePos = getMaxNode(countsPos);
Node nodeNeg = getMaxNode(countsNeg);
*/
return graph;
}
private Node getMaxNode(Map<Node, Integer> countsPos)
{
int max = 0;
Node nodeMaxPos = null;
boolean first = true;
for ( Node nodePos : countsPos.keySet() )
{
if ( first )
{
max = countsPos.get( nodePos );
nodeMaxPos = nodePos;
first = false;
continue;
}
if ( max < countsPos.get( nodePos ) )
{
max = countsPos.get( nodePos );
nodeMaxPos = nodePos;
}
}
return nodeMaxPos;
}
private boolean isAlreadyDefined(Edge edge, List<Edge> edges)
{
String label = edge.attr( "label" );
for ( Edge iterator : edges )
{
String dstLabel = iterator.attr( "label" );
boolean dstMatch = dstLabel.contentEquals( label );
if ( dstMatch )
{
return true;
}
}
return false;
}
private Node createNode(PageBean page) throws Exception
{
Node node = new Node();
String url = page.getUrl();
String urlString;
if ( url == null )
urlString = node.toString();
else
urlString = escape( url );
node.id( urlString );
node.attr( "label", page.getTitle() );
node.attr( "fixedsize", "true" );
node.attr( "height", String.valueOf( "4" ) );
node.attr( "width", String.valueOf( "3" ) );
node.attr( "shape", "box" );
if ( !page.isBroken() )
{
setColor( node, BLUE );
if ( page.isHome() )
{
setColor( node, GREEN );
}
} else
{
setColor( node, RED );
}
setImage( node, page.getCaption() );
setUrl( node, page.getUrl() );
return node;
}
private String escape(String string)
{
return "\"" + string + "\"";
}
private void setImage(Node node, String caption) throws IOException
{
if ( caption == null )
{
return;
}
// File root = user.getSitemapFolder();
// String relCaption = FileHelper.getRelativePath( root, caption );
node.attr( "image", caption );
}
private void setUrl(Node node, String url)
{
if ( url != null )
{
node.attr( "URL", url );
}
}
private void setColor(Node node, String color)
{
node.attr("color", color);
}
public void setHomeNode(Node node)
{
node.attr( "shape", "box" );
setColor( node, BLUE );
}
public String getDomain()
{
return user.getDomain();
}
public UserBean getUser()
{
return user;
}
public boolean isEmpty()
{
return sitemap.isEmpty();
}
public Collection<PageBean> getPagesWithVariations()
{
List<PageBean> pages = new ArrayList<PageBean>();
pages.addAll( getPages() );
for ( PageBean page : getPages() )
{
pages.addAll( page.getVariants() );
}
return pages;
}
public boolean hasBeenExplored(String url) throws Exception
{
PageBean page = findPage( url );
if ( page != null )
{
if ( page.getInstance().hasBeenExplored() )
{
return true;
}
else
{
for ( ElementBean element : page.getClickableContent() )
{
if ( !element.isBroken()
&& !element.hasBeenClicked()
&& element.getInstance().isClickable()
&& BotHelper.rightDomain(getUser().getDomain(), url))
{
return false;
}
}
return true;
}
}
else
{
return false;
}
}
public PageBean findPage(String url) throws Exception
{
PageBean page;
if ( url.isEmpty() )
{
return null;
}
else if ( !UrlHelper.containsHash( url ) )
{
page = findPageByUrl( url );
}
else
{
url = UrlHelper.removeHash( url );
page = findPageByUrl( url );
if ( page != null )
{
page = page.getInstance().findVariantByHash( UrlHelper.getHash( url ) );
}
}
return page;
}
public ElementBean getFirstUnexploredElement(String url) throws Exception
{
PageBean page = findPage( url );
if ( page == null )
{
return null;
}
else
{
if ( !page.getInstance().hasBeenExplored() )
{
for ( ElementBean element : page.getClickableContent() )
{
if ( !element.isBroken()
&& !element.hasBeenClicked()
&& element.getInstance().isClickable() )
{
return element;
}
}
}
return null;
}
}
public void delPage(IPage page)
{
if ( page.isOriginal() )
{
if ( sitemap.containsKey( page.getUrl() ) )
{
sitemap.remove( page.getUrl() );
}
}
}
public static SiteMap fromJson(File json) throws IOException
{
return fromJson( FileUtils.readFileToString( json ) );
}
public static SiteMap fromJson(String json) throws IOException
{
SiteMap sitemap = (SiteMap) JsonHelper.getInstance().map( SiteMap.class, json );
UserBean user = sitemap.getUser();
// Attach user and elements to the page
for ( PageBean page : sitemap.getPages() )
{
page.setUser( user );
for ( ElementBean element : page.getContent() )
{
element.setPage( page );
}
}
// Attach original page reference to each page
for ( PageBean originalPage : sitemap.getPages() )
{
for ( PageBean page : sitemap.getPages() )
{
if ( page.getOriginalPageId().contentEquals( originalPage.getId() ) )
{
page.setOriginal( originalPage );
}
}
}
return sitemap;
}
public void setHome(String home)
{
this.user.setHome( home );
}
public PageBean findPageByInternalId(String pageId)
{
for ( PageBean page : getPages() )
{
if ( page.getId().contentEquals( pageId ) )
{
return page;
}
}
return null;
}
public long getDate()
{
return date;
}
public void setDate(final long date)
{
this.date = date;
}
}