/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.consistency.repair;
import org.neo4j.kernel.impl.nioneo.store.Record;
import org.neo4j.kernel.impl.nioneo.store.RecordStore;
import org.neo4j.kernel.impl.nioneo.store.RelationshipRecord;
import static org.neo4j.consistency.repair.RelationshipChainDirection.NEXT;
import static org.neo4j.consistency.repair.RelationshipChainDirection.PREV;
public class RelationshipChainExplorer
{
public static final int none = Record.NO_NEXT_RELATIONSHIP.intValue();
private final RecordStore<RelationshipRecord> recordStore;
public RelationshipChainExplorer( RecordStore<RelationshipRecord> recordStore )
{
this.recordStore = recordStore;
}
public RecordSet<RelationshipRecord> exploreRelationshipRecordChainsToDepthTwo( RelationshipRecord record )
{
RecordSet<RelationshipRecord> records = new RecordSet<RelationshipRecord>();
for ( RelationshipNodeField nodeField : RelationshipNodeField.values() )
{
long nodeId = nodeField.get( record );
records.addAll( expandChains( expandChainInBothDirections( record, nodeId ), nodeId ) );
}
return records;
}
private RecordSet<RelationshipRecord> expandChains( RecordSet<RelationshipRecord> records, long otherNodeId )
{
RecordSet<RelationshipRecord> chains = new RecordSet<RelationshipRecord>();
for ( RelationshipRecord record : records )
{
chains.addAll( expandChainInBothDirections( record,
record.getFirstNode() == otherNodeId ? record.getSecondNode() : record.getFirstNode() ) );
}
return chains;
}
private RecordSet<RelationshipRecord> expandChainInBothDirections( RelationshipRecord record, long nodeId )
{
return expandChain( record, nodeId, PREV ).union( expandChain( record, nodeId, NEXT ) );
}
protected RecordSet<RelationshipRecord> followChainFromNode(long nodeId, long relationshipId )
{
RelationshipRecord record = recordStore.getRecord( relationshipId );
return expandChain( record, nodeId, NEXT );
}
private RecordSet<RelationshipRecord> expandChain( RelationshipRecord record, long nodeId,
RelationshipChainDirection direction )
{
RecordSet<RelationshipRecord> chain = new RecordSet<RelationshipRecord>();
chain.add( record );
RelationshipRecord currentRecord = record;
long nextRelId;
while ( currentRecord.inUse() &&
(nextRelId = direction.fieldFor( nodeId, currentRecord ).relOf( currentRecord )) != none ) {
currentRecord = recordStore.forceGetRecord( nextRelId );
chain.add( currentRecord );
}
return chain;
}
}