/*
* Bibliothek - DockingFrames
* Library built on Java/Swing, allows the user to "drag and drop"
* panels containing any Swing-Component the developer likes to add.
*
* Copyright (C) 2013 Benjamin Sigg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Benjamin Sigg
* benjamin_sigg@gmx.ch
* CH - Switzerland
*/
package bibliothek.gui.dock.extension.css.doc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Describes the location of a {@link DocProperty}.
* @author Benjamin Sigg
*/
public class DocPath {
/** the property whose path <code>this</code> is */
private DocProperty property;
/** all the nodes of this path */
private List<DocNode> nodes = new ArrayList<DocNode>();
/** the unsorted nodes of this path */
private List<DocNode> unordered = new ArrayList<DocNode>();
/** the actual path */
private CssDocPath path;
/** the parent path of <code>this</code> */
private DocPath parent;
/**
* Calculates the path of <code>property</code>.
* @param property the property whose path <code>this</code> represents.
* @param path the actual path
*/
public DocPath( DocProperty property, CssDocPath path ){
this.property = property;
add( path );
}
/**
* Gets the parent path of <code>this</code>.
* @return the parent path, can be <code>null</code>
*/
public DocPath getParent(){
return parent;
}
/**
* Gets the root of the documentation.
* @return the root
*/
public DocRoot getRoot(){
return property.getRoot();
}
/**
* Gets the documentation of this path.
* @return the documentation
*/
public DocText getDescription(){
return new DocText( getRoot(), path.description() );
}
/**
* Gets the sorted nodes, that appear exactly one time on the path.
* @return the sorted nodes
*/
public Iterable<DocNode> getNodes(){
return nodes;
}
/**
* Gets the nodes whose order and number of appearance is unknown.
* @return the unordered nodes
*/
public Iterable<DocNode> getUnordered(){
return unordered;
}
private void add( CssDocPath path ){
String refId = path.referenceId();
if( !refId.isEmpty() ){
add( getPathFor( refId, path.referencePath() ));
}
else{
unpack( path );
}
}
private void unpack( CssDocPath path ){
this.path = path;
for( CssDocPathNode node : path.nodes() ){
add( nodes, node );
}
for( CssDocPathNode node : path.unordered() ){
add( unordered, node );
}
String parentId = path.parentId();
if( !parentId.isEmpty() ){
parent = new DocPath( property, getPathFor( parentId, path.parentClass() ));
}
}
private CssDocPath getPathFor( String refId, Class<?> refClass ){
CssDocPath path;
if( refClass == Object.class ){
path = property.getClazz().getPath( refId );
}
else{
path = property.getRoot().get( refClass ).getPath( refId );
}
if( path == null ){
throw new IllegalArgumentException( "unknown ref: " + refId + " " + refClass );
}
return path;
}
private void add( Collection<DocNode> target, CssDocPathNode node ){
Class<?> refClass = node.reference();
if( refClass == Object.class ){
target.add( new DocNode( this, node ));
}
else{
CssDocPathNode replacement = refClass.getAnnotation( CssDocPathNode.class );
if( replacement == null ){
throw new IllegalArgumentException( "referenced " + refClass + " does not have any css-doc-path-nodes" );
}
add( target, replacement );
}
}
}