Sapphire Developer Guide > Services

ProblemsTraversalService

ProblemsTraversalService produces a problem-annotated traversal order through the content outline, which can be used to find the next error or warning from any location in the content outline.

An implementation of this service is provided with Sapphire. This service is not intended to be implemented by adopters.

ProblemsTraversalService extends DataService<ProblemsTraversalServiceData>
{
    MasterDetailsContentNode findNextProblem( MasterDetailsContentNode reference, Status.Severity severity )
    MasterDetailsContentNode findNextError( MasterDetailsContentNode reference )
    MasterDetailsContentNode findNextWarning( MasterDetailsContentNode reference )
}

Example

public class ShowNextErrorActionHandler extends SapphireActionHandler
{
    private ProblemsTraversalService service;

    @Override
    public void init( final SapphireAction action,
                      final ActionHandlerDef def )
    {
        super.init( action, def );

        final MasterDetailsContentNode node = (MasterDetailsContentNode) getPart();
        final MasterDetailsEditorPagePart page = node.nearest( MasterDetailsEditorPagePart.class );

        this.service = page.service( ProblemsTraversalService.class );

        final Listener listener = new Listener()
        {
            @Override
            public void handle( final Event event )
            {
                refreshVisibility();
            }
        };

        this.service.attach( listener );

        attach
        (
            new FilteredListener<DisposeEvent>()
            {
                @Override
                protected void handleTypedEvent( final DisposeEvent event )
                {
                    ShowNextErrorActionHandler.this.service.detach( listener );
                }
            }
        );

        refreshVisibility();
    }

    private void refreshVisibility()
    {
        final MasterDetailsContentNode node = (MasterDetailsContentNode) getPart();
        final MasterDetailsContentNode nextProblemNode = this.service.findNextError( node );

        setVisible( nextProblemNode != null );
    }

    private PropertyEditorPart findFirstError( final List<SectionPart> sections )
    {
        for( SectionPart section : sections )
        {
            final PropertyEditorPart res = findFirstError( section );

            if( res != null )
            {
                return res;
            }
        }

        return null;
    }

    private PropertyEditorPart findFirstError( final SapphirePart part )
    {
        if( part != null )
        {
            if( part instanceof PropertyEditorPart )
            {
                if( part.validation().severity() == Status.Severity.ERROR )
                {
                    return (PropertyEditorPart) part;
                }
            }
            else if( part instanceof FormPart )
            {
                for( SapphirePart p : ( (FormPart) part ).getChildParts() )
                {
                    final PropertyEditorPart result = findFirstError( p );

                    if( result != null )
                    {
                        return result;
                    }
                }
            }
            else if( part instanceof PageBookPart )
            {
                return findFirstError( ( (PageBookPart) part ).getCurrentPage() );
            }
        }

        return null;
    }

    @Override
    protected Object run( final SapphireRenderingContext context )
    {
        final MasterDetailsContentNode node = (MasterDetailsContentNode) getPart();
        final MasterDetailsContentNode nextProblemNode = this.service.findNextError( node );

        if( nextProblemNode != null )
        {
            nextProblemNode.select();

            final PropertyEditorPart firstProblemPropertyEditor = findFirstError( nextProblemNode.getSections() );

            if( firstProblemPropertyEditor != null )
            {
                firstProblemPropertyEditor.setFocus();
            }
        }

        return null;
    }
}