created mirror

This commit is contained in:
whatever
2026-09-14 20:19:29 -04:00
commit 6764738d92
600 changed files with 87187 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
/*
BinaryTreePart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A full binary tree spacepart demo.
* Supports two local dimensions: depth and breadth.
*/
public class BinaryTreePart extends ZZROStrSpacePart {
public static final String rcsid = "$Id: BinaryTreePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $";
public BinaryTreePart(ZZSpace space, String id) {
super(space, id);
}
public String homeID() {
return "1";
}
public String getText(ZZCellHandle c) {
return c.id.substring(c.id.length()-1);
}
public ZZDimension getDim(String name) {
if(name.equals("depth")) return new Depth();
if(name.equals("breadth")) return new Breadth();
return null;
}
public class Depth extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
// We can go one step
if(c.part == null && c.id.equals("1") && steps > 0) {
c = this.space.getCellByID(BinaryTreePart.this, "1", null);
steps --;
}
if(c.part != BinaryTreePart.this) return null;
while(steps > 0 && c != null) {
c = (ZZCellHandle)this.space.getCellByID(c.id+"0");
steps--;
}
while(steps < 0 && c != null) {
if(c.part != BinaryTreePart.this) return null;
int len = c.id.length();
if(c.id.charAt(len-1) == '0')
c = (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1));
else if(c.id.equals(id+":"+1))
c = (ZZCellHandle)this.space.getCellByID("1");
else
c = null;
steps++;
}
return c;
}
}
public class Breadth extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(c.part != BinaryTreePart.this) return null;
if(steps == 0) return c;
if(steps == 1) {
int len = c.id.length();
if(c.id.charAt(len-1) == '0')
return (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1)+"1");
} else if(steps == -1) {
int len = c.id.length();
if(c.id.charAt(len-1) == '1' &&
c.id.charAt(len-2) != ':')
return (ZZCellHandle)this.space.getCellByID(c.id.substring(0, len-1)+"0");
}
return null;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
DoubleStepPart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A dimension double-stepper part.
* This part, unlike most, has none of its own cells but simply
* provides for each dimension a doubling dimension.
*/
public class DoubleStepPart extends ZZROStrSpacePart {
public static final String rcsid = "$Id: DoubleStepPart.java,v 1.1 2000/11/06 12:39:39 tjl Exp $";
public static final boolean dbg = false;
static void p(String s) { if(dbg) System.out.println(s); }
public DoubleStepPart(ZZSpace space, String id) {
super(space, id);
}
public String homeID() {
return "1";
}
public String getText(ZZCellHandle c) {
return c.id.substring(c.id.length()-1);
}
public ZZDimension getDim(String name) {
return new Dbl(space.d(name));
}
public class Dbl extends ZZRODimension {
ZZDimension dim;
public Dbl(ZZDimension dim) {
this.dim = dim;
}
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
ZZCellHandle hd = dim.s(c, steps*2, o);
p("Dbl: Step "+steps+" "+c+" "+hd);
return hd;
}
}
}

160
Java/part/GenTreePart.java Normal file
View File

@@ -0,0 +1,160 @@
/*
GenTreePart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A tree implied by a sequence, done in a generic way.
* This is a tree implied by a structure, but in a generic way: an interface,
* GTreePartModel, is used to provide the tree structure.
* <p>
* I <b>still</b> don't know whether Parsed helps...
* @see GenTreePart
*/
public class GenTreePart extends ZZSpacePart {
public static final String rcsid = "$Id: GenTreePart.java,v 1.2 2000/11/16 21:01:56 tjl Exp $";
static public class Parsed {
String orig;
int depth;
}
GenTreePartModel model;
Depth dd = new Depth();
Breadth db = new Breadth();
public GenTreePart(ZZSpace space, String id, GenTreePartModel model) {
super(space, id);
this.model = model;
}
public ZZDimension getDim(String name) {
if(name.equals("depth")) return dd;
if(name.equals("breadth")) return db;
return null;
}
public class Depth extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
int level;
int maxlevel ;
if(c.part == GenTreePart.this) {
Parsed par = (Parsed)c.parsedID;
level = par.depth;
c = (ZZCellHandle)this.space.getCellByID(par.orig);
maxlevel = model.depth(c);
} else {
// It's either beginning or also end of rank.
level = model.depth(c);
if(level == -1) return null;
maxlevel = level;
}
if(maxlevel < 0) return null;
level -= steps;
if(level < 0) return null;
if(level > maxlevel) return null;
if(level == maxlevel) return c;
return GenTreePart.this.space.getCellByID(
GenTreePart.this,
level + "-" + c.id);
}
}
public class Breadth extends ZZDimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
ZZCell searchFrom;
int level;
if(c.part == GenTreePart.this) {
Parsed par = (Parsed)c.parsedID;
level = par.depth;
c = (ZZCellHandle)this.space.getCellByID(par.orig);
} else {
level = model.depth(c);
if(level < 0) return null;
}
ZZCell n = model.getNext(level, c, steps);
if(n == null) return null;
int lastlevel = model.depth(n);
// Return our cell: the cell we ended up at may be at higher level.
if(lastlevel > level) {
return GenTreePart.this.space.getCellByID(
GenTreePart.this,
level + "-" + n.getID());
} else {
return (ZZCellHandle)n;
}
}
public void disconnect(ZZCellHandle c, int dir) {
// Only do it negwards
if(dir > 0) {
ZZCellHandle c2 = s(c, 1);
if(c2 != null)
disconnect(c2, -1);
return;
}
// Get headcell
ZZCell ct = dd.h(c, -1);
model.disconnectNeg(ct);
}
public void connect(ZZCellHandle c, ZZCellHandle d) {
if(s(c, 1) != null)
throw new ZZConnectWouldBreakError("In gentreedepth");
if(s(d, -1) != null)
throw new ZZConnectWouldBreakError("In gentreedepth2");
ZZCell c1 = dd.h(c, -1);
ZZCell d1 = dd.h(d, -1);
model.connect(c1, d1);
}
}
public String getText(ZZCellHandle c) {
return "+";
}
public void setContent(ZZCellHandle c, Object o) {
}
public Object parseIDPart(String idPart) {
int min = idPart.indexOf("-");
Parsed ret = new Parsed();
ret.orig = idPart.substring(min+1);
ret.depth = Integer.parseInt(idPart.substring(0, min));
return ret;
}
public String generateIDPart(Object parsed) {
Parsed p = (Parsed)parsed;
return p.depth+"-"+p.orig;
}
}

View File

@@ -0,0 +1,77 @@
/*
GTreePartModel.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** A tree model that provides enough information for GTreePart to
* make a tree appear in the structure.
* Assumes that a real (or at least not generated by this GTreePart) cell
* exists for each tree node or leaf.
* The depth in the tree is a constant, and depth is counted from leaves
* upwards, starting from 0, and the largest depth(cell) is depth()-1.
* <p>
* This interface is heavily geared towards the thinking of having
* a single rank of cells, onto which the information about the levels
* of hierarchy is somehow connected.
* The same cell should <em>not</em> be given at different depths so
* using the marker cells is recommended.
* <p>
* These are NOT documented clearly enough - see the sample implementation
* in ../Modules/nile or GTreePartTestModel.
* @see GenTreePart
*/
public interface GenTreePartModel {
String rcsid = "$Id: GenTreePartModel.java,v 1.1 2000/11/16 00:25:10 tjl Exp $";
/** The depth of the whole tree.
*/
int depth();
/** The depth of this cell.
* This method should return -1 if the cell does not belong
* to the tree properly.
*/
int depth(ZZCell c);
/** Move N steps of at least this depth pos- or negwards.
*/
ZZCell getNext(int mindepth, ZZCell c, int steps);
/** Disconnect negwards from the given cell.
*/
void disconnectNeg(ZZCell c);
/** Connect the given cell poswards to the other.
*/
void connect(ZZCell c, ZZCell d);
/** Set the depth of the given cell.
* This method should ONLY touch the depth of the given cell.
* Its virtual "children" will be handled by the GTreePart.
*/
void setDepth(ZZCell c, int d);
}

View File

@@ -0,0 +1,83 @@
/*
GTreePartTestModel.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** A simple model to test GenTreePart.
* The same model as ImpliedTreePart has, except that the depth
* numbers are reversed and are 0, 1, 2 and 3.
* The actual cells in the stream are not included in the tree, only
* the section marker cells.
* @see GenTreePart
*/
public class GenTreeTestModel implements GenTreePartModel {
public static final String rcsid = "$Id: GenTreeTestModel.java,v 1.1 2000/11/16 00:25:10 tjl Exp $";
public static boolean dbg = true;
final static void p(String s) { if(dbg) System.out.println(s); }
final static void pa(String s) { System.out.println(s); }
public int depth() {
return 4;
}
public int depth(ZZCell c) {
if(c.s("d.1") == null)
return -1;
// So the int it 0..3
return Integer.parseInt(c.getText());
}
public ZZCell getNext(int mindepth, ZZCell c, int steps) {
if(steps == 0) return c;
c = c.s("d.1");
int dir = (steps > 0 ? 1 : -1);
ZZCell lasthdr = null;
while(steps != 0 && c != null) {
c = c.s("d.2", dir);
if(c == null) return null;
lasthdr = c.s("d.1", -1);
if(lasthdr == null) continue;
if(depth(lasthdr) < mindepth) continue;
steps -= dir;
}
if(c == null) return null;
return lasthdr;
}
public void disconnectNeg(ZZCell c) {
p("Model: disconnectneg "+c);
c.h("d.1", 1).disconnect("d.2", -1);
}
public void connect(ZZCell c, ZZCell d) {
p("Model: connect "+c+" "+d);
c.h("d.1", 1).h("d.2", 1).connect("d.2", d.h("d.1", 1));
}
public void setDepth(ZZCell c, int d) {
if(depth(c) == 0) return;
c.setText(""+d);
}
}

View File

@@ -0,0 +1,173 @@
/*
ImpliedTreePart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A tree implied by a sequence.
* A proof of concept of having a straight
* stream of material with "tags" connected next to it imply
* a tree.
* <p>
* Connect a bunch of stuff on d.2 and add cells with numbers connected
* negwards on d.1, then view on imptree:depth and imptree:breadth
* <p>
* The number is the level of the heading, reverse from HTML
* (1 is next to text, 2 is next above etc).
* For a heading of level N, N-1 cells are generated.
* The IDs of the generated cells are of the form
* k-ID where k is the level from the text up.
* So a heading of level 4 (cell ID 26) would have the following
* cells connected along depth: 26, i:3-26, i:2-26 and i:1-26.
* <p>
* One problem of space parts: changing the section depth deletes cells,
* and cursors on those cells should be notified!
*/
public class ImpliedTreePart extends ZZROStrSpacePart {
public static final String rcsid = "$Id: ImpliedTreePart.java,v 1.3 2000/11/13 11:59:32 tjl Exp $";
public ImpliedTreePart(ZZSpace space, String id) {
super(space, id);
}
public String getText(ZZCellHandle c) {
return c.id.substring(c.id.length()-1);
}
Depth dd = new Depth();
Breadth db = new Breadth();
public ZZDimension getDim(String name) {
if(name.equals("depth")) return dd;
if(name.equals("breadth")) return db;
return null;
}
public class Depth extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
int level;
if(c.part == ImpliedTreePart.this) {
int col = c.id.indexOf(":");
int min = c.id.indexOf("-");
level = Integer.parseInt(c.id.substring(col+1, min));
c = (ZZCellHandle)this.space.getCellByID(c.id.substring(min+1));
} else {
// It's either beginning or end of rank.
if(c.s("d.1", 1) != null) {
level = posno(c);
} else {
if(steps > 0) return null;
c = (ZZCellHandle)c.s("d.1", -1);
if(c == null) return null;
level = 0;
}
}
int maxlevel = posno(c);
if(maxlevel < 0) return null;
level -= steps;
if(level < 0) return null;
if(level == 0) return (ZZCellHandle)c.s("d.1", 1);
if(level > maxlevel) return null;
if(level == maxlevel) return c;
return ImpliedTreePart.this.space.getCellByID(
ImpliedTreePart.this,
level + "-" + c.id);
}
}
int posno(ZZCell c) {
try {
return Integer.parseInt(c.getText().trim());
} catch(NumberFormatException e) {
ZZLogger.log("Not a number! '"+c.getText()+"' "+c+" "+e);
return -1;
}
}
public class Breadth extends ZZDimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
ZZCell searchFrom;
int level;
if(c.part == ImpliedTreePart.this) {
int col = c.id.indexOf(":");
int min = c.id.indexOf("-");
level = Integer.parseInt(c.id.substring(col+1, min));
c = (ZZCellHandle)this.space.getCellByID(c.id.substring(min+1));
} else {
if(c.s("d.1", 1) == null)
return (ZZCellHandle)c.s("d.2", steps);
level = posno(c);
if(level < 0) return null;
}
searchFrom = c.s("d.1");
if(searchFrom == null) return null;
int dir = (steps > 0 ? 1 : -1);
int lastlevel = -1;
ZZCell lasthdr = null;
while(steps != 0) {
searchFrom = searchFrom.s("d.2", dir);
if(searchFrom == null) return null;
lasthdr = searchFrom.s("d.1", -1);
if(lasthdr == null) continue;
if((lastlevel = posno(lasthdr)) < level) continue;
steps -= dir;
}
// Return our cell: the cell we ended up at is at higher level.
if(lastlevel > level) {
return ImpliedTreePart.this.space.getCellByID(
ImpliedTreePart.this,
level + "-" + lasthdr.getID());
} else {
return (ZZCellHandle)lasthdr;
}
}
public void disconnect(ZZCellHandle c, int dir) {
if(dir > 0) {
ZZCellHandle c2 = s(c, 1);
if(c2 != null)
disconnect(c2, -1);
return;
}
ZZCell ct = dd.h(c, 1);
ct.disconnect("d.2", -1);
}
public void connect(ZZCellHandle c, ZZCellHandle d) {
if(s(c, 1) != null)
throw new ZZConnectWouldBreakError("In impliedtreedepth");
if(s(d, -1) != null)
throw new ZZConnectWouldBreakError("In impliedtreedepth2");
ZZCell c1 = dd.h(c, 1).h("d.2", 1);
ZZCell d1 = dd.h(d, 1).h("d.2", -1);
c1.connect("d.2", d1);
}
}
}

View File

@@ -0,0 +1,192 @@
/*
ImpliedTreePart2.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A tree implied by a sequence.
* <b>Second version, to test the parsed space part stuff.</b>
* A proof of concept of having a straight
* stream of material with "tags" connected next to it imply
* a tree.
* <p>
* Connect a bunch of stuff on d.2 and add cells with numbers connected
* negwards on d.1, then view on imptree:depth and imptree:breadth
* <p>
* The number is the level of the heading, reverse from HTML
* (1 is next to text, 2 is next above etc).
* For a heading of level N, N-1 cells are generated.
* The IDs of the generated cells are of the form
* k-ID where k is the level from the text up.
* So a heading of level 4 (cell ID 26) would have the following
* cells connected along depth: 26, i:3-26, i:2-26 and i:1-26.
* <p>
* One problem of space parts: changing the section depth deletes cells,
* and cursors on those cells should be notified!
*/
public class ImpliedTreePart2 extends ZZSpacePart {
public static final String rcsid = "$Id: ImpliedTreePart2.java,v 1.1 2000/11/13 11:59:48 tjl Exp $";
static public class Parsed {
String orig;
int depth;
}
public ImpliedTreePart2(ZZSpace space, String id) {
super(space, id);
}
public String getText(ZZCellHandle c) {
return c.id.substring(c.id.length()-1);
}
public void setContent(ZZCellHandle c, Object o) {
}
public Object parseIDPart(String idPart) {
int min = idPart.indexOf("-");
Parsed ret = new Parsed();
ret.orig = idPart.substring(min+1);
ret.depth = Integer.parseInt(idPart.substring(0, min));
return ret;
}
public String generateIDPart(Object parsed) {
Parsed p = (Parsed)parsed;
return p.depth+"-"+p.orig;
}
Depth dd = new Depth();
Breadth db = new Breadth();
public ZZDimension getDim(String name) {
if(name.equals("depth")) return dd;
if(name.equals("breadth")) return db;
return null;
}
public class Depth extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
int level;
if(c.part == ImpliedTreePart2.this) {
Parsed par = (Parsed)c.parsedID;
level = par.depth;
c = (ZZCellHandle)this.space.getCellByID(par.orig);
} else {
// It's either beginning or end of rank.
if(c.s("d.1", 1) != null) {
level = posno(c);
} else {
if(steps > 0) return null;
c = (ZZCellHandle)c.s("d.1", -1);
if(c == null) return null;
level = 0;
}
}
int maxlevel = posno(c);
if(maxlevel < 0) return null;
level -= steps;
if(level < 0) return null;
if(level == 0) return (ZZCellHandle)c.s("d.1", 1);
if(level > maxlevel) return null;
if(level == maxlevel) return c;
return ImpliedTreePart2.this.space.getCellByID(
ImpliedTreePart2.this,
level + "-" + c.id);
}
}
int posno(ZZCell c) {
try {
return Integer.parseInt(c.getText().trim());
} catch(NumberFormatException e) {
ZZLogger.log("Not a number! '"+c.getText()+"' "+c+" "+e);
return -1;
}
}
public class Breadth extends ZZDimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(steps == 0) return c;
ZZCell searchFrom;
int level;
if(c.part == ImpliedTreePart2.this) {
Parsed par = (Parsed)c.parsedID;
level = par.depth;
c = (ZZCellHandle)this.space.getCellByID(par.orig);
} else {
if(c.s("d.1", 1) == null)
return (ZZCellHandle)c.s("d.2", steps);
level = posno(c);
if(level < 0) return null;
}
searchFrom = c.s("d.1");
if(searchFrom == null) return null;
int dir = (steps > 0 ? 1 : -1);
int lastlevel = -1;
ZZCell lasthdr = null;
while(steps != 0) {
searchFrom = searchFrom.s("d.2", dir);
if(searchFrom == null) return null;
lasthdr = searchFrom.s("d.1", -1);
if(lasthdr == null) continue;
if((lastlevel = posno(lasthdr)) < level) continue;
steps -= dir;
}
// Return our cell: the cell we ended up at is at higher level.
if(lastlevel > level) {
return ImpliedTreePart2.this.space.getCellByID(
ImpliedTreePart2.this,
level + "-" + lasthdr.getID());
} else {
return (ZZCellHandle)lasthdr;
}
}
public void disconnect(ZZCellHandle c, int dir) {
if(dir > 0) {
ZZCellHandle c2 = s(c, 1);
if(c2 != null)
disconnect(c2, -1);
return;
}
ZZCell ct = dd.h(c, 1);
ct.disconnect("d.2", -1);
}
public void connect(ZZCellHandle c, ZZCellHandle d) {
if(s(c, 1) != null)
throw new ZZConnectWouldBreakError("In impliedtreedepth");
if(s(d, -1) != null)
throw new ZZConnectWouldBreakError("In impliedtreedepth2");
ZZCell c1 = dd.h(c, 1).h("d.2", 1);
ZZCell d1 = dd.h(d, 1).h("d.2", -1);
c1.connect("d.2", d1);
}
}
}

634
Java/part/VersionPart.java Normal file
View File

@@ -0,0 +1,634 @@
/*
VersionPart.java
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Antti-Juhani Kaijanaho
*/
package org.gzigzag;
import java.util.*;
/** <b>EXPERIMENTAL:</b> A space part showing past versions of a ZZCacheDimSpace.
*/
public class VersionPart extends ZZROSpacePart {
public static final String rcsid = "$Id: VersionPart.java,v 1.15.2.1 2001/04/08 16:24:49 ajk Exp $";
public static boolean dbg = false;
private static void p(String s) { if(dbg) ZZLogger.log(s); }
private static void pa(String s) { ZZLogger.log(s); }
private static final Object nolla = new Object();
protected static final ZZObsTrigger ot = new ZZObsTrigger();
public static boolean regular_dimensions = false;
protected Hashtable dimensions = new Hashtable();
protected String listDimensionName = "list";
protected String activeDimensionName = "active";
public VersionPart(ZZCacheDimSpace cds, String s) {
super(cds, s);
if (cds == null) throw new ZZError("null cds");
dimensions.put(listDimensionName, new ListDimension());
dimensions.put("home", new HomeDimension());
dimensions.put(activeDimensionName, new ActiveDimension());
dimensions.put("version-active", new ActiveCellVersionsDimension());
}
// spaces and stamps form a combined data structure where spaces
// provides fast lookup of SpaceElements based on space timestamps
// and stamps contains the active timestamps in ascending order.
private Hashtable spaces = new Hashtable();
private Vector stamps = new Vector();
/** Show what's in stamps. This is a debugging method. */
private void dump_stamps() {
if (!dbg) return;
for (int i = 0; i < stamps.size(); i++) {
pa("stamps[" + i + "] == " + stamps.elementAt(i));
}
}
/** A set of data about one space. */
private class SpaceElement {
/** The space timestamp. */
Integer stampo;
/** Index of this SpaceElement in stamps. */
int inx;
/** The space itself. */
ZZCacheDimSpace space;
/** The cell that denotes this space in the version:list
* rank. */
ZZDimSpace.DimCell cell;
/** A cache of wrapper cells, keyed by unwrapped cell IDs, for
* this space. */
private Hashtable wrappercells = new Hashtable();
/** A cache of wrapper dimensions, keyed by unwrapped
* dimension IDs, for this space. A key may map to "nolla",
* which means that the key does not denote an existing
* dimension. */
private Hashtable wrapperdims = new Hashtable();
public void activate() {
if (space == null) {
space = new ZZCacheDimSpace((ZZCacheDimSpace)VersionPart.this.space, stampo.intValue());
put(this);
}
}
/** Get a wrapper cell for the cell "old". */
public VersionCell getWrapperCell(ZZCellHandle old) {
return getWrapperCell(old, old.getID());
}
public VersionCell getWrapperCell(String oldid) {
return getWrapperCell((ZZCellHandle)space.getCellByID(oldid), oldid);
}
public VersionCell getWrapperCell(ZZCellHandle old, String oldid) {
if (wrappercells.containsKey(oldid)) {
return (VersionCell)wrappercells.get(oldid);
} else {
VersionCell vc = new VersionCell(this, old);
wrappercells.put(oldid, vc);
return vc;
}
}
/** Get a wrapper dimension for the dimension "dim". */
public VersionDimension getWrapperDimension(String dim) {
if (wrapperdims.containsKey(dim)) {
Object o = wrapperdims.get(dim);
if (o == nolla) return null;
return (VersionDimension)o;
} else {
try {
wrapperdims.put(dim, new VersionDimension(this, dim));
} catch (ZZError e) {
wrapperdims.put(dim, nolla);
}
return getWrapperDimension(dim);
}
}
}
/** Return a cell with this ID. */
public ZZDimSpace.DimCell getCellByID(String s) {
ID id = (ID)parseIDPart(s);
SpaceElement se = getSpaceElement(id.stamp);
if (id.id == null) {
return se.cell;
} else {
se.activate();
return se.getWrapperCell((ZZCellHandle)se.space.getCellByID(id.id));
}
}
/** Put se in spaces and update stamps. */
private void put(SpaceElement se) {
synchronized (spaces) {
int i;
for (i = 0; i < stamps.size(); i++) {
if (((Integer)stamps.elementAt(i)).intValue() >= se.stampo.intValue()) break;
}
stamps.insertElementAt(se.stampo, i);
se.inx = i;
for (int j = i + 1; j < stamps.size(); j++) {
Integer stampo = (Integer)stamps.elementAt(j);
SpaceElement sep = (SpaceElement)spaces.get(stampo);
++sep.inx;
}
spaces.put(se.stampo, se);
}
ot.chg(spaces);
}
/** Get a SpaceElement corresponding to stamp. */
protected SpaceElement getActiveSpaceElement(int stamp) {
return getActiveSpaceElement(new Integer(stamp));
}
/** Get a SpaceElement corresponding to stampo and activate it. */
protected SpaceElement getActiveSpaceElement(Integer stampo) {
synchronized (spaces) {
SpaceElement se = getSpaceElement(stampo);
se.activate();
return se;
}
}
/** Get a SpaceElement corresponding to stamp. */
protected SpaceElement getSpaceElement(int stamp) {
return getSpaceElement(new Integer(stamp));
}
/** Get a SpaceElement corresponding to stampo. */
protected SpaceElement getSpaceElement(Integer stampo) {
synchronized (spaces) {
if (spaces.containsKey(stampo)) {
return ((SpaceElement)spaces.get(stampo));
} else {
SpaceElement se = new SpaceElement();
se.inx = Integer.MAX_VALUE;
se.stampo = stampo;
se.space = null;
se.cell = new ListCell(se);
return se;
}
}
}
/** Return the space corresponding to stamp. */
protected ZZCacheDimSpace getSpace(int stamp) {
return getActiveSpaceElement(stamp).space;
}
/** Activate the space corresponding to stamp. */
public void loadVersion(int stamp) {
if (stamp > ((ZZCacheDimSpace)space).timestamp)
stamp = ((ZZCacheDimSpace)space).timestamp;
getActiveSpaceElement(stamp);
}
/** A parsed representation of a cell's or dimension's ID. */
protected static class ID {
/** The wrapped dimension or cell's ID or null, if this is a list cell. */
public final String id;
/** The space timestamp related to this cell or dimension. */
public final int stamp;
public ID(String id, int stamp) {
this.id = id;
this.stamp = stamp;
}
public String toString() {
if (id == null) return "" + stamp;
return "" + stamp + "." + id;
}
}
public ZZDimension getDim(String name) {
pa("VersionPart.getDim(" + name + ")");
if (dimensions.containsKey(name)) return (ZZDimension)dimensions.get(name);
if (name.substring(0, 2).equals("d."))
return new AllVersionDimension(name);
ID did = (ID)parseIDPart(name);
SpaceElement cds = getActiveSpaceElement(did.stamp);
return cds.getWrapperDimension(did.id);
}
/** A wrapper cell for cells in old space versions. */
protected class VersionCell extends ZZDimSpace.DimCell {
final ZZCellHandle old;
public VersionCell(SpaceElement se, ZZCellHandle old) {
VersionPart.this.space.super(VersionPart.this,
new ID(old.getID(), se.stampo.intValue()));
this.old = old;
}
private boolean isIgnoredDim(String dim) {
return dim.equals("d.cursor")
|| dim.equals("d.cursor-list")
|| dim.equals("d.cursor-cargo")
|| dim.indexOf(':') != -1;
}
public ZZCell s(String dim, int dir, ZZObs o) {
ZZCell rv = s(dim, dir, o, new Object());
p("(" + this + ").s(" + dim + ", " + dir + ", " + o + ") ==> " + rv);
return rv;
}
private ZZCell s(String dim, int dir, ZZObs o, Object foo) {
if (!regular_dimensions || isIgnoredDim(dim))
return super.s(dim, dir, o);
// Connected in current version? If yes, use the connection.
ZZCell c = super.s(dim, dir, o);
if (c != null) return c;
// No? Is there a connection in past active versions.
// If yes, use the newest.
synchronized (spaces) {
int n = stamps.size();
for (int i = n - 1; i >= 0; --i) {
Integer stampo = (Integer)stamps.elementAt(i);
p("trying with " + stampo);
SpaceElement se = getActiveSpaceElement(stampo);
VersionDimension vd = se.getWrapperDimension(dim);
c = vd.s(this, dir, o);
if (c != null) return c;
}
}
// No? Then there is no connection.
return null;
}
public void disconnect(String dim, int dir) {
if (regular_dimensions && !isIgnoredDim(dim)) {
if (s(dim, dir, null) != null) {
throw new ZZError("immutable connection");
}
}
super.disconnect(dim, dir);
}
public void setText(String text) {
throw new ZZError("readonly cell");
}
public void setSpan(Span text) {
throw new ZZError("readonly cell");
}
public String getText(ZZObs o) {
return old.getText(o);
}
public Span getSpan(ZZObs o) {
return old.getSpan(o);
}
public void delete() {
throw new ZZError("immutable cell");
}
}
/** A cell in the active spaces list. */
protected class ListCell extends ZZDimSpace.DimCell {
SpaceElement se;
public ListCell(SpaceElement se) {
VersionPart.this.space.super(VersionPart.this,
new ID(null, se.stampo.intValue()));
p("new ListCell, ID = " + getID());
this.se = se;
}
/** Create a new cell. If creating along version:list, we
* activate the next or previous space version. Otherwise we
* redelegate to the superclass. */
public ZZCell N(String dim, int dir, ZZObs o, long flags) {
if (!dim.equals(VersionPart.this.id + ":" + activeDimensionName))
return super.N(dim, dir, o, flags);
loadVersion(se.stampo.intValue() + dir);
return VersionPart.this.space.d(VersionPart.this.id + ":" + activeDimensionName).s(this, dir, o);
}
public void setText(String text) {
throw new ZZError("readonly cell");
}
public void setSpan(Span text) {
throw new ZZError("readonly cell");
}
public void delete() {
VersionPart.this.space.deleteCell(this);
se.space = null;
}
}
/** Dimension that lists all active versions. This dimension has
* funky semantics. First of all, there is always at most one
* nontrivial rank on this dimension. That rank's headcell is
* always the space homecell. The other cells are ListCells (ID
* of type "version:NUMBER") and they are listed on that rank in
* ascending numeric order on their content. The content always
* equals the NUMBER in the cell ID. If you connect some cell
* containing a number to this rank, the number is interpreted as
* a version and that version is activated. This means that
* instead of the cell appearing on that rank, a new cell appears
* in the right place and time. Disconnecting from this rank
* deactivates that version. One cannot connect to homecell's
* negative side or to other ranks on this dimension. */
protected class ActiveDimension extends ZZDimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) {
ZZCellHandle rv;
// inx will first denote the index of c in stamps; steps
// will then be added to it to make it point to the index
// in staps of the return value (or off-bounds if we want
// to return null)
int inx = Integer.MIN_VALUE;
try {
synchronized (spaces) {
if (c.equals(VersionPart.this.space.getHomeCell())) {
// home cell's posward neighbour is stamps[0]
inx = -1;
} else {
ID id = (ID)parseID(c.getID());
if (id.id != null) {
// not a home cell or a ListCell, so we
// want to end up out of bounds
inx = -2-steps;
} else {
// this is a ListCell, look up the index in stamps
SpaceElement se = ((ListCell)c).se;
inx = se.inx;
}
}
// now inx will index the return value
inx += steps;
if (inx == -1) {
// stamps[0]'s negward neighbour is the home cell
rv = (ZZCellHandle)VersionPart.this.space.getHomeCell();
} else if (inx == stamps.size()) {
// We're technically out of bounds, but this
// is sooo useful! We'll have the last
// committed version always as the tailcell.
// Its presence as the tailcell does not
// necessarily mean it's activated, however;
// we want it to remain unactivated after a
// new commit if it has not been examined, but
// also we want it to magically be active
// after a commit otherwise.
Integer stampo = new Integer(((ZZCacheDimSpace)VersionPart.this.space).timestamp);
// Careful here! If the tailcell version is
// active, it is stamps[stamps.size()-1] and
// thus we must not give it a posward
// neighbour that it is itself (that would
// break rank invariants)
if (spaces.containsKey(stampo))
rv = null;
else {
// Okay, it's unactivated.
rv = getSpaceElement(stampo).cell;
}
} else if (inx < -1 || inx > stamps.size()) {
// off-bounds means no cigar
rv = null;
} else {
// within bounds, so this is straightforward
Integer stampo = (Integer)stamps.elementAt(inx);
rv = getSpaceElement(stampo).cell;
}
}
} catch (SyntaxError e) {
rv = null;
}
p("ActiveDimension.s(" + c + ", " + steps + ") (inx == " + inx + ", stamps.size() == " + stamps.size() + ") ==> " + rv);
dump_stamps();
if (obs != null) { ot.addObs(spaces, obs); }
return rv;
}
/** Is this cell a ListCell? */
private boolean isOurs(ZZCellHandle c) {
return c.equals(VersionPart.this.space.getHomeCell())
|| (c.part == VersionPart.this
&& ((ID)c.parsedID).id == null);
}
/** "Connect" two cells on this dimension. This is rather
* magical, see the class documentation. */
public void connect(ZZCellHandle c, ZZCellHandle d) {
pa("c = " + c + ", d = " + d);
if (isOurs(c) && isOurs(d)) return; // already on the rank
if (isOurs(c)) loadVersion(Integer.parseInt(d.getText()));
else if (isOurs(d)) loadVersion(Integer.parseInt(c.getText()));
else throw new ZZError("cannot connect those cells");
dump_stamps();
}
/** "Disconnect" two cells on this dimension. This is rather
* magical, see the class documentation. */
public void disconnect(ZZCellHandle c, int dir) {
synchronized (spaces) {
if (c.part != VersionPart.this || ((ID)c.parsedID).id != null) return;
Integer stampo = new Integer(((ID)c.parsedID).stamp);
if (!spaces.containsKey(stampo)) return;
SpaceElement se = (SpaceElement)spaces.get(stampo);
spaces.remove(stampo);
int n = stamps.size();
stamps.removeElementAt(se.inx);
for (int i = se.inx; i < stamps.size(); i++) {
Integer stampone = (Integer)stamps.elementAt(i);
SpaceElement sese = getActiveSpaceElement(stampone);
sese.inx = i;
}
dump_stamps();
}
}
}
protected class ListDimension extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) {
ZZCellHandle home = (ZZCellHandle)VersionPart.this.space.getHomeCell();
int i;
if (c.equals(home)) {
i = 0;
} else {
if (c.part != VersionPart.this) return null;
ID id = (ID)c.parsedID;
if (id.id != null) return null;
i = id.stamp;
}
i += steps;
if (!(0 <= i && i <= ((ZZCacheDimSpace)VersionPart.this.space).timestamp)) return null;
if (obs != null) ot.addObs(dimensions, obs);
if (i == 0) return home;
return getSpaceElement(i).cell;
}
}
/** This dimension connects ListCells to their spaces' homecells.*/
protected class HomeDimension extends ZZRODimension {
// note, this dimension never triggers anything as it is truly RO
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
synchronized (spaces) {
if (c.part != VersionPart.this) return null;
ID id = (ID)c.parsedID;
if (id.id != null) {
if (!getSpace(id.stamp).getHomeCell().getID().equals(id.id)) {
return null;
}
if (steps != -1) return null;
return getActiveSpaceElement(id.stamp).cell;
}
if (steps != 1) return null;
return ((ListCell)c).
se.getWrapperCell((ZZCellHandle)getSpace(id.stamp).getHomeCell());
}
}
}
/** This dimension wraps around dimensions in old space versions. */
protected class VersionDimension extends ZZRODimension {
SpaceElement se;
ZZDimension old;
public VersionDimension(SpaceElement se, String dim) {
this.se = se;
Object o = se.space.d(dim);
if (o == null) throw new ZZError("no such dimension");
old = (ZZDimension)o;
}
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
p("VersionDimension(" + se.stampo + ").s, c = " + c + ", c.part = " + c.part + ", c.getClass() = " + c.getClass());
if (c.part != VersionPart.this) return null;
ID id = (ID)c.parsedID;
if (id.id == null) return null;
if (!(c instanceof VersionCell)) return null;
ZZCellHandle oldc = ((VersionCell)c).old;
if (id.stamp != se.stampo.intValue()) {
se.activate();
oldc = (ZZCellHandle)se.space.getCellByID(c.getID());
}
ZZCellHandle oldrc = old.s(oldc, steps, o);
p("oldc = " + oldc + ", oldrc = " + oldrc);
if (oldrc == null) return null;
return se.getWrapperCell(oldrc);
}
}
protected class AllVersionDimension extends ZZRODimension {
String name;
public AllVersionDimension(String name) {
this.name = name;
}
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs o) {
if(c.part != VersionPart.this)
return (ZZCellHandle)c.s(name, steps, o);
ID id = (ID)c.parsedID;
if(id == null)
return (ZZCellHandle)c.s(name, steps, o);
return getActiveSpaceElement(id.stamp)
.getWrapperDimension(name)
.s(c, steps, o);
}
}
protected class ActiveCellVersionsDimension extends ZZRODimension {
public ZZCellHandle s(ZZCellHandle c, int steps, ZZObs obs) {
synchronized (spaces) {
String cid;
int inx;
if (c.part == VersionPart.this) {
ID id = (ID)c.parsedID;
if (id.id == null) return null;
SpaceElement se_cur = getActiveSpaceElement(id.stamp);
inx = se_cur.inx;
cid = id.id;
} else if (c.part == null) {
inx = stamps.size();
cid = c.getID();
} else {
return null;
}
inx -= steps;
if (inx == stamps.size())
return (ZZCellHandle)VersionPart.this.space.getCellByID(cid);
if (inx < 0 || inx > stamps.size())
return null;
Integer stampo = (Integer)stamps.elementAt(inx);
SpaceElement se_new = getActiveSpaceElement(stampo);
if (obs != null) ot.addObs(spaces, obs);
return se_new.getWrapperCell(cid);
}
}
}
public Object parseIDPart(String s) {
int idx = s.indexOf(".");
if (idx == s.length() -1) {
throw new SyntaxError("syntax error in cell/dimension ID: missing period");
}
String id;
if (idx == -1) {
id = null;
idx = s.length();
} else {
id = s.substring(idx+1);
}
int stamp;
try {
stamp = Integer.parseInt(s.substring(0, idx));
} catch (NumberFormatException e) {
throw new SyntaxError("syntax error in cell/dimension ID: " + e.getMessage());
}
return new ID(id, stamp);
}
public String generateIDPart(Object parsed) {
String rv = ((ID)parsed).toString();
p("VersionPart.generateIDPart returns " + rv);
return rv;
}
public String getText(ZZCellHandle c) {
ID id = (ID)parseID(c.getID());
if (id.id != null) {
return getSpace(id.stamp).getText(id.id);
}
return ""+id.stamp;
}
public void postCommitHook() { ot.chg(dimensions); }
}

View File

@@ -0,0 +1,39 @@
/*
ZZROSpacePart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
/** <b>EXPERIMENTAL:</b> A read-only ZZSpacePart.
*/
public abstract class ZZROSpacePart extends ZZSpacePart {
public static final String rcsid = "$Id: ZZROSpacePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $";
public ZZROSpacePart(ZZSpace space, String id) {
super(space, id);
}
public void setContent(ZZCellHandle c, Object o) {
return;
}
}

View File

@@ -0,0 +1,47 @@
/*
ZZROStrSpacePart.java
*
* Copyright (c) 2000, Ted Nelson and Tuomas Lukka
*
* You may use and distribute under the terms of either the GNU Lesser
* General Public License, either version 2 of the license or,
* at your choice, any later version. Alternatively, you may use and
* distribute under the terms of the XPL.
*
* See the LICENSE.lgpl and LICENSE.xpl files for the specific terms of
* the licenses.
*
* This software 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 README
* file for more details.
*
*/
/*
* Written by Tuomas Lukka
*/
package org.gzigzag;
/** <b>EXPERIMENTAL:</b> A read-only part of a ZZ space that only operates
* on IDs.
*/
public abstract class ZZROStrSpacePart extends ZZROSpacePart {
public static final String rcsid = "$Id: ZZROStrSpacePart.java,v 1.3 2000/11/06 12:39:39 tjl Exp $";
public ZZROStrSpacePart(ZZSpace space, String id) {
super(space, id);
}
public Object parseIDPart(String idPart) {
return null;
}
public String generateID(Object parsed) {
return null;
}
public String generateIDPart(Object parsed) {
return null;
}
}