/*
* Created on Dec 22, 2004
*/
package org.openedit.links;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.openedit.page.Page;
import com.openedit.util.PathUtilities;
/**
* This keeps track of a list of Link objects: ie. <a href="sdsdfdf">sddsfsd</a>
* @author cburkey
*
*/
public class LinkTree implements Serializable
{
private static final long serialVersionUID = 766014286370105378L;
protected Link fieldRootLink;
protected Link fieldSelectedLink;
protected long fieldNextId;
protected long fieldLastModified;
protected Page fieldPage;
protected String fieldId;
protected LinkedList fieldCrumbs;
public LinkTree()
{
String a = "";
}
/**
* @param inString
* @return
*/
public Link getLink(String inId)
{
if (getRootLink() != null && getRootLink().getId() != null && getRootLink().getId().equals(inId))
{
return getRootLink();
}
if( getRootLink() == null)
{
return null;
}
return getRootLink().getDecendant(inId);
}
public List getLinkChildren(String inId)
{
Link link = getLink(inId);
if ( link != null)
{
return link.getChildren();
}
return null;
}
/**
* @return
*/
public List renderAsList()
{
if ( getRootLink() != null)
{
return getRootLink().list();
}
return null;
}
public Link getRootLink()
{
return fieldRootLink;
}
public void setRootLink(Link inRootLink)
{
fieldRootLink = inRootLink;
}
public Link getSelectedLink()
{
return findSelectedLink(getRootLink());
}
public List findSelectedParents(int inParentLevel)
{
//get the selected link
List parents = new ArrayList();
Link parent = getSelectedLink(); //Most specific on bottom
while ( parent != null )
{
parents.add(0,parent);
parent = parent.getParentLink();
}
parents.addAll(getCrumbs()); //Crumbs become more specific
if ( parents.size() > inParentLevel)
{
return parents.subList(inParentLevel, parents.size());
}
return null;
}
public Link findSelectedParentLink(int inParentLevel)
{
//get the selected link
List parents = new ArrayList();
Link parent = getSelectedLink();
while ( parent != null )
{
parents.add(0,parent);
parent = parent.getParentLink();
}
if ( parents.size() > inParentLevel)
{
Link selected = (Link)parents.get(inParentLevel);
return selected;
}
return getRootLink();
}
/**
* @param inRootLink
* @return
*/
private Link findSelectedLink(Link inRootLink)
{
if ( inRootLink == null)
{
return getRootLink();
}
if ( inRootLink.isSelected())
{
return inRootLink;
}
for (Iterator iter = inRootLink.getChildren().iterator(); iter.hasNext();)
{
Link element = (Link) iter.next();
Link link = findSelectedLink(element);
if ( link != null)
{
return link;
}
}
return null;
}
/**
* @param inLink
*/
public void removeLink(Link inLink)
{
if(inLink == null){
return;
}
Link parent = inLink.getParentLink();
if ( parent != null)
{
parent.removeChild( inLink );
}
else
{
setRootLink(null);
}
if( inLink.hasChildren())
{
for (Iterator iter = new ArrayList(inLink.getChildren()).iterator(); iter.hasNext();)
{
Link link = (Link) iter.next();
removeLink(link);
}
}
}
/**
* @param inLink
*/
public void moveUp(Link inLink)
{
Link parent = inLink.getParentLink();
if ( parent != null)
{
parent.moveUp(inLink);
}
}
/**
* @param inLink
*/
public void moveDown(Link inLink)
{
Link parent = inLink.getParentLink();
if ( parent != null)
{
parent.moveDown(inLink);
}
}
/**
* @param inLink
*/
public void moveRight(Link inLink)
{
//put it as a child of my upper brother
Link parent = inLink.getParentLink();
if( parent != null)
{
Link brother = parent.getChildAbove(inLink);
if ( brother != null)
{
parent.removeChild(inLink);
brother.addChild(inLink);
}
}
}
/**
* @param inLink
*/
public void moveLeft(Link inLink)
{
//pull it up one
Link parent1 = inLink.getParentLink();
if ( parent1 != null)
{
Link parent2 = parent1.getParentLink();
if ( parent2 != null)
{
parent1.removeChild(inLink);
parent2.addChildNearLocation(inLink, parent1);
}
}
}
/**
* @return
*/
public String nextId()
{
if( fieldNextId == 0)
{
fieldNextId = System.currentTimeMillis();
}
return String.valueOf(fieldNextId++);
}
public void changeLinkId(Link inLink, String inNewId)
{
inLink.setId(inNewId);
}
/**
* @param inParentId
* @param inLink
*/
public Link addLink(String inParentId, Link inLink)
{
if( getRootLink() == null || getRootLink().getId().equals(inLink.getId()))
//if we don't have a root or we're re-reading the root, then make this the root
{
setRootLink( inLink );
return inLink;
}
Link oldLink = getLink(inLink.getId());
if ( oldLink != null && oldLink.getParentLink() != null)
{
oldLink.getParentLink().removeChild(oldLink);
}
//find the parent node if none then use the root node
Link parentLink = getLink(inParentId);
if ( parentLink == null )
{
parentLink = getRootLink();
}
parentLink.addChild(inLink);
return inLink;
}
/**
* @param inPath
* @return
*/
public Link findSelectedLinkByUrl(String inPath)
{
if ( getRootLink() == null)
{
return null;
}
else if ( getRootLink().getUrl() != null && getRootLink().getUrl().equals( inPath ) )
{
return getRootLink();
}
Link selected = getSelectedLink();
if ( selected != null)
{
//look in all the parents first since this is faster
while( selected != null)
{
//loop up the tree and check each parent link.
//This keeps us near the place we where before
Link found = findLinkByUrl( inPath, selected );
if ( found != null)
{
return found;
}
selected = selected.getParentLink();
}
}
else
{
return findLinkByUrl( inPath, getRootLink() );
}
return null;
}
public Link findLinkByUrl( String inPath, Link inLink )
{
if ( inPath == null)
{
return null;
}
if ( inLink == null)
{
return null;
}
if ( inLink.getUrl() != null )
{
if (PathUtilities.match(inPath, inLink.getUrl()))
{
return inLink;
}
}
if ( inLink.hasChildren() )
{
for (Iterator iter = inLink.getChildren().iterator(); iter.hasNext();)
{
Link link = (Link) iter.next();
Link found = findLinkByUrl( inPath, link);
if ( found != null )
{
return found;
}
}
}
return null;
}
public String checkUnique( String inOriginal )
{
return checkUnique( inOriginal, inOriginal, 0);
}
/**
* @param inLinks
* @param inId
* @return
*/
private String checkUnique( String inOriginal, String inId, int count)
{
Link id = getLink(inId);
if ( id != null)
{
count ++;
return checkUnique(inOriginal,inOriginal + count,count);
}
if ( count > 0)
{
return inOriginal + count;
}
return inOriginal;
}
/**
* @param inSelectedLink
*/
public void setSelectedLink(String inSelectedLink)
{
Link link = getLink(inSelectedLink);
setSelectedLink( link );
}
public void setSelectedLink(Link link)
{
if ( link == null)
{
if( getCrumbs().size() > 0)
{
clearSelection( getSelectedLink() );
}
return;
}
else
{
clearCrumbs(); //We have hit a known place that can use normall crumbs
clearSelection( getRootLink() );
}
//Look for any children that may also have the same url. i.e. about.html could be in the about category
if ( link.hasChildren())
{
for (Iterator iter = link.getChildren().iterator(); iter.hasNext();)
{
Link child = (Link) iter.next();
Link hit = findLinkByUrl(link.getUrl(),child);
if ( hit != null )
{
hit.setSelected(true);
}
}
}
link.setSelected(true);
}
protected void clearSelection(Link inRootLink)
{
if( inRootLink == null)
{
return;
}
inRootLink.setSelected(false);
if ( inRootLink.hasChildren() )
{
for (Iterator iter = inRootLink.getChildren().iterator(); iter.hasNext();)
{
Link link = (Link) iter.next();
clearSelection(link);
}
}
}
/**
* @param inString
* @param inLink
* @param inI
*/
public Link insertLink(String inParentId, Link inLink)
{
//duplicate code above
Link oldLink = getLink(inLink.getId());
if ( oldLink != null && oldLink.getParentLink() != null)
{
oldLink.getParentLink().removeChild(oldLink);
}
if( getRootLink() == null )
{
setRootLink( inLink );
return inLink;
}
//find the parent node if none then use the root node
Link parentLink = getLink(inParentId);
if ( parentLink == null )
{
parentLink = getRootLink();
}
parentLink.insertChild(inLink);
return inLink;
}
/**
* @return
*/
public long getLastModified()
{
return fieldLastModified;
}
public void setLastModified(long inLastModified)
{
fieldLastModified = inLastModified;
}
public String findRedirect(String inPath)
{
Link link = findLinkByUrl(inPath, getRootLink() );
if ( link != null)
{
String redirectPath = link.getRedirectPath();
if (redirectPath != null)
{
//path /abc/345.html -> http://xyz/abc/345.html
int indestpath = redirectPath.indexOf("*"); //http://xyz/*
int inpath = link.getUrl().indexOf("*"); // /abc/*
if (indestpath > -1 && inpath > -1 )
{
//this is a dynamic redirect path
//http://xyz/
//take off a part of the path before the *?
String begin = redirectPath.substring(0,indestpath);
String ending = inPath.substring(inpath, inPath.length());
redirectPath = begin + ending;
}
return redirectPath;
}
}
return null;
}
public String getId()
{
return fieldId;
}
public void setId(String inId)
{
fieldId = inId;
}
public boolean isDraft() {
return getPage().isDraft();
}
public void clearCrumbs()
{
getCrumbs().clear();
}
public LinkedList getCrumbs()
{
if (fieldCrumbs == null)
{
fieldCrumbs = new LinkedList();
}
return fieldCrumbs;
}
public void setCrumbs(LinkedList inCrumbs)
{
fieldCrumbs = inCrumbs;
}
protected Link makeCrumb(String inPath, String inText)
{
Link link = new Link();
link.setPath(inPath);
link.setText(inText);
link.setId(inText);
link.setSelected(true);
return link;
}
public void addCrumb(String inPath, String inText)
{
Link link = makeCrumb(inPath, inText);
getCrumbs().add(link);
}
public void prependCrumb(String inPath, String inText)
{
Link link = makeCrumb(inPath, inText);
getCrumbs().addFirst(link);
}
public Page getPage()
{
return fieldPage;
}
public void setPage(Page inPage)
{
fieldPage = inPage;
}
public String getPath()
{
return getPage().getPath();
}
}