/*
* Copyright (C) 2011 Laurent Caillette
*
* This program 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 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/>.
*/
package org.novelang.treemangling.designator;
import java.util.List;
import org.novelang.common.Problem;
import org.novelang.common.SyntacticTree;
import org.novelang.common.tree.Treepath;
import org.novelang.designator.FragmentIdentifier;
import org.novelang.parser.NodeKind;
import org.novelang.parser.NodeKindTools;
/**
* Given a {@link Treepath} to some identifier-bearing tree, extracts a single identifier
* segment. The segment may be self-defining if the tree has a {@link NodeKind#ABSOLUTE_IDENTIFIER}
* as immediate child, or may rely on other segments in the parents.
* TODO: some cleanup as this seems to deal with defunct relative identifiers.
*
* @author Laurent Caillette
*/
public class SegmentExtractor
{
private final IdentifierDefinition identifierDefinition ;
private final String segment ;
/**
*
* @param treepath Path to the node that may carry some (implicit or explicit) identifier.
* @param problems a list of problems to add to one occurs.
*/
public SegmentExtractor(
final Treepath< SyntacticTree > treepath,
final List< Problem > problems
) {
final Treepath< SyntacticTree > pathToIdentifier =
DesignatorTools.findPathToExplicitIdentifier( treepath ) ;
final SyntacticTree tree = pathToIdentifier == null ?
null :
pathToIdentifier.getTreeAtEnd()
;
if( NodeKindTools.is( NodeKind.ABSOLUTE_IDENTIFIER, tree ) ) {
segment = extractSegment( tree ) ;
identifierDefinition = IdentifierDefinition.ABSOLUTE ;
} else {
String markerText ;
final SyntacticTree titleTree = DesignatorTools.findTitleTree( treepath.getTreeAtEnd() ) ;
if( titleTree == null ) {
markerText = null ;
} else {
try {
markerText = DesignatorTools.getMarkerText( titleTree ) ;
} catch( Exception e ) {
// Exception type is a bit wide but it's due to the signature of getMarkerText
// which delegates to a Renderer/Writer inside of which so many things can go wrong.
// Not sure this is a Problem (user input), may be a technical exception at this stage.
problems.add( Problem.createProblem( e ) ) ;
markerText = null ;
}
}
if( markerText == null ) {
segment = null ;
identifierDefinition = IdentifierDefinition.NONE ;
} else {
segment = markerText ;
identifierDefinition = IdentifierDefinition.IMPLICIT ;
}
}
}
private static String extractSegment( final SyntacticTree identifierTree ) {
return identifierTree.getChildAt( 0 ).getText() ;
}
public IdentifierDefinition getIdentifierDefinition() {
return identifierDefinition ;
}
public String getSegment() {
return segment ;
}
/*package*/ static FragmentIdentifier extract(
final FragmentIdentifier parentIdentifier,
final Treepath< SyntacticTree > pathToIdentifier
) {
final SyntacticTree identifierTree = pathToIdentifier.getTreeAtEnd() ;
if( NodeKind.ABSOLUTE_IDENTIFIER == identifierTree.getNodeKind() ) {
return new FragmentIdentifier( extractSegment( identifierTree ) ) ;
}
return null ;
}
}