# 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;
        }
    }

Copyright (c) 2016 Oracle
Content made available under the terms of Eclipse Public License.