/*
* JacORB - a free Java ORB
*
* Copyright (C) 1999-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package org.jacorb.collection;
import org.jacorb.collection.util.ObjectInvalid;
import org.jacorb.collection.util.SortedVector;
import org.omg.CORBA.Any;
import org.omg.CORBA.AnyHolder;
import org.omg.CosCollection.AnySequenceHolder;
import org.omg.CosCollection.ElementInvalid;
import org.omg.CosCollection.ElementInvalidReason;
import org.omg.CosCollection.EmptyCollection;
import org.omg.CosCollection.IteratorInBetween;
import org.omg.CosCollection.IteratorInvalid;
import org.omg.CosCollection.KeyCollection;
import org.omg.CosCollection.KeyInvalid;
import org.omg.CosCollection.KeySortedCollectionOperations;
import org.omg.CosCollection.OperationsOperations;
import org.omg.CosCollection.PositionInvalid;
import org.omg.PortableServer.POA;
class KeySortedCollectionImpl extends OrderedCollectionImpl implements KeySortedCollectionOperations {
protected SortedVector keys;
protected KeyNode test_key = new KeyNode();
/* ========================================================================= */
KeySortedCollectionImpl( OperationsOperations ops, POA poa, IteratorFactory iterator_factory ){
super( ops, poa, iterator_factory );
keys = new SortedVector( new KeyComparator( ops ) );
};
/* ========================================================================= */
public org.omg.CORBA.TypeCode key_type(){
return ops.key_type();
};
/* ------------------------------------------------------------------------- */
public synchronized boolean contains_element_with_key(Any key) throws KeyInvalid{
check_key( key );
test_key.key = key;
try {
if( keys.indexOf( test_key ) >= 0 ){
return true;
} else {
return false;
}
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean contains_all_keys_from(KeyCollection collector) throws KeyInvalid{
throw new org.omg.CORBA.NO_IMPLEMENT();
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_or_add_element_with_key(Any element) throws ElementInvalid{
check_element( element );
test_key.key = ops.key( element );
try {
if( keys.indexOf( test_key ) < 0 ){
return add_element( element );
};
return false;
} catch ( ObjectInvalid e ){
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_or_add_element_with_key_set_iterator(Any element,org.omg.CosCollection. Iterator where) throws ElementInvalid,IteratorInvalid{
check_element( element );
test_key.key = ops.key( element );
try {
if( keys.indexOf( test_key ) < 0 ){
return add_element_set_iterator( element, where );
};
return false;
} catch ( ObjectInvalid e ){
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean add_or_replace_element_with_key(Any element) throws ElementInvalid{
check_element( element );
test_key.key = ops.key( element );
try {
int pos = keys.indexOf( test_key );
pos = ((KeyNode)keys.elementAt( pos )).start_position;
if( pos < 0 ){
return add_element( element );
} else {
element_replace( pos, element );
return false;
}
} catch ( ObjectInvalid e ) {
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
} catch ( PositionInvalid e ) {
throw new ElementInvalid( ElementInvalidReason.positioning_property_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean add_or_replace_element_with_key_set_iterator(Any element, org.omg.CosCollection.Iterator where) throws ElementInvalid,IteratorInvalid{
check_element( element );
test_key.key = ops.key( element );
try {
int pos = keys.indexOf( test_key );
pos = ((KeyNode)keys.elementAt( pos )).start_position;
if( pos < 0 ){
return add_element_set_iterator( element, where );
} else {
PositionalIteratorImpl i = check_iterator( where );
element_replace( pos, element );
i.set_pos(pos);
i.set_in_between( false );
return false;
}
} catch ( ObjectInvalid e ){
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
} catch ( PositionInvalid e ) {
throw new ElementInvalid( ElementInvalidReason.positioning_property_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean remove_element_with_key(Any key) throws KeyInvalid{
check_key( key );
test_key.key = key;
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return false;
}
pos = ((KeyNode)keys.elementAt( pos )).start_position;
element_remove( pos );
return true;
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
} catch ( EmptyCollection e ){
throw new KeyInvalid();
} catch ( PositionInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized int remove_all_elements_with_key(Any key) throws KeyInvalid{
check_key( key );
test_key.key = key;
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return 0;
}
KeyNode node = (KeyNode)keys.elementAt( pos );
pos = node.start_position;
for( int i=node.count; i>0; i-- ){
element_remove( pos+i-1 );
};
return node.count;
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
} catch ( EmptyCollection e ){
throw new KeyInvalid();
} catch ( PositionInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean replace_element_with_key(Any element) throws ElementInvalid{
check_element( element );
test_key.key = ops.key( element );
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return false;
}
KeyNode node = (KeyNode)keys.elementAt( pos );
pos = node.start_position;
element_replace( pos, element );
return true;
} catch ( ObjectInvalid e ){
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
} catch ( PositionInvalid e ){
throw new ElementInvalid( ElementInvalidReason.positioning_property_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean replace_element_with_key_set_iterator(Any element, org.omg.CosCollection.Iterator where) throws ElementInvalid,IteratorInvalid{
check_element( element );
PositionalIteratorImpl i = check_iterator( where );
test_key.key = ops.key( element );
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return false;
}
KeyNode node = (KeyNode)keys.elementAt( pos );
pos = node.start_position;
element_replace( pos, element );
i.set_pos( pos );
i.set_in_between( false );
return true;
} catch ( ObjectInvalid e ){
throw new ElementInvalid( ElementInvalidReason.element_type_invalid );
} catch ( PositionInvalid e ){
throw new ElementInvalid( ElementInvalidReason.positioning_property_invalid );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean retrieve_element_with_key(Any key, AnyHolder element) throws KeyInvalid{
check_key( key );
test_key.key = key;
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return false;
}
KeyNode node = (KeyNode)keys.elementAt( pos );
pos = node.start_position;
element.value = element_retrieve( pos );
return true;
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
} catch ( PositionInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized void key(Any element, AnyHolder a_key) throws ElementInvalid{
check_element( element );
a_key.value = ops.key( element );
};
/* ------------------------------------------------------------------------- */
public synchronized void keys(Any[] elements, AnySequenceHolder a_keys) throws ElementInvalid{
for( int i=0; i<elements.length; i++ ){
check_element( elements[i] );
}
a_keys.value = new Any[ elements.length ];
for( int i=0; i<elements.length; i++ ){
a_keys.value[i] = ops.key( elements[i] );
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_element_with_key(Any key, org.omg.CosCollection.Iterator where) throws KeyInvalid,IteratorInvalid{
check_key( key );
PositionalIteratorImpl i = check_iterator( where );
test_key.key = key;
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
i.invalidate();
return false;
}
KeyNode node = (KeyNode)keys.elementAt( pos );
i.set_pos( node.start_position );
i.set_in_between( false );
return true;
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_next_element_with_key(Any key, org.omg.CosCollection.Iterator where) throws KeyInvalid,IteratorInvalid{
check_key( key );
PositionalIteratorImpl i = check_iterator( where );
i.check_invalid();
int pos = i.get_pos();
int new_pos = i.is_in_between()?pos:pos+1;
if( data.size() <= new_pos ){
i.invalidate();
}
test_key.key = key;
Any this_key = ops.key((Any)data.elementAt( new_pos ));
if( ops.key_equal( key, this_key ) ){
i.set_pos( new_pos );
i.set_in_between( false );
return true;
} else {
i.invalidate();
return false;
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_next_element_with_different_key(org.omg.CosCollection.Iterator where) throws IteratorInBetween,IteratorInvalid{
PositionalIteratorImpl i = check_iterator( where );
i.check_iterator();
int pos = i.get_pos();
Any key = ops.key((Any)data.elementAt( pos ) );
test_key.key = key;
try {
int key_pos = keys.indexOf( test_key );
if( key_pos == keys.size()-1 ){
i.invalidate();
return false;
} else {
KeyNode node = (KeyNode)keys.elementAt( key_pos+1 );
i.set_pos( node.start_position );
return true;
}
} catch ( ObjectInvalid e ){
e.printStackTrace( System.out );
throw new org.omg.CORBA.INTERNAL();
}
};
/* ------------------------------------------------------------------------- */
public synchronized int number_of_different_keys(){
return keys.size();
};
/* ------------------------------------------------------------------------- */
public synchronized int number_of_elements_with_key(Any key) throws KeyInvalid{
check_key( key );
test_key.key = key;
try {
int pos = keys.indexOf( test_key );
if( pos < 0 ){
return 0;
};
KeyNode node = (KeyNode)keys.elementAt( pos );
return node.count;
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
// ----- KeySorted -----
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_first_element_with_key(Any key, org.omg.CosCollection.Iterator where) throws KeyInvalid,IteratorInvalid{
check_key( key );
PositionalIteratorImpl i = check_iterator( where );
try {
test_key.key = key;
int pos = keys.indexOf( test_key );
if( pos >= 0 ){
KeyNode node = (KeyNode)keys.elementAt( pos );
i.set_pos( node.start_position );
i.set_in_between( false );
return true;
} else {
i.invalidate();
return false;
}
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_last_element_with_key(Any key, org.omg.CosCollection.Iterator where) throws KeyInvalid,IteratorInvalid{
check_key( key );
PositionalIteratorImpl i = check_iterator( where );
try {
test_key.key = key;
int pos = keys.indexOf( test_key );
if( pos >= 0 ){
KeyNode node = (KeyNode)keys.elementAt( pos );
i.set_pos( node.start_position + node.count - 1 );
i.set_in_between( false );
return true;
} else {
i.invalidate();
return false;
}
} catch ( ObjectInvalid e ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_previous_element_with_key(Any key, org.omg.CosCollection.Iterator where) throws KeyInvalid,IteratorInvalid{
check_key( key );
PositionalIteratorImpl i = check_iterator( where );
i.check_invalid();
int pos = i.get_pos();
if( pos == 0 ){
i.invalidate();
return false;
}
Any element = (Any)data.elementAt( pos-1 );
if( ops.key_equal( key, ops.key( element ) ) ){
i.set_pos( pos-1 );
i.set_in_between( false );
return true;
}
i.invalidate();
return false;
};
/* ------------------------------------------------------------------------- */
public synchronized boolean locate_previous_element_with_different_key(org.omg.CosCollection.Iterator where) throws IteratorInBetween,IteratorInvalid{
PositionalIteratorImpl i = check_iterator( where );
i.check_iterator();
int pos = i.get_pos();
Any key = ops.key( (Any)data.elementAt( pos ) );
if( pos-- == 0 ){
i.invalidate();
return false;
}
while( pos >= 0 ) {
Any element = (Any)data.elementAt( pos );
if( !ops.key_equal( key, ops.key( element ) ) ){
i.set_pos( pos );
i.set_in_between( false );
return true;
}
pos--;
}
i.invalidate();
return false;
};
/* ========================================================================= */
/* ========================================================================= */
protected void element_inserted( int pos ) {
super.element_inserted( pos );
Any key = ops.key( (Any)data.elementAt(pos) );
key_inserted( key, pos );
};
/* ------------------------------------------------------------------------- */
protected void element_removed( int pos, Any old ){
super.element_removed( pos, old );
Any key = ops.key( old );
key_removed( key );
};
/* ------------------------------------------------------------------------- */
protected void element_replaced( int pos, Any old ){
super.element_replaced( pos, old );
Any old_key = ops.key( old );
Any new_key = ops.key( (Any)data.elementAt(pos) );
if( !ops.equal( old_key, new_key ) ){
key_removed( old_key );
key_inserted( new_key, pos );
}
};
/* ------------------------------------------------------------------------- */
protected void check_key( Any key ) throws KeyInvalid {
if( !ops.check_key_type( key ) ){
throw new KeyInvalid();
}
};
/* ------------------------------------------------------------------------- */
protected void key_inserted( Any key, int pos ){
try {
test_key.key = key;
int key_pos = keys.indexOf( test_key );
KeyNode node;
if( key_pos == -1 ){
node = new KeyNode();
node.key = key;
node.count = 0;
key_pos = keys.addElement( node );
node.start_position = pos;
} else {
node = (KeyNode)keys.elementAt( key_pos );
}
node.count++;
for( int i=key_pos+1; i<keys.size(); i++ ){
node = (KeyNode)keys.elementAt( i );
node.start_position++;
}
} catch ( ObjectInvalid e ){
e.printStackTrace( System.out );
throw new org.omg.CORBA.INTERNAL();
}
};
/* ------------------------------------------------------------------------- */
protected void key_removed( Any key ){
try {
test_key.key = key;
int key_pos = keys.indexOf( test_key );
KeyNode node = (KeyNode)keys.elementAt( key_pos );
node.count--;
for( int i=key_pos+1; i<keys.size(); i++ ){
node = (KeyNode)keys.elementAt( i );
node.start_position--;
}
if( node.count == 0 ){
keys.removeElementAt( key_pos );
}
} catch ( ObjectInvalid e ){
e.printStackTrace( System.out );
throw new org.omg.CORBA.INTERNAL();
}
};
/* ------------------------------------------------------------------------- */
};