/*
* Copyright 2011 Uwe Krueger.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mandelsoft.mand.mapping;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author Uwe Krüger
*/
public class MappingBuilder extends BalancedTreeSupport {
private int minIt;
private int maxIt;
private int target;
public MappingBuilder(int minIt, int maxIt, int target)
{
this.maxIt=maxIt;
this.minIt=minIt;
this.target=target;
}
public void setTarget(int target)
{
if (nodecount>0) throw new IllegalArgumentException("no target change during mapping");
this.target=target;
}
public int getTargetSize()
{
return target;
}
public int getSourceSize()
{
return maxIt-minIt+1;
}
public int getMinIt()
{
return minIt;
}
public int getMaxIt()
{
return maxIt;
}
/////////////////////////////////////////////////////////////////////////
private class Node extends TreeNode<Node> {
int value;
int target;
Node(int i, int c)
{
value=i;
target=c;
}
public int compareTo(Node o)
{
if (this.value==o.value) return 0;
if (this.value<o.value) return -1;
return 1;
}
@Override
public String toString()
{
return ""+value+"("+target+")";
}
}
public MappingBuilder()
{
}
public void add(int it, int target)
{
if (target>=this.target) {
throw new IllegalArgumentException("illegal target size "+target+
" max="+this.target);
}
root=add((Node)root, new Node(it, target));
}
private Node add(Node n, Node a)
{
if (n==null) {
return a;
}
if (a.compareTo(n)==0) {
throw new IllegalArgumentException("duplicate key "+a.value);
}
else {
if (a.compareTo(n)>0) {
n.left=add(n.left, a);
n=n.balanceLeft();
}
else {
n.right=add(n.right, a);
n=n.balanceRight();
}
setDepth(n);
}
return n;
}
public int get(int i)
{
if (i>=getSourceSize()) {
throw new IllegalArgumentException("illegal iteration "+i);
}
Node n=(Node)root;
int upper=-1;
while (n!=null) {
if (i>n.value) n=n.left;
else {
upper=n.target;
n=n.right;
}
}
return upper;
}
//////////////////////////////////////////////////////////////////////////
// creating tree mapping
//////////////////////////////////////////////////////////////////////////
TreeMapping createTreeMapping()
{
TreeMapping.Node tn=copy((Node)root);
return new TreeMapping(tn);
}
private TreeMapping.Node copy(Node n)
{
if (n==null) return null;
return new TreeMapping.Node(n.value, n.target,
copy(n.left), copy( n.right));
}
//////////////////////////////////////////////////////////////////////////
// creating array mapping
//////////////////////////////////////////////////////////////////////////
ArrayMapping createArrayMapping()
{
int[] mapping=new int[getSourceSize()];
fill(mapping,(Node)root,new Node(-1,-1));
// for (int i=0; i<mapping.length;i++) {
// System.out.println(""+i+": "+mapping[i]);
// }
return new ArrayMapping(mapping);
}
private static class Interval {
Node top;
Node bottom;
public Interval(Node top, Node bottom)
{
this.top=top;
this.bottom=bottom;
}
}
private static Interval fill(int[] mapping, Node n, Node bottom)
{
Interval iv;
Node top=n;
Node ivtop=n;
Node ivbottom=bottom;
if (n.left!=null) {
iv=fill(mapping,n.left,n);
ivtop=iv.top;
top=iv.bottom;
}
if (n.right!=null) {
iv=fill(mapping,n.right,bottom);
ivbottom=iv.bottom;
bottom=iv.top;
}
// System.out.println("fill "+n.value+"->"+ivtop.value+","+ivbottom.value+
// " ["+top.value+","+bottom.value+") with "+top.target);
for (int i=top.value; i>bottom.value; i--) mapping[i]=top.target;
return new Interval(ivtop,ivbottom);
}
//////////////////////////////////////////////////////////////////////////
// main
//////////////////////////////////////////////////////////////////////////
static void compare(String msg, MappingTest a, MappingTest b)
{
System.out.println("comparing "+msg);
if (a.getMinIt()!=b.getMinIt())
System.out.println("MinIt mismatch: "+a.getMinIt()+"!="+b.getMinIt());
if (a.getMaxIt()!=b.getMaxIt())
System.out.println("MaxIt mismatch: "+a.getMaxIt()+"!="+b.getMaxIt());
if (a.getTargetSize()!=b.getTargetSize())
System.out.println("target mismatch: "+a.getTargetSize()+"!="+b.getTargetSize());
for (int i=a.getMinIt(); i<=a.getMaxIt(); i++) {
if (a.getColormapIndex(i)!=b.getColormapIndex(i))
System.out.println("mapping mismatch: "+i+": "+
a.getColormapIndex(i)+"!="+b.getColormapIndex(i));
}
}
static private void write(MappingTest m, File f)
{
DataOutputStream dos=null;
try {
dos=new DataOutputStream(new FileOutputStream(f));
try {
m.write(dos, true);
dos.flush();
}
finally {
dos.close();
}
}
catch (IOException ex) {
System.out.println("cannot create "+f+": "+ex);
}
}
static private MappingTest read(File f)
{
MappingTest m=new MappingTest();
DataInputStream dis=null;
try {
dis=new DataInputStream(new FileInputStream(f));
try {
m.read(dis, true);
return m;
}
finally {
dis.close();
}
}
catch (IOException ex) {
System.out.println("cannot read "+f+": "+ex);
}
return null;
}
void print()
{
if (root!=null) root.print("");
}
static public void main(String[] args)
{
MappingBuilder mb=new MappingBuilder(1,20,8);
mb.add(19, 7);
mb.add(8, 6);
mb.add(4, 5);
mb.add(3, 4);
mb.add(2, 3);
mb.add(1, 2);
mb.add(0, 1);
mb.print();
MappingRepresentation mra=mb.createArrayMapping();
MappingRepresentation mrt=mb.createTreeMapping();
MappingTest ma=new MappingTest(mb,mra);
MappingTest mt=new MappingTest(mb,mrt);
for (int i=0; i<mb.getSourceSize(); i++) {
System.out.println(""+i+": "+mb.get(i)+"/ "+mra.getColormapIndex(i)+
"/ "+mrt.getColormapIndex(i));
}
compare("ma<->mt",ma,mt);
File f=new File("C:/work/AccuRev/test/testmapping");
write(mt,f);
MappingTest mr=read(f);
System.out.println("read type "+mr.getType());
compare("mr<->mt",mr,mt);
}
}