/* * Created on May 10, 2005 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package fr.lifl.stc.stan.link; import java.io.Serializable; import org.apache.bcel.SignatureConstants; import fr.lifl.stc.stan.link.Link; import fr.lifl.stc.stan.link.defaultLink.DefaultLink; /** * @author dorina * * An optimized implementation of the matrix of links. In order to reduce memory consumption, space is * allocated only when needed. Elements of the matrix are accesed through get/set methods. */ public class TableLink implements Serializable{ public static final long serialVersionUID = 0; public final static Link EMPTY_LINK = new DefaultLink(); public static int maxL = 0, maxC = 0; Link t[][]; int sizeL, sizeC; /** * * @param n * @param m */ public TableLink(int n, int m) { super(); sizeL = n; sizeC = m; if(sizeL > maxL ) maxL = sizeL; if(sizeC > maxC ) maxC = sizeC; } public int getSizeL() { return sizeL; } public int getSizeC() { return sizeC; } //FIXME should we clone l or it must be cloned before /** * * @param i * @param j * @param l * @return */ public boolean set(int i, int j, Link l){ if(l==null || l.isEmpty()) return false; if(t == null) t = new Link[sizeL][]; if(t[i] == null) t[i]= new Link[sizeC]; t[i][j] = l; return true; } /** * force the value at position (i,j) to l * @param i * @param j * @param l */ public void put(int i, int j, Link l){ if(t!=null && t[i]!=null) t[i][j] = l; } /** * * @param i * @param j * @return */ public Link get(int i, int j){ //checkTable(); //checkLine(i); if(t != null && t[i] != null && t[i][j]!=null) return t[i][j]; return null; } public boolean isEmpty(int i, int j){ if(t==null || t[i]==null || t[i][j]==null) return true; return t[i][j].isEmpty(); } public Object clone(){ TableLink newTable = new TableLink(this.sizeL, this.sizeC); if(this.t != null) { newTable.t = new Link[this.sizeL][]; for(int i = 0; i < this.sizeL; i++){ if(t[i] != null) { newTable.t[i]= new Link[sizeC]; for(int j = 0; j < this.sizeC; j++) { if( t[i][j] != null) newTable.t[i][j] = t[i][j].clone1(); } } } } return newTable; } /*public Object clone(){ TableLink newTable = new TableLink(this.sizeL, this.sizeC); for(int i = 0; i < this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) newTable.set(i, j, this.get(i, j)); return newTable; } */ public boolean equals(Object o) { if(!(o instanceof TableLink)) return false; TableLink l = (TableLink)o; boolean isEqual = true; if(t==null) { if(l.t==null) return true; return false; } if(l.t==null) { return false; } for(int i = 0; i < this.getSizeL(); i++ ) { if(t[i]==null) { if(l.t[i]==null) return true; return false; } if(l.t[i]==null) { return false; } for(int j = 0; j < this.getSizeC(); j++) if(!Link.equals(t[i][j], l.t[i][j])) return false; } return isEqual; } /* public boolean equals(Object o) { if(!(o instanceof TableLink)) return false; TableLink l = (TableLink)o; TableLink l = f.getLinks(); for(int i = 0; i < this.linksFlow.getSizeL(); i++ ) for(int j = 0; j < this.linksFlow.getSizeC(); j++) if(!Link.equals(linksFlow.get(i,j), l.get(i,j))) return false; return true; } */ public Link[][] getTableLinks(){ Link [][] l = new Link[this.sizeL][this.sizeC]; for(int i = 0; i < this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) { Link aux = this.get(i, j); if(aux == null) aux = EMPTY_LINK; l[i][j] = aux; } return l; } public int getLinksNotNull() { int res = 0; for(int i = 0; i < this.sizeL; i++) res += this.getLinksNotNull(i); return res; } public int getLinksNotNull(int line) { if(line >= this.sizeL) return 0; int res = 0; for(int j = 0; j < this.sizeC; j++) { Link l = this.get(line,j); if(l!=null && !l.isEmpty()) res++; } return res; } //=============================== /* * Converts the matrix in a stream of bytes of this form: * * codification_type table_dimensions number_of_flows array_of_flows * * where * * codification_type can be a combination between ( SIMPLE_CODIFICATION od DOUBLE_CODIFICATION) and ACC_NEW_SIGNATURE * * table_dimension represent the number of line/columns of the signature * * number_of_links is coded on 1 or 2 bytes (depends od codification_type) * * array_of_flow contains elements of this format: * line column value_of_flow * * Empty links are excluded * * the codification_type depends on the matrix dimension: * if dimension < 15 , line and column are coded on 4 bits each (1 byte in total) * else , line and column are coded on 1 byte each (2 bytes in total) * link is coded on 1 byte. * * @param previous the codification should consist in specifying if we encode a new signature or the differences between previous */ public byte[] toBytes(TableLink previous) { byte b[]; int linksNotNull = 0; //FIXME : links deleted int noModif = 0; int noErase = 0; if(previous !=null){ for(int i = 0; i< this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) { if(previous.isEmpty(i,j) && !this.isEmpty(i,j)) noModif++; else if(!previous.isEmpty(i,j) && this.isEmpty(i,j)) noErase++; } linksNotNull = noModif + noErase; } else { linksNotNull = this.getLinksNotNull(); } int lengthSize = codificationType()== SignatureConstants.CODIF_4B ? 1 : 2; int length = 1; if(codificationType() == SignatureConstants.CODIF_4B) length += 2*linksNotNull + lengthSize; else length += 3*linksNotNull + lengthSize; //length for links to be erased also if(previous != null){ length += lengthSize; } //length of table_dimension length += SignatureConstants.LABEL_BYTECODE_SIZE; b = new byte[length]; int index = 0; //set codification_type byte codif = codificationType(); if(previous == null) codif |= SignatureConstants.ACC_NEW_SIGNATURE; b[index++] = codif; //set table_dimension byte[] arrTmp = SignatureConstants.toByteArray(this.sizeL, SignatureConstants.LABEL_BYTECODE_SIZE); System.arraycopy(arrTmp, 0, b, index, arrTmp.length); index += arrTmp.length; if(previous !=null){ //set number_of_links to be addded arrTmp = SignatureConstants.toByteArray(noModif, lengthSize); System.arraycopy(arrTmp, 0, b, index, arrTmp.length); index += arrTmp.length; for(int i = 0; i< this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) { if(previous.isEmpty(i,j) && !this.isEmpty(i,j)){ Link l = this.get(i,j); if(codificationType() == SignatureConstants.CODIF_4B) { int tmp ;//intToByte(i) ; tmp = (i << 4) & 0xF0; tmp = tmp | (j & 0x0F); b[index++] = intToByte(tmp); } else { b[index++] = intToByte(i); b[index++] = intToByte(j); } DefaultLink dl = (DefaultLink)l; b[index++] = dl.getLink(); } } //set number_of_ links to be erased arrTmp = SignatureConstants.toByteArray(noErase, lengthSize); System.arraycopy(arrTmp, 0, b, index, arrTmp.length); index += arrTmp.length; for(int i = 0; i< this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) { if(!previous.isEmpty(i,j) && this.isEmpty(i,j)) { Link l = previous.get(i,j); if(codificationType() == SignatureConstants.CODIF_4B) { int tmp ;//intToByte(i) ; tmp = (i << 4) & 0xF0; tmp = tmp | (j & 0x0F); b[index++] = intToByte(tmp); } else { b[index++] = intToByte(i); b[index++] = intToByte(j); } DefaultLink dl = (DefaultLink)l; b[index++] = dl.getLink(); } } } else { //set number_of_links arrTmp = SignatureConstants.toByteArray(linksNotNull, lengthSize); System.arraycopy(arrTmp, 0, b, index, arrTmp.length); index += arrTmp.length; //set links for(int i = 0; i < this.sizeL; i++) for(int j = 0; j < this.sizeC; j++) { Link l = this.get(i,j); if(l!=null && !l.isEmpty()) { if(codificationType() == SignatureConstants.CODIF_4B) { int tmp ;//intToByte(i) ; tmp = (i << 4) & 0xF0; tmp = tmp | (j & 0x0F); b[index++] = intToByte(tmp); } else { b[index++] = intToByte(i); b[index++] = intToByte(j); } DefaultLink dl = (DefaultLink)l; b[index++] = dl.getLink(); } } } return b; } byte codificationType() { if(this.getSizeC()<16 && this.getSizeL() < 16) return SignatureConstants.CODIF_4B; return SignatureConstants.CODIF_8B; } public static final byte intToByte(int i){ return (byte)i; } }