Skip to content

Commit

Permalink
Create ByPropertyIdMap
Browse files Browse the repository at this point in the history
  • Loading branch information
Benestar committed May 7, 2015
1 parent 1e085d2 commit e01251e
Show file tree
Hide file tree
Showing 4 changed files with 887 additions and 0 deletions.
323 changes: 323 additions & 0 deletions src/ByPropertyIdArrayNew.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
<?php

namespace Wikibase\DataModel;

use InvalidArgumentException;
use OutOfBoundsException;
use Wikibase\DataModel\Entity\PropertyId;

/**
* Helper for managing objects grouped by property id.
*
* @since 0.2
*
* @license GNU GPL v2+
* @author Bene* < [email protected] >
*/
class ByPropertyIdArrayNew {

/**
* @var ByPropertyIdGrouper
*/
private $byPropertyIdGrouper;

/**
* @var PropertyIdProvider[]
*/
private $flatArray;

/**
* @param PropertyIdProvider[] $propertyIdProviders
*
* @throws InvalidArgumentException
*/
public function __construct( array $propertyIdProviders ) {
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $propertyIdProviders );
$this->flatArray = array();

foreach ( $this->byPropertyIdGrouper->getPropertyIds() as $propertyId ) {
$propertyIdProviders = $this->byPropertyIdGrouper->getByPropertyId( $propertyId );
$this->flatArray = array_merge( $this->flatArray, $propertyIdProviders );
}
}

/**
* @since 0.2
* @deprecated since 1.2
*/
public function buildIndex() {}

/**
* @since 0.2
* @deprecated since 1.2
*
* @param PropertyId $propertyId
* @return PropertyIdProvider[]
*
* @throws OutOfBoundsException
*/
public function getByPropertyId( PropertyId $propertyId ) {
return $this->byPropertyIdGrouper->getByPropertyId( $propertyId );
}

/**
* Returns the absolute index of an object or false if the object could not be found.
*
* @since 0.5
* @deprecated since 1.2
*
* @param object $object
* @return bool|int
*
* @throws RuntimeException
*/
public function getFlatArrayIndexOfObject( $object ) {
return array_search( $object, $this->flatArray, true );
}

/**
* @since 0.2
* @deprecated since 1.2
*
* @return PropertyId[]
*/
public function getPropertyIds() {
return $this->byPropertyIdGrouper->getPropertyIds();
}

/**
* Returns a list of all PropertyIdProvider instances grouped by their PropertyId.
*
* @since 0.2
*
* @return PropertyIdProvider[]
*/
public function toFlatArray() {
return $this->flatArray;
}

/**
* Returns the index of the given PropertyIdPovider in the flat array.
*
* @since 1.2
*
* @param PropertyIdProvider $propertyIdProvider
* @return int
*
* @throws OutOfBoundsException
*/
public function getIndex( PropertyIdProvider $propertyIdProvider ) {
$index = array_search( $propertyIdProvider, $this->flatArray, true );

if ( $index === false ) {
throw new OutOfBoundsException( 'The given PropertyIdProvider was not found.' );
}

return $index;
}

/**
* Adds the given PropertyIdProvider to the array at the given index.
*
* @since 0.2
*
* @param PropertyIdProvider $propertyIdProvider
* @param int $index
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
public function addObjectAtIndex( PropertyIdProvider $propertyIdProvider, $index ) {
$this->assertValidIndex( $index );

$groupIndices = $this->getFlatArrayGroupIndices();
$propertyId = $propertyIdProvider->getPropertyId();
$idSerialization = $propertyId->getSerialization();

if ( isset( $groupIndices[$idSerialization] ) ) {
$groupIndex = $groupIndices[$idSerialization];
$count = count( $this->byPropertyIdGrouper->getByPropertyId( $propertyId ) );
} else {
$groupIndex = 0;
$count = 0;
}

// if not inside of group also move property group
if ( $index < $groupIndex || $groupIndex + $count <= $index ) {
// find real index to insert
$index = $index === 0 ? 0 : $this->findNextIndex( $index );
$this->moveGroupInFlatArray( $groupIndex, $count, $index );
}

$this->addtoFlatArray( $propertyIdProvider, $index );
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $this->flatArray );
}

/**
* Removes the PropertyIdProvider at the given index and returns it.
*
* @since 1.2
*
* @param int $index
* @return PropertyIdProvider
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
public function removeAtIndex( $index ) {
$this->assertValidIndex( $index );

$object = $this->removeFromFlatArray( $index );
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $this->flatArray );

return $object;
}

/**
* Removes the given PropertyIdProvider and returns it.
*
* @since 1.2
*
* @param PropertyIdProvider $propertyIdProvider
* @return PropertyIdProvider
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
public function removeObject( PropertyIdProvider $propertyIdProvider ) {
return $this->removeAtIndex( $this->getIndex( $propertyIdProvider ) );
}

/**
* Moves a PropertyIdProvider from the old to the new index and returns it.
*
* @since 1.2
*
* @param int $oldIndex
* @param int $newIndex
* @return PropertyIdProvider
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
public function moveToIndex( $oldIndex, $newIndex ) {
$this->assertValidIndex( $oldIndex );
$this->assertValidIndex( $newIndex );

$object = $this->removeAtIndex( $oldIndex );
$this->addObjectAtIndex( $object, $newIndex );

return $object;
}

/**
* Moves the given PropertyIdProvider to the new index and returns it.
*
* @since 0.2
*
* @param PropertyIdProvider $propertyIdProvider
* @param int $index
* @return PropertyIdProvider
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
public function moveObjectToIndex( PropertyIdProvider $propertyIdProvider, $index ) {
return $this->moveToIndex( $this->getIndex( $propertyIdProvider ), $index );
}

/**
* Adds the object at the given index.
* @see array_splice
*
* @param PropertyIdProvider $propertyIdProvider
* @param int $index
*/
private function addtoFlatArray( PropertyIdProvider $propertyIdProvider, $index ) {
array_splice( $this->flatArray, $index, 0, array( $propertyIdProvider ) );
}

/**
* Removes the object at the given index and returns it.
* @see array_splice
*
* @param int $index
* @return PropertyIdProvider
*/
private function removeFromFlatArray( $index ) {
$objects = array_splice( $this->flatArray, $index, 1 );
return $objects[0];
}

/**
* Moves a list of objects with the given length from the start to the target index.
* @see array_splice
*
* @param int $start
* @param int $length
* @param int $target
*/
private function moveGroupInFlatArray( $start, $length, $target ) {
// make sure we do not exceed the limits
if ( $start < $target ) {
$target = $target - $length;
}

$objects = array_splice( $this->flatArray, $start, $length );
array_splice( $this->flatArray, $target, 0, $objects );
}

/**
* Finds the next index in the flat array which starts a new PropertyId group.
*
* @param int $index
* @return int
*/
private function findNextIndex( $index ) {
$groupIndices = $this->getFlatArrayGroupIndices();

foreach ( $groupIndices as $groupIndex ) {
if ( $groupIndex >= $index ) {
return $groupIndex;
}
}

return count( $this->flatArray );
}

/**
* Finds all indeces where a new PropertyId group starts.
*
* @return int[]
*/
private function getFlatArrayGroupIndices() {
$indices = array();
$index = 0;

foreach ( $this->byPropertyIdGrouper->getPropertyIds() as $propertyId ) {
$indices[$propertyId->getSerialization()] = $index;
$index += count( $this->byPropertyIdGrouper->getByPropertyId( $propertyId ) );
}

return $indices;
}

/**
* Asserts that the given paramter is a valid index.
*
* @param int $index
*
* @throws InvalidArgumentException
* @throws OutOfBoundsException
*/
private function assertValidIndex( $index ) {
if ( !is_int( $index ) ) {
throw new InvalidArgumentException( 'Only integer indices are supported.' );
}

if ( $index < 0 || $index > count( $this->flatArray ) ) {
throw new OutOfBoundsException( 'The index exceeds the array dimensions.' );
}
}

}
Loading

0 comments on commit e01251e

Please sign in to comment.