/******************************************************************************
* Copyright (c) 2016 Oracle
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Konstantin Komissarchik - initial implementation and ongoing maintenance
******************************************************************************/
package org.eclipse.sapphire.ui.forms;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import org.eclipse.sapphire.Listener;
import org.eclipse.sapphire.modeling.Status;
/**
* @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a>
*/
public final class ProblemsTraversalServiceData
{
static ProblemsTraversalServiceData EMPTY = new ProblemsTraversalServiceData();
private Entry first;
private Entry last;
private final Map<MasterDetailsContentNodePart,Entry> index;
private ProblemsTraversalServiceData()
{
this.index = Collections.emptyMap();
}
ProblemsTraversalServiceData( final MasterDetailsEditorPagePart page,
final Listener listener )
{
this.index = new IdentityHashMap<MasterDetailsContentNodePart,Entry>();
traverse( page.outline().getRoot(), listener );
}
private void traverse( final MasterDetailsContentNodePart node,
final Listener listener )
{
final Entry entry = new Entry();
if( this.first == null )
{
this.first = entry;
this.last = entry;
}
else
{
this.last.next = entry;
this.last = entry;
}
this.index.put( node, entry );
entry.node = node;
for( SectionPart section : node.getSections() )
{
if( node.visible() && section.visible() )
{
final Status.Severity severity = section.validation().severity();
if( severity == Status.Severity.ERROR )
{
entry.error = true;
}
else if( severity == Status.Severity.WARNING )
{
entry.warning = true;
}
}
section.attach( listener );
}
for( MasterDetailsContentNodePart child : node.nodes() )
{
traverse( child, listener );
}
node.attach( listener );
}
public MasterDetailsContentNodePart findNextProblem( final MasterDetailsContentNodePart reference,
final Status.Severity severity )
{
if( reference == null || ! ( severity == Status.Severity.ERROR || severity == Status.Severity.WARNING ) )
{
throw new IllegalArgumentException();
}
return ( severity == Status.Severity.ERROR ? findNextError( reference ) : findNextWarning( reference ) );
}
public MasterDetailsContentNodePart findNextError( final MasterDetailsContentNodePart reference )
{
if( reference == null )
{
throw new IllegalArgumentException();
}
Entry entry = this.index.get( reference );
if( entry != null )
{
entry = entry.next;
while( entry != null && ! entry.error )
{
entry = entry.next;
}
}
return ( entry == null ? null : entry.node );
}
public MasterDetailsContentNodePart findNextWarning( final MasterDetailsContentNodePart reference )
{
if( reference == null )
{
throw new IllegalArgumentException();
}
Entry entry = this.index.get( reference );
if( entry != null )
{
entry = entry.next;
while( entry != null && ! entry.warning )
{
entry = entry.next;
}
}
return ( entry == null ? null : entry.node );
}
@Override
public boolean equals( final Object obj )
{
if( obj instanceof ProblemsTraversalServiceData )
{
Entry x = this.first;
Entry y = ( (ProblemsTraversalServiceData) obj ).first;
while( x != null && y != null )
{
if( x.node != y.node || x.error != y.error || x.warning != y.warning )
{
return false;
}
x = x.next;
y = y.next;
}
if( x == null && y == null )
{
return true;
}
}
return false;
}
@Override
public int hashCode()
{
int result = 1;
Entry entry = this.first;
while( entry != null )
{
result = 31 * result + entry.node.hashCode() + Boolean.valueOf( entry.error ).hashCode() + Boolean.valueOf( entry.warning ).hashCode();
entry = entry.next;
}
return result;
}
private static final class Entry
{
public MasterDetailsContentNodePart node;
public boolean error;
public boolean warning;
public Entry next;
}
}