+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.acorn.cluster;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.UUID;
+
+import org.simantics.acorn.internal.Change;
+import org.simantics.acorn.internal.ClusterChange;
+import org.simantics.acorn.internal.ClusterSupport2;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.InvalidClusterException;
+import org.simantics.db.impl.ClusterBase;
+import org.simantics.db.impl.ClusterI;
+import org.simantics.db.impl.ClusterSupport;
+import org.simantics.db.impl.IClusterTable;
+import org.simantics.db.impl.Modifier;
+import org.simantics.db.service.ClusterCollectorPolicy.CollectorCluster;
+import org.simantics.db.service.ClusterUID;
+import org.simantics.db.service.ClusteringSupport.Id;
+import org.simantics.utils.strings.AlphanumComparator;
+
+public abstract class ClusterImpl extends ClusterBase implements Modifier, CollectorCluster {
+ protected static final int LONG_HEADER_SIZE = 7;
+ protected static final long LONG_HEADER_VERSION = 1;
+ protected static ClusterUID checkValidity(long type, long[] longs, int[] ints, byte[] bytes)
+ throws InvalidClusterException {
+ if (longs.length < LONG_HEADER_SIZE)
+ throw new InvalidClusterException("Header size mismatch. Expected=" + ClusterImpl.LONG_HEADER_SIZE + ", got=" + longs.length);
+ if (longs[0] != type)
+ throw new InvalidClusterException("Type mismatch. Expected=" + type + ", got=" + longs[0] + " " + ClusterUID.make(longs[2], longs[3]));
+ if (longs[1] != ClusterImpl.LONG_HEADER_VERSION)
+ throw new InvalidClusterException("Header size mismatch. Expected=" + ClusterImpl.LONG_HEADER_VERSION + ", got=" + longs[1]);
+ return ClusterUID.make(longs[2], longs[3]);
+ }
+ protected static Id getUniqueId(long[] longs) {
+ return new IdImpl(new UUID(longs[3], longs[4]));
+ }
+ static final boolean DEBUG = false;
+ final public IClusterTable clusterTable;
+ // This can be null iff the cluster has been converted to big
+ public Change change = new Change();
+ public ClusterChange cc;
+ public byte[] foreignLookup;
+
+ private boolean dirtySizeInBytes = true;
+ private long sizeInBytes = 0;
+
+ protected ClusterImpl() {
+ clusterTable = null;
+ }
+
+ public ClusterImpl(IClusterTable clusterTable, ClusterUID clusterUID, int clusterKey, ClusterSupport support) {
+ super(support, clusterUID, clusterKey);
+// SessionImplSocket session = (SessionImplSocket)support.getSession();
+// if(session != null)
+ this.clusterTable = clusterTable;
+// else
+ }
+
+ public static ClusterImpl dummy() {
+ return new ClusterSmall();
+ }
+
+ public static ClusterImpl make(IClusterTable clusterTable, ClusterUID clusterUID, int clusterKey, ClusterSupport2 support) {
+ return new ClusterSmall(clusterUID, clusterKey, support, clusterTable);
+ }
+ public static ClusterSmall proxy(IClusterTable clusterTable, ClusterUID clusterUID, int clusterKey, long clusterId, ClusterSupport2 support) {
+ if (DEBUG)
+ new Exception("Cluster proxy for " + clusterUID).printStackTrace();
+ return new ClusterSmall(null, clusterUID, clusterKey, support);
+ }
+ public static ClusterImpl make(IClusterTable clusterTable, long[] longs, int[] ints, byte[] bytes, ClusterSupport2 support, int clusterKey)
+ throws DatabaseException {
+ if (longs[0] == 0)
+ return new ClusterBig(clusterTable, longs, ints, bytes, support, clusterKey);
+ else
+ return new ClusterSmall(clusterTable, longs, ints, bytes, support, clusterKey);
+ }
+
+// public boolean virtual = false;
+
+ @Override
+ public boolean hasVirtual() {
+ return false;
+// return clusterTable.hasVirtual(clusterKey);
+ }
+
+ @Override
+ public void markVirtual() {
+// clusterTable.markVirtual(clusterKey);
+// virtual = true;
+ }
+
+ @Override
+ public boolean isWriteOnly() {
+ return false;
+ }
+ @Override
+ public boolean isLoaded() {
+ return true;
+ }
+
+ @Override
+ public void resized() {
+ dirtySizeInBytes = true;
+// if(clusterTable != null)
+// clusterTable.setDirtySizeInBytes(true);
+ }
+
+ public long getCachedSize() {
+ if(dirtySizeInBytes) {
+ try {
+ sizeInBytes = getUsedSpace();
+ //System.err.println("recomputed size of cluster " + getClusterId() + " => " + sizeInBytes);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+ dirtySizeInBytes = false;
+ }
+ return sizeInBytes;
+ }
+
+ protected void calculateModifiedId() {
+// setModifiedId(new IdImpl(UUID.randomUUID()));
+ }
+
+ public static class ClusterTables {
+ public byte[] bytes;
+ public int[] ints;
+ public long[] longs;
+ }
+
+ public byte[] storeBytes() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ public ClusterTables store() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ abstract protected int getResourceTableCount();
+
+ public String dump(final ClusterSupport support) {
+
+ StringBuilder sb = new StringBuilder();
+ for(int i=1;i<getResourceTableCount();i++) {
+ sb.append(""+i+"\n");
+ final int resourceKey = i;
+ final ArrayList<String> stms = new ArrayList<String>();
+ try {
+
+ byte[] value = getValue(i, support);
+ if(value != null)
+ sb.append(" bytes: " + Arrays.toString(value) + "\n");
+
+ forPredicates(i, new PredicateProcedure<Integer>() {
+
+ @Override
+ public boolean execute(Integer c, final int predicateKey, int objectIndex) {
+
+ try {
+
+ forObjects(resourceKey, predicateKey, objectIndex, new ObjectProcedure<Integer>() {
+
+ @Override
+ public boolean execute(Integer context, int objectKey) throws DatabaseException {
+
+ ClusterUID puid = support.getClusterByResourceKey(predicateKey).getClusterUID();
+ ClusterUID ouid = support.getClusterByResourceKey(objectKey).getClusterUID();
+
+ stms.add(" " + puid + " " + (predicateKey&0xFFF) + " " + ouid + " " + (objectKey&0xFFF));
+
+ return false;
+
+ }
+
+ }, 0, support);
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ }
+
+ return false;
+
+ }
+
+ },0,support);
+
+ Collections.sort(stms, AlphanumComparator.COMPARATOR);
+
+ for(String s : stms) {
+ sb.append(s);
+ sb.append("\n");
+ }
+
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ }
+ }
+
+ return sb.toString();
+
+ }
+
+ abstract public boolean isValueEx(int resourceIndex) throws DatabaseException;
+
+ abstract public ClusterI addRelation(int resourceKey, ClusterUID puid, int predicateKey, ClusterUID ouid, int objectKey, ClusterSupport support) throws DatabaseException;
+
+ @Override
+ public IClusterTable getClusterTable() {
+ return clusterTable;
+ }
+}