/**
* This file is part of the CRISTAL-iSE kernel.
* Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 3 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; with out even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* http://www.fsf.org/licensing/licenses/lgpl.html
*/
package com.c2kernel.collection;
import java.util.Iterator;
import com.c2kernel.common.InvalidCollectionModification;
import com.c2kernel.common.ObjectAlreadyExistsException;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.entity.C2KLocalObject;
import com.c2kernel.graph.model.GraphModel;
import com.c2kernel.lookup.ItemPath;
import com.c2kernel.persistency.ClusterStorage;
import com.c2kernel.utils.CastorHashMap;
/**
* Collections are Item local objects that reference other Items.
*
*
In parallel with the OO meta-model, Items can be linked to other Items in
* different ways. These links are modelled with Collections, which are local
* objects stored in an Item which reference a number of other Items in the same
* server. The Collections holds a CollectionMember, sometimes known as a slot,
* to reference each Item and store additional information about the link.
*
*
Features:
*
* - Typing - Collections can restrict membership of based on type
* information derived from Item, Property and Collection descriptions. This
* restriction may be per-slot or apply to the whole Collection.
*
*
- Fixed or flexible slots - The CollectionMember objects of a
* Collection may be empty, individually typed, or created and removed as
* required, simulating either array, structures or lists.
*
*
- Layout - Collections can include a {@link GraphModel} to lay out
* its slots on a two-dimensional canvas, for modelling real world compositions.
*
*
* Collections are managed through predefined steps.
*/
abstract public class Collection implements C2KLocalObject
{
public static final short EMPTY = -1;
private int mCounter = -1; // Contains next available Member ID
protected CollectionMemberList mMembers = new CollectionMemberList();
protected int mID = -1;
protected String mName = ""; // Not checked for uniqueness
protected Integer mVersion = null;
public int getCounter()
{
if (mCounter == -1)
for (E element : mMembers.list) {
if (mCounter < element.getID())
mCounter = element.getID();
}
return ++mCounter;
}
public void setCounter(int count)
{
mCounter = count;
}
public int size()
{
return mMembers.list.size();
}
public void setID(int id)
{
mID = id;
}
public int getID()
{
return mID;
}
@Override
public void setName(String name)
{
mName = name;
}
@Override
public String getName()
{
return mName;
}
public Integer getVersion() {
return mVersion;
}
public void setVersion(Integer mVersion) {
this.mVersion = mVersion;
}
public String getVersionName() {
return mVersion==null?"last":String.valueOf(mVersion);
}
@Override
public String getClusterType()
{
return ClusterStorage.COLLECTION;
}
public void setMembers(CollectionMemberList newMembers)
{
mMembers = newMembers;
}
public boolean contains(ItemPath itemPath) {
for (E element : mMembers.list) {
if (element.getItemPath().equals(itemPath))
return true;
}
return false;
}
public String getDescVer(E mem) {
String descVer = "last";
Object descVerObj = mem.getProperties().get("Version");
if (descVerObj != null) descVer = descVerObj.toString();
return descVer;
}
public boolean isFull()
{
for (E element : mMembers.list) {
if (element.getItemPath() == null)
return false;
}
return true;
}
public E getMember(int memberId) throws ObjectNotFoundException {
for (E element : mMembers.list) {
if (element.getID() == memberId)
return element;
}
throw new ObjectNotFoundException("Member "+memberId+" not found in "+mName);
}
public CollectionMemberList getMembers()
{
return mMembers;
}
public abstract E addMember(ItemPath itemPath, CastorHashMap props, String classProps) throws InvalidCollectionModification, ObjectAlreadyExistsException;
public abstract void removeMember(int memberId) throws ObjectNotFoundException;
@Override
public boolean equals(Object other) {
if (!(other instanceof Collection>)) return false;
Collection> otherColl = (Collection>)other;
boolean same = mName.equals(otherColl.getName()) && size() == otherColl.size();
if (!same) return false;
for (Iterator i = getMembers().list.iterator(); i.hasNext();) {
try {
E thisMem = i.next();
CollectionMember otherMem = otherColl.getMember(thisMem.getID());
if (!thisMem.equals(otherMem)) return false;
} catch (ObjectNotFoundException ex) {
return false;
}
}
return true;
}
}