Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openmdx.base.rest.spi.Object_2Facade Maven / Gradle / Ivy
/*
* ====================================================================
* Project: openMDX/Core, http://www.openmdx.org/
* Description: Object Facade
* Owner: OMEX AG, Switzerland, http://www.omex.ch
* ====================================================================
*
* This software is published under the BSD license as listed below.
*
* Copyright (c) 2009-2013, OMEX AG, Switzerland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of the openMDX team nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* ------------------
*
* This product includes software developed by other organizations as
* listed in the NOTICE file.
*/
package org.openmdx.base.rest.spi;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
import javax.resource.ResourceException;
import javax.resource.cci.MappedRecord;
import org.openmdx.base.collection.TreeSparseArray;
import org.openmdx.base.exception.RuntimeServiceException;
import org.openmdx.base.exception.ServiceException;
import org.openmdx.base.mof.cci.ModelElement_1_0;
import org.openmdx.base.mof.cci.ModelHelper;
import org.openmdx.base.mof.cci.Model_1_0;
import org.openmdx.base.mof.cci.Multiplicity;
import org.openmdx.base.mof.spi.Model_1Factory;
import org.openmdx.base.naming.Path;
import org.openmdx.base.resource.Records;
import org.openmdx.base.rest.cci.ObjectRecord;
import org.openmdx.kernel.exception.BasicException;
import org.w3c.cci2.SparseArray;
/**
* Object Facade
*/
@SuppressWarnings({"rawtypes","unchecked"})
public class Object_2Facade {
/**
* Constructor
*
* @param delegate
*/
private Object_2Facade(
MappedRecord delegate
) throws ResourceException {
if(!org.openmdx.base.rest.spi.ObjectRecord.isCompatible(delegate)) {
throw BasicException.initHolder(
new ResourceException(
"The delegate has the wrong type",
BasicException.newEmbeddedExceptionStack(
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.BAD_PARAMETER,
new BasicException.Parameter("expected", ObjectRecord.NAME),
new BasicException.Parameter("actual", delegate.getRecordName())
)
)
);
}
this.delegate = (ObjectRecord) delegate;
}
/**
* Constructor
*/
private Object_2Facade(
) throws ResourceException {
this.delegate = Records.getRecordFactory().createMappedRecord(ObjectRecord.class);
}
/**
* The query record
*/
private final ObjectRecord delegate;
/**
* Create a facade for the given record
*
* @param record
*
* @return the object facade
*
* @throws ResourceException
*/
public static Object_2Facade newInstance(
MappedRecord record
) throws ResourceException {
return record == null ? null : new Object_2Facade(record);
}
/**
* Create a facade with the given object identifier
*
* @param objectId the object identifier
*
* @return the object facade
*
* @throws ResourceException
*/
public static Object_2Facade newInstance(
Path objectId
) throws ResourceException {
Object_2Facade facade = new Object_2Facade();
facade.setPath(objectId);
return facade;
}
/**
* Create a facade with the given object identifier
*
* @param transactionalObjectId the object identifier
*
* @return the object facade
*
* @throws ResourceException
*/
public static Object_2Facade newInstance(
UUID transactionalObjectId
) throws ResourceException {
return newInstance(new Path(transactionalObjectId));
}
/**
* Create a facade for the given object identifier and object class
*
* @param objectClass the object class
*
* @return the object facade
*
* @throws ResourceException
*/
public static Object_2Facade newInstance(
Path objectId,
String objectClass
) throws ResourceException {
Object_2Facade object = newInstance(objectId);
if(objectClass != null){
object.setValue(Records.getRecordFactory().createMappedRecord(objectClass));
}
return object;
}
/**
* Retrieve the delegate
*
* @return the delegate
*/
public ObjectRecord getDelegate(){
return this.delegate;
}
/**
* Retrieve objectId.
*
* @return Returns the objectId.
*/
public final Path getPath(
) {
return delegate.getResourceIdentifier();
}
public static Path getPath(
MappedRecord delegate
) {
return delegate instanceof ObjectRecord ?
((ObjectRecord)delegate).getResourceIdentifier() :
(Path)delegate.get("resourceIdentifier");
}
public String getObjectClass(
) {
return this.delegate.getValue().getRecordName();
}
public static String getObjectClass(
MappedRecord delegate
) {
return getValue(delegate).getRecordName();
}
/**
* Set objectId.
*
* @param path The objectId to set.
*/
public final void setPath(Path path) {
this.delegate.setResourceIdentifier(path);
}
/**
* Set transient object id.
*
* @param path The transient object id to set.
*/
public final void setTransientObjectId(UUID transientObjectId) {
this.delegate.setTransientObjectId(transientObjectId);
}
/**
* Retrieve the transient object id.
*
* @param path The transient object id to set.
*/
public final UUID getTransientObjectId() {
return this.delegate.getTransientObjectId();
}
/**
* Tells whether it is a proxy operation
*
* @return false
if the transient object id is null
*/
public boolean isProxyOperation(){
return this.delegate.getTransientObjectId() != null;
}
/**
* Retrieve the value
*
* @return Returns the value.
*/
public final MappedRecord getValue(
) {
return this.delegate.getValue();
}
public static MappedRecord getValue(
MappedRecord delegate
) {
return delegate instanceof ObjectRecord ?
((ObjectRecord)delegate).getValue() :
(MappedRecord)delegate.get("value");
}
public Object getAttributeValues(
String attributeName
){
MappedRecord value = this.getValue();
Object v = value.get(attributeName);
return
v == null ? null :
v instanceof SparseArray ? new SparseArrayFacade(value, attributeName) :
v instanceof Map ? v :
new ListFacade(value,attributeName);
}
public Object attributeValues(
String attributeName
) throws ServiceException {
return this.attributeValues(
attributeName,
Multiplicity.LIST
);
}
public int getSizeOfAttributeValuesAsList(
String attributeName
) throws ServiceException{
return attributeValuesAsList(attributeName).size();
}
public void clearAttributeValuesAsList(
String attributeName
) throws ServiceException{
List target = attributeValuesAsList(attributeName);
target.clear();
}
public Object getSingletonFromAttributeValuesAsList(
String attributeName
) throws ServiceException{
return attributeValuesAsList(attributeName).get(0);
}
public void setAttributeValue(
String attributeName,
Object value
){
MappedRecord record = this.getValue();
record.put(attributeName, value);
}
public void replaceAttributeValuesAsListBySingleton(
String attributeName,
Object value
) throws ServiceException{
List target = attributeValuesAsList(attributeName);
target.clear();
target.add(value);
}
public void replaceAttributeValuesAsList(
String attributeName,
Collection> values
) throws ServiceException{
List target = attributeValuesAsList(attributeName);
target.clear();
target.addAll(values);
}
public boolean attributeValuesAsListContains(
String attributeName,
Object value
) throws ServiceException{
return attributeValuesAsList(attributeName).contains(value);
}
public void addToAttributeValuesAsList(
String attributeName,
Object value
) throws ServiceException{
List target = attributeValuesAsList(attributeName);
target.add(value);
}
public void addAllToAttributeValuesAsList(
String attributeName,
Collection> values
) throws ServiceException{
List target = attributeValuesAsList(attributeName);
target.addAll(values);
}
public Object getAttributeValueFromList(
String attributeName,
int index
) throws ServiceException{
return attributeValuesAsList(attributeName).get(index);
}
public List getAttributeValuesAsReadOnlyList(
String attributeName
) throws ServiceException {
return Collections.unmodifiableList(attributeValuesAsList(attributeName));
}
public List getAttributeValuesAsGuardedList(
String attributeName
) throws ServiceException {
String objectClass = getObjectClass();
List values = attributeValuesAsList(attributeName);
if(isCollectionAware(objectClass)) {
return values;
} else {
return new GuardedList(objectClass, attributeName, values);
}
}
private boolean isCollectionAware(String objectClass) {
return isTypeSafe(objectClass) || objectClass.startsWith("org:openmdx:system:");
}
private boolean isTypeSafe(String objectClass) {
return objectClass.startsWith("org:omg:model1:");
}
public boolean isTypeSafe(){
return isTypeSafe(getObjectClass());
}
public boolean isCollection(
String attributeName
){
return getRawValue(attributeName) instanceof Collection;
}
/**
* @param attributeName
* @return
*/
public Object getRawValue(String attributeName) {
return this.getValue().get(attributeName);
}
public Collection attributeValuesAsCollection(
String attributeName
) throws ServiceException {
return (Collection)getRawValue(attributeName);
}
public List attributeValuesAsList(
String attributeName
) throws ServiceException {
return (List)this.attributeValues(
attributeName,
Multiplicity.LIST
);
}
public Map attributeValuesAsMap(
String attributeName
) throws ServiceException {
return (Map)this.attributeValues(
attributeName,
Multiplicity.MAP
);
}
public Object attributeValues(
String attributeName,
Multiplicity multiplicity
) throws ServiceException {
Object value = this.getAttributeValues(attributeName);
if(value == null) {
MappedRecord record = this.getValue();
if (Multiplicity.MAP == multiplicity){
value = record.get(attributeName);
if(value == null) try {
record.put(
attributeName,
value = Records.getRecordFactory().createMappedRecord(Multiplicity.MAP.code())
);
} catch (ResourceException exception) {
throw new ServiceException(exception);
}
} else {
record.put(
attributeName,
null
);
value = Multiplicity.SPARSEARRAY == multiplicity ? new SparseArrayFacade(
record,
attributeName
) : new ListFacade(
record,
attributeName
);
}
}
return value;
}
public Object attributeValue(
String attributeName
) throws ServiceException {
MappedRecord value = this.getValue();
Object v = value.get(attributeName);
if(v == null) {
return null;
}
else if(v instanceof List) {
return ((List>)v).get(0);
}
else if(v instanceof SparseArray) {
return ((SparseArray>)v).get(Integer.valueOf(0));
}
else {
return v;
}
}
/**
* Set the value.
*
* @param value The value to set.
*/
public final void setValue(
MappedRecord value
) {
this.delegate.setValue(value);
}
/**
* Retrieve the read lock.
*
* @return Returns the read lock.
*/
public final Object getLock(
) {
return getLock(this.delegate);
}
/**
* Retrieve the read lock.
*
* @return Returns the read lock.
*/
public static Object getLock(
MappedRecord delegate
) {
return delegate instanceof ObjectRecord ?
((ObjectRecord)delegate).getLock() :
delegate.get("lock");
}
/**
* Set the read lock.
*
* @param lock The lock to set.
*/
public final void setLock(Object lock) {
this.delegate.setLock(lock);
}
/**
* Retrieve version.
*
* @return Returns the version.
*/
public final byte[] getVersion(
) {
return getVersion(this.delegate);
}
public static byte[] getVersion(
MappedRecord delegate
) {
return delegate instanceof ObjectRecord ?
((ObjectRecord)delegate).getVersion() :
(byte[])delegate.get("version");
}
/**
* Set version.
*
* @param version The version to set.
*/
public final void setVersion(byte[] version) {
this.delegate.setVersion(version);
}
/**
* Clone the wrapped object
*
* @return a facade of the clone
* @throws ResourceException
*
* @throws ServiceException
*/
public Object_2Facade cloneObject(
) throws ServiceException{
Object_2Facade copy;
try {
copy = newInstance(
this.getPath(),
this.getObjectClass()
);
} catch (ResourceException exception) {
throw new ServiceException(exception);
}
copy.setVersion(this.getVersion());
MappedRecord value = this.getValue();
for(String key: (Set)value.keySet()) {
Object source = this.attributeValues(key);
if(source instanceof SparseArray) {
((SparseArray)copy.attributeValues(
key,
Multiplicity.SPARSEARRAY
)).putAll(
(SparseArray)source
);
} else if (source instanceof List){
((List)copy.attributeValues(
key,
Multiplicity.LIST
)).addAll(
(List)source
);
} else if (source instanceof Map,?>){
((Map)copy.attributeValues(
key,
Multiplicity.MAP
)).putAll(
(Map)source
);
} else {
new ServiceException(
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.ASSERTION_FAILURE,
"Unexpected value type to be cloned",
new BasicException.Parameter(BasicException.Parameter.XRI, this.getPath()),
new BasicException.Parameter("key", key),
new BasicException.Parameter("type", source == null ? null : source.getClass().getName())
).log();
}
}
return copy;
}
/**
* Clone an object
*
* @param object
* @return a clone of the object
*
* @throws ServiceException
*/
public static ObjectRecord cloneObject(
MappedRecord object
) throws ServiceException {
try {
return newInstance(object).cloneObject().getDelegate();
} catch (ResourceException e) {
throw new ServiceException(e);
}
}
/**
* Clone the wrapped object
*
* @param the delegate's record name
*
* @return a facade of the clone
* @throws ResourceException
*
* @throws ServiceException
*/
public Object_2Facade transformObject(
String dataRecordName
) throws ServiceException{
try {
final MappedRecord target = Records.getRecordFactory().createMappedRecord(dataRecordName);
final MappedRecord source = this.getValue();
for(Object key : source.keySet()) {
if(target.containsKey(key)){
final Object value = source.get(key);
try {
target.put(key, value);
} catch (RuntimeException exception) {
throw new ServiceException(
exception,
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.TRANSFORMATION_FAILURE,
"Object transformation failure",
new BasicException.Parameter("source type", source.getRecordName()),
new BasicException.Parameter("target type", target.getRecordName()),
new BasicException.Parameter("key", key),
new BasicException.Parameter("value", value)
);
}
}
}
final Object_2Facade that = new Object_2Facade();
that.setPath(this.getPath());
that.setValue(target);
return that;
} catch (ResourceException exception) {
throw new ServiceException(exception);
}
}
/**
* @param type the fully qualified MOF class name
* @param featureName the unqualified feature name
*
* @throws ServiceException
*/
protected static boolean isSingleValued(
String type,
String featureName
){
Model_1_0 model = Model_1Factory.getModel();
try {
ModelElement_1_0 classifierDef = model.getElement(type);
if(classifierDef != null) {
ModelElement_1_0 featureDef = model.getFeatureDef(classifierDef, featureName, false);
if(featureDef != null) {
return ModelHelper.getMultiplicity(featureDef).isSingleValued();
} else {
throw new ServiceException(
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.NOT_FOUND,
"Invalid feature",
new BasicException.Parameter("type", type),
new BasicException.Parameter("feature", featureName)
);
}
} else {
throw new ServiceException(
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.NOT_FOUND,
"Class not found",
new BasicException.Parameter("class", type)
);
}
} catch (ServiceException exception) {
exception.log();
return false;
}
}
//-----------------------------------------------------------------------
// List Facade
//-----------------------------------------------------------------------
static class ListFacade
implements List, Cloneable, Serializable
{
/**
* Creates DelegatingSparseList
. The value is managed in record at key.
*/
public ListFacade(
MappedRecord record,
Object key
) {
this.record = record;
this.key = key;
}
private static final long serialVersionUID = 9044898033126787944L;
private final MappedRecord record;
private final Object key;
private List nonDelegate(
){
E value = (E)this.record.get(this.key);
return value == null ?
(List)Collections.EMPTY_LIST :
Collections.singletonList(value);
}
private synchronized List attributeValues(
){
Object value = this.record.get(this.key);
if(value instanceof List) {
return (List)value;
} else try {
List values = Records.getRecordFactory().createIndexedRecord(Multiplicity.LIST.code());
if(value != null) {
values.add((E)value);
}
this.record.put(
this.key,
values
);
return values;
} catch (ResourceException exception) {
throw new RuntimeServiceException(exception);
}
}
private List getList(
) {
Object values = this.record.get(this.key);
return values instanceof List ? (List)values : nonDelegate();
}
/* (non-Javadoc)
* @see java.util.List#add(int, java.lang.Object)
*/
public void add(
int index,
E element
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
((List)values).add(index, element);
}
else {
if(index == 0 && values == null) {
this.record.put(
this.key,
element
);
}
else {
this.attributeValues().add(index, element);
}
}
}
/* (non-Javadoc)
* @see java.util.List#add(java.lang.Object)
*/
public boolean add(
E element
) {
Object values = this.record.get(this.key);
if(element == null) {
return false;
}
else if(values instanceof List) {
try {
return ((List)values).add(element);
} catch (UnsupportedOperationException e) {
throw new UnsupportedOperationException("Unable to add " + element + " to " + values);
}
}
else {
if(values == null) {
this.record.put(
this.key,
element
);
return true;
}
else {
return this.attributeValues().add(element);
}
}
}
/* (non-Javadoc)
* @see java.util.List#addAll(java.util.Collection)
*/
public boolean addAll(
Collection extends E> c
) {
Object values = this.record.get(this.key);
if(c.isEmpty()) {
return false;
}
else if(values instanceof List) {
return ((List)values).addAll(c);
}
else {
if(values != null || c.size() > 1) {
return this.attributeValues().addAll(c);
}
else {
Object value = c.iterator().next();
this.record.put(
this.key,
value
);
return value != null;
}
}
}
/* (non-Javadoc)
* @see java.util.List#addAll(int, java.util.Collection)
*/
public boolean addAll(
int index,
Collection extends E> c
) {
Object values = this.record.get(this.key);
if(c.isEmpty()) {
return false;
}
else if(values instanceof List) {
return ((List)values).addAll(index, c);
}
else {
if(index > 0 || values != null || c.size() > 1) {
return this.attributeValues().addAll(index, c);
}
else {
Object value = c.iterator().next();
this.record.put(
this.key,
value
);
return value != null;
}
}
}
/* (non-Javadoc)
* @see java.util.List#clear()
*/
public void clear(
) {
this.attributeValues().clear();
}
/* (non-Javadoc)
* @see java.util.List#contains(java.lang.Object)
*/
public boolean contains(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).contains(o);
}
else {
return values != null && values.equals(o);
}
}
/* (non-Javadoc)
* @see java.util.List#containsAll(java.util.Collection)
*/
public boolean containsAll(
Collection> c
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).containsAll(c);
}
else {
for(
Iterator> i = c.iterator();
i.hasNext();
) {
if(!this.contains(i.next())) {
return false;
}
}
return true;
}
}
/* (non-Javadoc)
* @see java.util.List#equals(java.lang.Object)
*/
@Override
public boolean equals(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).equals(o);
}
else {
if(o instanceof List>) {
List> l = (List>)o;
if(values == null) {
return l.isEmpty();
}
else if(l.size() == 1) {
return values.equals(l.get(0));
}
else {
return false;
}
}
else {
return false;
}
}
}
/* (non-Javadoc)
* @see java.util.List#get(int)
*/
public E get(
int index
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).get(index);
}
else {
return index == 0 ? (E)values : null;
}
}
/* (non-Javadoc)
* @see java.util.List#hashCode()
*/
@Override
public int hashCode(
) {
switch(this.size()) {
case 0: return 0;
default: return this.record.get(this.key).hashCode();
}
}
/* (non-Javadoc)
* @see java.util.List#indexOf(java.lang.Object)
*/
public int indexOf(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).indexOf(o);
}
else {
if(values == null) {
return o == null ? 0 : -1;
}
else {
return values.equals(o) ? 0 : -1;
}
}
}
/* (non-Javadoc)
* @see java.util.List#isEmpty()
*/
public boolean isEmpty(
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).isEmpty();
}
else {
return values == null;
}
}
/* (non-Javadoc)
* @see java.util.List#iterator()
*/
public Iterator iterator(
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).iterator();
}
else {
return new NonDelegateIterator(this);
}
}
/* (non-Javadoc)
* @see java.util.List#lastIndexOf(java.lang.Object)
*/
public int lastIndexOf(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).lastIndexOf(o);
}
else {
if(values == null) {
return o == null ? 0 : -1;
}
else {
return values.equals(o) ? 0 : -1;
}
}
}
/* (non-Javadoc)
* @see java.util.List#listIterator()
*/
public ListIterator listIterator(
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).listIterator();
}
else {
return new NonDelegateIterator(this);
}
}
/* (non-Javadoc)
* @see java.util.List#listIterator(int)
*/
public ListIterator listIterator(
int index
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).listIterator(index);
}
else {
return new NonDelegateIterator(index, this);
}
}
/* (non-Javadoc)
* @see java.util.List#remove(int)
*/
public E remove(
int index
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).remove(index);
}
else {
if(index < 0) throw new IndexOutOfBoundsException(
"Index " + index + " is less than 0"
);
if(index < 0 || index > size()) throw new IndexOutOfBoundsException(
"Index " + index + " is greater than size " + size()
);
E value = (E)values;
this.record.remove(this.key);
return value;
}
}
/* (non-Javadoc)
* @see java.util.List#remove(java.lang.Object)
*/
public boolean remove(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).remove(o);
}
else {
boolean modify = this.contains(o);
if(modify) {
this.record.remove(this.key);
}
return modify;
}
}
/* (non-Javadoc)
* @see java.util.List#removeAll(java.util.Collection)
*/
public boolean removeAll(
Collection> c
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).removeAll(c);
}
else {
if(values == null) {
return false;
}
else {
for(
Iterator> i = c.iterator();
i.hasNext();
) {
if(this.remove(i.next())) return true;
}
return false;
}
}
}
/* (non-Javadoc)
* @see java.util.List#retainAll(java.util.Collection)
*/
public boolean retainAll(
Collection> c
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).retainAll(c);
}
else {
if(values == null){
return false;
}
else {
boolean modify = !c.contains(values);
if(modify) {
this.record.remove(this.key);
}
return modify;
}
}
}
/* (non-Javadoc)
* @see java.util.List#set(int, java.lang.Object)
*/
public E set(
int index,
E element
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).set(index, element);
}
else {
if(index == 0) {
E value = (E)values;
this.record.put(
this.key,
element
);
return value;
}
else {
return this.attributeValues().set(index, element);
}
}
}
/* (non-Javadoc)
* @see java.util.List#size()
*/
public int size(
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).size();
}
else {
return values == null ? 0 : 1;
}
}
/* (non-Javadoc)
* @see java.util.List#subList(int, int)
*/
public List subList(
int fromIndex,
int toIndex
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).subList(fromIndex, toIndex);
}
else {
if(values == null || fromIndex > 0) {
return Collections.nCopies(toIndex - fromIndex, null);
}
else if (toIndex == 1){
return this.nonDelegate();
}
else {
return this.attributeValues().subList(fromIndex, toIndex);
}
}
}
/* (non-Javadoc)
* @see java.util.List#toArray()
*/
public Object[] toArray(
) {
Object values = this.record.get(this.key);
if(values instanceof List) {
return ((List)values).toArray();
}
else {
return values == null ? EMPTY_ARRAY : new Object[]{values};
}
}
/* (non-Javadoc)
* @see java.util.List#toArray(java.lang.Object[])
*/
public T[] toArray(
T[] _a
) {
Object values = this.record.get(this.key);
T[] a = _a;
if(values instanceof List) {
return ((List)values).toArray(a);
}
else {
if(values != null) {
if(a.length == 0) {
a = (T[]) Array.newInstance(
a.getClass().getComponentType(),
1
);
}
a[0] = (T)values;
}
return a;
}
}
//------------------------------------------------------------------------
// Members
//------------------------------------------------------------------------
private static final Object[] EMPTY_ARRAY = new Object[0];
//------------------------------------------------------------------------
// Implements Cloneable
//------------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
protected Object clone(
) {
throw new UnsupportedOperationException("clone not supported for delegating sparse lists");
}
//------------------------------------------------------------------------
// Extends Object
//------------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getList().toString();
}
}
//------------------------------------------------------------------------
// Class NonDelegateIterator
//------------------------------------------------------------------------
static class NonDelegateIterator implements ListIterator {
private int index;
private List list;
/**
* Constructor
*
* @param index
*/
NonDelegateIterator(
int index,
List list
){
this.index = index;
this.list = list;
}
NonDelegateIterator(
List list
){
this(0, list);
}
/* (non-Javadoc)
* @see java.util.ListIterator#nextIndex()
*/
public int nextIndex() {
return this.index;
}
/* (non-Javadoc)
* @see java.util.ListIterator#previousIndex()
*/
public int previousIndex() {
return this.index - 1;
}
/* (non-Javadoc)
* @see java.util.ListIterator#remove()
*/
public void remove() {
this.list.set(this.index - 1, null);
}
/* (non-Javadoc)
* @see java.util.ListIterator#hasNext()
*/
public boolean hasNext() {
return nextIndex() < this.list.size();
}
/* (non-Javadoc)
* @see java.util.ListIterator#hasPrevious()
*/
public boolean hasPrevious() {
return previousIndex() >= 0;
}
/* (non-Javadoc)
* @see java.util.ListIterator#next()
*/
public E next() {
if(!hasNext()) throw new NoSuchElementException();
return this.list.get(this.index++);
}
/* (non-Javadoc)
* @see java.util.ListIterator#previous()
*/
public E previous() {
if(!hasPrevious()) throw new NoSuchElementException();
return this.list.get(--this.index);
}
/* (non-Javadoc)
* @see java.util.ListIterator#add(java.lang.Object)
*/
public void add(Object o) {
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see java.util.ListIterator#set(java.lang.Object)
*/
public void set(E o) {
this.list.set(this.index - 1, o);
}
}
//-----------------------------------------------------------------------
// Sparse Array Facade
//-----------------------------------------------------------------------
static class SparseArrayFacade
implements SparseArray, Cloneable, Serializable
{
/**
* Creates SparseArrayFacade
.
* The value is managed in record at key.
*
* @param record
* @param key
*/
public SparseArrayFacade(
MappedRecord record,
Object key
) {
this.record = record;
this.key = key;
}
private static final long serialVersionUID = 5241681200495515635L;
private final MappedRecord record;
private final Object key;
private synchronized SparseArray attributeValues(
){
Object value = this.record.get(this.key);
if(value instanceof SparseArray) {
return (SparseArray)value;
} else {
SparseArray values = new TreeSparseArray();
values.put(Integer.valueOf(0), (E)value);
this.record.put(
this.key,
values
);
return values;
}
}
/* (non-Javadoc)
* @see java.util.List#addAll(java.util.Collection)
*/
public void putAll(
Map extends Integer, ? extends E> m
) {
Object values = this.record.get(this.key);
if(m.isEmpty()) {
return;
}
else if(values instanceof SparseArray) {
((SparseArray)values).putAll(m);
}
else {
this.attributeValues().putAll(m);
}
}
/* (non-Javadoc)
* @see java.util.List#clear()
*/
public void clear(
) {
this.attributeValues().clear();
}
/* (non-Javadoc)
* @see java.util.List#equals(java.lang.Object)
*/
@Override
public boolean equals(
Object o
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).equals(o);
}
else {
if(o instanceof SparseArray>) {
SparseArray> l = (SparseArray>)o;
if(values == null) {
return l.isEmpty();
}
else if(l.size() == 1) {
return values.equals(l.get(Integer.valueOf(0)));
}
else {
return false;
}
}
else {
return false;
}
}
}
/* (non-Javadoc)
* @see java.util.List#get(int)
*/
public E get(
Object key
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).get(key);
}
else {
return this.attributeValues().get(key);
}
}
/* (non-Javadoc)
* @see java.util.List#hashCode()
*/
@Override
public int hashCode(
) {
switch(this.size()) {
case 0: return 0;
default: return this.record.get(this.key).hashCode();
}
}
/* (non-Javadoc)
* @see java.util.List#isEmpty()
*/
public boolean isEmpty(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).isEmpty();
}
else {
return this.attributeValues().isEmpty();
}
}
/* (non-Javadoc)
* @see java.util.List#iterator()
*/
public Iterator iterator(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).iterator();
}
else {
return this.attributeValues().iterator();
}
}
/* (non-Javadoc)
* @see java.util.List#lastIndexOf(java.lang.Object)
*/
public Integer lastKey(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return (Integer)((SparseArray)values).lastKey();
}
else {
return this.attributeValues().lastKey();
}
}
/* (non-Javadoc)
* @see java.util.List#lastIndexOf(java.lang.Object)
*/
public Integer firstKey(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return (Integer)((SparseArray)values).firstKey();
}
else {
return this.attributeValues().firstKey();
}
}
/* (non-Javadoc)
* @see java.util.List#listIterator()
*/
public ListIterator populationIterator(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).populationIterator();
}
else {
return this.attributeValues().populationIterator();
}
}
/* (non-Javadoc)
* @see java.util.List#remove(int)
*/
public E remove(
Object key
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).remove(key);
}
else {
return this.attributeValues().remove(key);
}
}
/* (non-Javadoc)
* @see java.util.List#set(int, java.lang.Object)
*/
public E put(
Integer key,
E element
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).put(key, element);
}
else {
return this.attributeValues().put(key, element);
}
}
/* (non-Javadoc)
* @see java.util.List#size()
*/
public int size(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).size();
}
else {
return this.attributeValues().size();
}
}
/* (non-Javadoc)
* @see java.util.List#subList(int, int)
*/
public SparseArray subMap(
Integer fromKey,
Integer toKey
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray) {
return ((SparseArray)values).subMap(fromKey, toKey);
}
else {
return this.attributeValues().subMap(
fromKey,
toKey
);
}
}
/* (non-Javadoc)
* @see org.w3c.cci2.SparseArray#asList()
*/
public List asList(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).asList();
}
else {
return this.attributeValues().asList();
}
}
/* (non-Javadoc)
* @see org.w3c.cci2.SparseArray#headMap(java.lang.Integer)
*/
public SparseArray headMap(
Integer toKey
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).headMap(toKey);
}
else {
return this.attributeValues().headMap(toKey);
}
}
/* (non-Javadoc)
* @see org.w3c.cci2.SparseArray#tailMap(java.lang.Integer)
*/
public SparseArray tailMap(
Integer fromKey
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).tailMap(fromKey);
}
else {
return this.attributeValues().tailMap(fromKey);
}
}
/* (non-Javadoc)
* @see java.util.SortedMap#comparator()
*/
public Comparator super Integer> comparator(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).comparator();
}
else {
return this.attributeValues().comparator();
}
}
/* (non-Javadoc)
* @see java.util.Map#containsKey(java.lang.Object)
*/
public boolean containsKey(
Object key
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).containsKey(key);
}
else {
return this.attributeValues().containsKey(key);
}
}
/* (non-Javadoc)
* @see java.util.Map#containsValue(java.lang.Object)
*/
public boolean containsValue(
Object value
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).containsValue(value);
}
else {
return this.attributeValues().containsValue(value);
}
}
/* (non-Javadoc)
* @see java.util.Map#entrySet()
*/
public Set> entrySet(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).entrySet();
}
else {
return this.attributeValues().entrySet();
}
}
/* (non-Javadoc)
* @see java.util.Map#keySet()
*/
public Set keySet(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).keySet();
}
else {
return this.attributeValues().keySet();
}
}
/* (non-Javadoc)
* @see java.util.Map#values()
*/
public Collection values(
) {
Object values = this.record.get(this.key);
if(values instanceof SparseArray>) {
return ((SparseArray)values).values();
}
else {
return this.attributeValues().values();
}
}
//------------------------------------------------------------------------
// Implements Cloneable
//------------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#clone()
*/
@Override
protected Object clone(
) {
throw new UnsupportedOperationException("clone not supported for delegating sparse arrays");
}
//------------------------------------------------------------------------
// Extends Object
//------------------------------------------------------------------------
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString(
) {
return this.attributeValues().toString();
}
}
//------------------------------------------------------------------------
// Class GuardedList
//------------------------------------------------------------------------
/**
* GuardedList asserts that only multivalued features may have more than one element
*/
static class GuardedList extends AbstractList {
GuardedList(String objectClass, String featureName, List valuesAsList) {
this.objectClass = objectClass;
this.featureName = featureName;
this.delegate = valuesAsList;
}
private final List delegate;
private final String objectClass;
private final String featureName;
private Boolean singlevalued;
/* (non-Javadoc)
* @see java.util.AbstractList#get(int)
*/
@Override
public Object get(int index) {
return this.delegate.get(index);
}
/* (non-Javadoc)
* @see java.util.AbstractCollection#size()
*/
@Override
public int size() {
return this.delegate.size();
}
/* (non-Javadoc)
* @see java.util.AbstractList#set(int, java.lang.Object)
*/
@Override
public Object set(int index, Object element) {
return this.delegate.set(index, element);
}
private boolean isSinglevalued(){
if(this.singlevalued == null) {
this.singlevalued = Boolean.valueOf(isSingleValued(this.objectClass, this.featureName));
}
return this.singlevalued.booleanValue();
}
/* (non-Javadoc)
* @see java.util.AbstractList#add(int, java.lang.Object)
*/
@Override
public void add(int index, Object element) {
if(this.delegate.isEmpty() || !this.isSinglevalued()) {
this.delegate.add(index, element);
} else {
throw new RuntimeServiceException(
BasicException.Code.DEFAULT_DOMAIN,
BasicException.Code.ASSERTION_FAILURE,
"The maximal cardinality of 1 would be exceeded",
new BasicException.Parameter("objectClass", this.objectClass),
new BasicException.Parameter("featureName", this.featureName),
new BasicException.Parameter("delegate", this.delegate),
new BasicException.Parameter("index", index),
new BasicException.Parameter("value", element)
).log();
}
}
/* (non-Javadoc)
* @see java.util.AbstractList#remove(int)
*/
@Override
public Object remove(int index) {
return this.delegate.remove(index);
}
}
}