001: // kelondroRow.java
002: // (C) 2006 by Michael Peter Christen; mc@anomic.de, Frankfurt a. M., Germany
003: // first published 24.05.2006 on http://www.anomic.de
004: //
005: // This is a part of the kelondro database,
006: // which is a part of YaCy, a peer-to-peer based web search engine
007: //
008: // $LastChangedDate: 2006-04-02 22:40:07 +0200 (So, 02 Apr 2006) $
009: // $LastChangedRevision: 1986 $
010: // $LastChangedBy: orbiter $
011: //
012: // LICENSE
013: //
014: // This program is free software; you can redistribute it and/or modify
015: // it under the terms of the GNU General Public License as published by
016: // the Free Software Foundation; either version 2 of the License, or
017: // (at your option) any later version.
018: //
019: // This program is distributed in the hope that it will be useful,
020: // but WITHOUT ANY WARRANTY; without even the implied warranty of
021: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
022: // GNU General Public License for more details.
023: //
024: // You should have received a copy of the GNU General Public License
025: // along with this program; if not, write to the Free Software
026: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
027:
028: package de.anomic.kelondro;
029:
030: import java.io.UnsupportedEncodingException;
031: import java.util.ArrayList;
032: import java.util.Comparator;
033: import java.util.HashMap;
034: import java.util.Map;
035: import java.util.StringTokenizer;
036:
037: import de.anomic.server.serverByteBuffer;
038: import de.anomic.server.logging.serverLog;
039:
040: public final class kelondroRow {
041:
042: protected kelondroColumn[] row;
043: protected int[] colstart;
044: protected kelondroByteOrder objectOrder;
045: public int objectsize;
046: public int primaryKeyIndex, primaryKeyLength;
047: protected Map<String, Object[]> nickref = null; // a mapping from nicknames to Object[2]{kelondroColumn, Integer(colstart)}
048:
049: public kelondroRow(kelondroColumn[] row,
050: kelondroByteOrder objectOrder, int primaryKey) {
051: assert objectOrder != null;
052: this .objectOrder = objectOrder;
053: this .row = row;
054: assert (objectOrder != null);
055: this .colstart = new int[row.length];
056: this .objectsize = 0;
057: for (int i = 0; i < row.length; i++) {
058: this .colstart[i] = this .objectsize;
059: this .objectsize += this .row[i].cellwidth;
060: }
061: this .primaryKeyIndex = primaryKey;
062: this .primaryKeyLength = (primaryKey < 0) ? this .objectsize
063: : row[primaryKeyIndex].cellwidth;
064: }
065:
066: public kelondroRow(String structure, kelondroByteOrder objectOrder,
067: int primaryKey) {
068: assert (objectOrder != null);
069: this .objectOrder = objectOrder;
070: // define row with row syntax
071: // example:
072: //# Structure=<pivot-12>,'=',<UDate-3>,<VDate-3>,<LCount-2>,<GCount-2>,<ICount-2>,<DCount-2>,<TLength-3>,<WACount-3>,<WUCount-3>,<Flags-1>
073:
074: // parse pivot definition:
075: structure.replace('=', ',');
076:
077: // parse property part definition:
078: int p = structure.indexOf('|');
079: if (p < 0)
080: p = structure.length();
081: ArrayList<kelondroColumn> l = new ArrayList<kelondroColumn>();
082: String attr = structure.substring(0, p);
083: StringTokenizer st = new StringTokenizer(attr, ",");
084: while (st.hasMoreTokens()) {
085: l.add(new kelondroColumn(st.nextToken()));
086: }
087:
088: // define columns
089: this .row = new kelondroColumn[l.size()];
090: this .colstart = new int[row.length];
091: this .objectsize = 0;
092: for (int i = 0; i < l.size(); i++) {
093: this .colstart[i] = this .objectsize;
094: this .row[i] = (kelondroColumn) l.get(i);
095: this .objectsize += this .row[i].cellwidth;
096: }
097: this .primaryKeyIndex = primaryKey;
098: this .primaryKeyLength = (primaryKey < 0) ? this .objectsize
099: : row[primaryKeyIndex].cellwidth;
100: }
101:
102: public final void setOrdering(kelondroByteOrder objectOrder,
103: int primaryKey) {
104: assert (objectOrder != null);
105: this .objectOrder = objectOrder;
106: this .primaryKeyIndex = primaryKey;
107: this .primaryKeyLength = (primaryKey < 0) ? this .objectsize
108: : row[primaryKeyIndex].cellwidth;
109: }
110:
111: public final kelondroOrder<byte[]> getOrdering() {
112: return this .objectOrder;
113: }
114:
115: protected final void genNickRef() {
116: if (nickref != null)
117: return;
118: nickref = new HashMap<String, Object[]>(row.length);
119: for (int i = 0; i < row.length; i++)
120: nickref.put(row[i].nickname, new Object[] { row[i],
121: new Integer(colstart[i]) });
122: }
123:
124: public final int columns() {
125: return this .row.length;
126: }
127:
128: /*
129: public final int objectsize() {
130: return this.objectsize;
131: }
132: */
133: public final kelondroColumn column(int col) {
134: return row[col];
135: }
136:
137: public final int width(int column) {
138: return this .row[column].cellwidth;
139: }
140:
141: public final int[] widths() {
142: int[] w = new int[this .row.length];
143: for (int i = 0; i < this .row.length; i++)
144: w[i] = row[i].cellwidth;
145: return w;
146: }
147:
148: public final String toString() {
149: StringBuffer s = new StringBuffer();
150: s.append(row[0].toString());
151: for (int i = 1; i < row.length; i++) {
152: s.append(", ");
153: s.append(row[i].toString());
154: }
155: return new String(s);
156: }
157:
158: public final Entry newEntry() {
159: return new Entry();
160: }
161:
162: public final Entry newEntry(byte[] rowinstance) {
163: if (rowinstance == null)
164: return null;
165: //assert (rowinstance[0] != 0);
166: assert (this .objectOrder.wellformed(rowinstance, 0,
167: row[0].cellwidth)) : "rowinstance[0] = "
168: + new String(rowinstance, 0, row[0].cellwidth) + " / "
169: + serverLog.arrayList(rowinstance, 0, row[0].cellwidth);
170: if (!(this .objectOrder.wellformed(rowinstance, 0,
171: row[0].cellwidth)))
172: return null;
173: return new Entry(rowinstance, false);
174: }
175:
176: public final Entry newEntry(Entry oldrow, int fromColumn) {
177: if (oldrow == null)
178: return null;
179: assert (oldrow.getColBytes(0)[0] != 0);
180: assert (this .objectOrder.wellformed(oldrow.getColBytes(0), 0,
181: row[0].cellwidth));
182: return new Entry(oldrow, fromColumn, false);
183: }
184:
185: public final Entry newEntry(byte[] rowinstance, int start,
186: boolean clone) {
187: if (rowinstance == null)
188: return null;
189: //assert (rowinstance[0] != 0);
190: assert (this .objectOrder.wellformed(rowinstance, start,
191: row[0].cellwidth)) : "rowinstance = "
192: + new String(rowinstance);
193: // this method offers the option to clone the content
194: // this is necessary if it is known that the underlying byte array may change and therefore
195: // the reference to the byte array does not contain the original content
196: return new Entry(rowinstance, start, clone);
197: }
198:
199: public final Entry newEntry(byte[][] cells) {
200: if (cells == null)
201: return null;
202: assert (cells[0][0] != 0);
203: assert (this .objectOrder.wellformed(cells[0], 0,
204: row[0].cellwidth));
205: return new Entry(cells);
206: }
207:
208: public final Entry newEntry(String external, boolean decimalCardinal) {
209: if (external == null)
210: return null;
211: return new Entry(external, decimalCardinal);
212: }
213:
214: public final EntryIndex newEntryIndex(byte[] rowinstance, int index) {
215: if (rowinstance == null)
216: return null;
217: assert (rowinstance[0] != 0);
218: assert (this .objectOrder.wellformed(rowinstance, 0,
219: row[0].cellwidth));
220: return new EntryIndex(rowinstance, index);
221: }
222:
223: public static class EntryComparator extends
224: kelondroAbstractOrder<Entry> implements
225: kelondroOrder<Entry>, Comparator<Entry> {
226:
227: kelondroByteOrder base;
228:
229: public EntryComparator(kelondroByteOrder baseOrder) {
230: this .base = baseOrder;
231: }
232:
233: public int compare(Entry a, Entry b) {
234: return a.compareTo(b);
235: }
236:
237: public kelondroOrder<Entry> clone() {
238: return new EntryComparator(base);
239: }
240:
241: public long cardinal(Entry key) {
242: return base.cardinal(key.getPrimaryKeyBytes());
243: }
244:
245: public String signature() {
246: return base.signature();
247: }
248:
249: public boolean wellformed(Entry a) {
250: return base.wellformed(a.getPrimaryKeyBytes());
251: }
252:
253: }
254:
255: public class Entry implements Comparable<Entry> {
256:
257: private byte[] rowinstance;
258: private int offset; // the offset where the row starts within rowinstance
259:
260: public Entry() {
261: rowinstance = new byte[objectsize];
262: for (int i = 0; i < objectsize; i++)
263: this .rowinstance[i] = 0;
264: offset = 0;
265: }
266:
267: public Entry(byte[] newrow, boolean forceclone) {
268: this (newrow, 0, forceclone);
269: }
270:
271: public Entry(Entry oldrow, int fromColumn, boolean forceclone) {
272: this (oldrow.rowinstance, oldrow.offset
273: + oldrow.colstart(fromColumn), forceclone);
274: }
275:
276: public Entry(byte[] newrow, int start, boolean forceclone) {
277: if ((!forceclone) && (newrow.length - start >= objectsize)) {
278: this .rowinstance = newrow;
279: this .offset = start;
280: } else {
281: this .rowinstance = new byte[objectsize];
282: System.arraycopy(newrow, start, this .rowinstance, 0,
283: objectsize);
284: this .offset = 0;
285: }
286: //for (int i = ll; i < objectsize; i++) this.rowinstance[i] = 0;
287: }
288:
289: public Entry(byte[][] cols) {
290: assert row.length == cols.length : "cols.length = "
291: + cols.length + ", row.length = " + row.length;
292: this .rowinstance = new byte[objectsize];
293: this .offset = 0;
294: int ll;
295: int cs, cw;
296: for (int i = 0; i < row.length; i++) {
297: cs = colstart[i];
298: cw = row[i].cellwidth;
299: if ((i >= cols.length) || (cols[i] == null)) {
300: for (int j = 0; j < cw; j++)
301: this .rowinstance[cs + j] = 0;
302: } else {
303: //assert cols[i].length <= cw : "i = " + i + ", cols[i].length = " + cols[i].length + ", cw = " + cw;
304: ll = Math.min(cols[i].length, cw);
305: System.arraycopy(cols[i], 0, rowinstance, cs, ll);
306: for (int j = ll; j < cw; j++)
307: this .rowinstance[cs + j] = 0;
308: }
309: }
310: }
311:
312: public Entry(String external, boolean decimalCardinal) {
313: // parse external form
314: if (external.charAt(0) == '{')
315: external = external.substring(1, external.length() - 1);
316: String[] elts = external.split(",");
317: if (nickref == null)
318: genNickRef();
319: String nick;
320: int p;
321: this .rowinstance = new byte[objectsize];
322: this .offset = 0;
323: for (int i = 0; i < elts.length; i++) {
324: p = elts[i].indexOf('=');
325: if (p > 0) {
326: nick = elts[i].substring(0, p).trim();
327: if (p + 1 == elts[i].length())
328: setCol(nick, null);
329: else {
330: if ((decimalCardinal)
331: && (row[i].celltype == kelondroColumn.celltype_cardinal)) {
332: try {
333: setCol(nick, Long.parseLong(elts[i]
334: .substring(p + 1).trim()));
335: } catch (NumberFormatException e) {
336: serverLog.logSevere("kelondroRow",
337: "NumberFormatException for celltype_cardinal; row = "
338: + i
339: + ", celltype = "
340: + row[i].celltype
341: + ", encoder = "
342: + row[i].encoder
343: + ", value = '"
344: + elts[i].substring(
345: p + 1).trim()
346: + "'");
347: setCol(nick, 0);
348: }
349: } else if ((decimalCardinal)
350: && (row[i].celltype == kelondroColumn.celltype_binary)) {
351: assert row[i].cellwidth == 1;
352: try {
353: setCol(nick,
354: new byte[] { (byte) Integer
355: .parseInt(elts[i]
356: .substring(
357: p + 1)
358: .trim()) });
359: } catch (NumberFormatException e) {
360: serverLog.logSevere("kelondroRow",
361: "NumberFormatException for celltype_binary; row = "
362: + i
363: + ", celltype = "
364: + row[i].celltype
365: + ", encoder = "
366: + row[i].encoder
367: + ", value = '"
368: + elts[i].substring(
369: p + 1).trim()
370: + "'");
371: setCol(nick, new byte[] { 0 });
372: }
373: } else if ((decimalCardinal)
374: && (row[i].celltype == kelondroColumn.celltype_bitfield)) {
375: setCol(nick, (new kelondroBitfield(
376: row[i].cellwidth, elts[i]
377: .substring(p + 1).trim()))
378: .bytes());
379: } else {
380: setCol(nick, elts[i].substring(p + 1)
381: .trim().getBytes());
382: }
383: }
384: }
385: }
386: }
387:
388: protected final int colstart(int column) {
389: return colstart[column];
390: }
391:
392: protected final int cellwidth(int column) {
393: return row[column].cellwidth;
394: }
395:
396: public final int compareTo(Entry o) {
397: // compares only the content of the primary key
398: if (objectOrder == null)
399: throw new kelondroException(
400: "objects cannot be compared, no order given");
401: return objectOrder.compare(this .getPrimaryKeyBytes(),
402: ((Entry) o).getPrimaryKeyBytes());
403: }
404:
405: public final boolean equals(Entry otherEntry) {
406: // compares the content of the complete entry
407: byte[] t = this .bytes();
408: byte[] o = otherEntry.bytes();
409: if (o.length != t.length)
410: return false;
411: for (int i = 0; i < t.length; i++) {
412: if (t[i] != o[i])
413: return false;
414: }
415: return true;
416: }
417:
418: public final byte[] bytes() {
419: if ((offset == 0) && (rowinstance.length == objectsize)) {
420: return rowinstance;
421: } else {
422: byte[] tmp = new byte[objectsize];
423: System.arraycopy(rowinstance, offset, tmp, 0,
424: objectsize);
425: return tmp;
426: }
427: }
428:
429: public final void writeToArray(byte[] target, int targetOffset) {
430: // this method shall replace the byte()s where possible, bacause it may reduce the number of new byte[] allocations
431: assert (targetOffset + objectsize <= target.length) : "targetOffset = "
432: + targetOffset
433: + ", target.length = "
434: + target.length + ", objectsize = " + objectsize;
435: System.arraycopy(rowinstance, offset, target, targetOffset,
436: objectsize);
437: }
438:
439: public final int columns() {
440: return row.length;
441: }
442:
443: public final int objectsize() {
444: return objectsize;
445: }
446:
447: public final boolean empty(int column) {
448: return rowinstance[offset + colstart[column]] == 0;
449: }
450:
451: public final void setCol(String nickname, char c) {
452: if (nickref == null)
453: genNickRef();
454: Object[] ref = (Object[]) nickref.get(nickname);
455: if (ref == null)
456: return;
457: rowinstance[offset + ((Integer) ref[1]).intValue()] = (byte) c;
458: }
459:
460: public final void setCol(String nickname, byte[] cell) {
461: if (nickref == null)
462: genNickRef();
463: Object[] ref = (Object[]) nickref.get(nickname);
464: if (ref == null)
465: return;
466: kelondroColumn col = (kelondroColumn) ref[0];
467: setCol(col.encoder, ((Integer) ref[1]).intValue(),
468: col.cellwidth, cell);
469: }
470:
471: public final void setCol(int column, byte[] cell) {
472: setCol(row[column].encoder, colstart[column],
473: row[column].cellwidth, cell);
474: }
475:
476: public final void setCol(int column, char[] cell) {
477: int clstrt = colstart[column];
478: for (int i = 0; i < cell.length; i++)
479: rowinstance[offset + clstrt + i] = (byte) cell[i];
480: for (int i = cell.length; i < row[column].cellwidth; i++)
481: rowinstance[offset + clstrt + i] = 0;
482: }
483:
484: private final void setCol(int encoding, int clstrt, int length,
485: byte[] cell) {
486: if (cell == null) {
487: while (length-- > 0)
488: rowinstance[offset + clstrt + length] = 0;
489: } else {
490: if (cell.length < length) {
491: System.arraycopy(cell, 0, rowinstance, offset
492: + clstrt, cell.length);
493: while (length-- > cell.length)
494: rowinstance[offset + clstrt + length] = 0;
495: } else {
496: //assert cell.length == length;
497: System.arraycopy(cell, 0, rowinstance, offset
498: + clstrt, length);
499: }
500: }
501: }
502:
503: public final void setCol(int column, byte c) {
504: rowinstance[offset + colstart[column]] = c;
505: }
506:
507: public final void setCol(int column, String cell,
508: String encoding) {
509: if (encoding == null)
510: setCol(column, cell.getBytes());
511: else
512: try {
513: setCol(column, (cell == null) ? null : cell
514: .getBytes(encoding));
515: } catch (UnsupportedEncodingException e) {
516: e.printStackTrace();
517: }
518: }
519:
520: public final void setCol(String nick, String cell,
521: String encoding) {
522: if (encoding == null)
523: setCol(nick, cell.getBytes());
524: else
525: try {
526: setCol(nick, cell.getBytes(encoding));
527: } catch (UnsupportedEncodingException e) {
528: e.printStackTrace();
529: }
530: }
531:
532: public final void setCol(String nickname, long cell) {
533: if (nickref == null)
534: genNickRef();
535: Object[] ref = (Object[]) nickref.get(nickname);
536: if (ref == null)
537: return;
538: kelondroColumn col = (kelondroColumn) ref[0];
539: setCol(col.encoder, offset + ((Integer) ref[1]).intValue(),
540: col.cellwidth, cell);
541: }
542:
543: public final void setCol(int column, long cell) {
544: // uses the column definition to choose the right encoding
545: setCol(row[column].encoder, offset + colstart[column],
546: row[column].cellwidth, cell);
547: }
548:
549: private final void setCol(int encoder, int offset, int length,
550: long cell) {
551: switch (encoder) {
552: case kelondroColumn.encoder_none:
553: throw new kelondroException("ROW",
554: "setColLong has celltype none, no encoder given");
555: case kelondroColumn.encoder_b64e:
556: kelondroBase64Order.enhancedCoder.encodeLong(cell,
557: rowinstance, offset, length);
558: break;
559: case kelondroColumn.encoder_b256:
560: kelondroNaturalOrder.encodeLong(cell, rowinstance,
561: offset, length);
562: break;
563: case kelondroColumn.encoder_bytes:
564: throw new kelondroException("ROW",
565: "setColLong of celltype bytes not applicable");
566: }
567: }
568:
569: public final byte[] getCol(String nickname, byte[] dflt) {
570: if (nickref == null)
571: genNickRef();
572: Object[] ref = (Object[]) nickref.get(nickname);
573: if (ref == null)
574: return dflt;
575: kelondroColumn col = (kelondroColumn) ref[0];
576: byte[] cell = new byte[col.cellwidth];
577: System.arraycopy(rowinstance, offset
578: + ((Integer) ref[1]).intValue(), cell, 0,
579: cell.length);
580: return cell;
581: }
582:
583: public final String getColString(String nickname, String dflt,
584: String encoding) {
585: if (nickref == null)
586: genNickRef();
587: Object[] ref = (Object[]) nickref.get(nickname);
588: if (ref == null)
589: return dflt;
590: kelondroColumn col = (kelondroColumn) ref[0];
591: return getColString(col.encoder, ((Integer) ref[1])
592: .intValue(), col.cellwidth, encoding);
593: }
594:
595: public final String getColString(int column, String encoding) {
596: return getColString(row[column].encoder, colstart[column],
597: row[column].cellwidth, encoding);
598: }
599:
600: private final String getColString(int encoder, int clstrt,
601: int length, String encoding) {
602: if (rowinstance[offset + clstrt] == 0)
603: return null;
604: if (length > rowinstance.length - offset - clstrt)
605: length = rowinstance.length - offset - clstrt;
606: while ((length > 0)
607: && (rowinstance[offset + clstrt + length - 1] == 0))
608: length--;
609: if (length == 0)
610: return null;
611: try {
612: if ((encoding == null) || (encoding.length() == 0))
613: return new String(rowinstance, offset + clstrt,
614: length);
615: else
616: return new String(rowinstance, offset + clstrt,
617: length, encoding);
618: } catch (UnsupportedEncodingException e) {
619: return "";
620: }
621: }
622:
623: public final long getColLong(String nickname, long dflt) {
624: if (nickref == null)
625: genNickRef();
626: Object[] ref = (Object[]) nickref.get(nickname);
627: if (ref == null)
628: return dflt;
629: kelondroColumn col = (kelondroColumn) ref[0];
630: int clstrt = ((Integer) ref[1]).intValue();
631: return getColLong(col.encoder, clstrt, col.cellwidth);
632: }
633:
634: public final long getColLong(int column) {
635: // uses the column definition to choose the right encoding
636: return getColLong(row[column].encoder, colstart[column],
637: row[column].cellwidth);
638: }
639:
640: protected final long getColLong(int encoder, int clstrt,
641: int length) {
642: switch (encoder) {
643: case kelondroColumn.encoder_none:
644: throw new kelondroException("ROW",
645: "getColLong has celltype none, no encoder given");
646: case kelondroColumn.encoder_b64e:
647: // start - fix for badly stored parameters
648: if ((length >= 3)
649: && (rowinstance[offset + clstrt] == '[')
650: && (rowinstance[offset + clstrt + 1] == 'B')
651: && (rowinstance[offset + clstrt + 2] == '@'))
652: return 0;
653: if ((length == 2)
654: && (rowinstance[offset + clstrt] == '[')
655: && (rowinstance[offset + clstrt + 1] == 'B'))
656: return 0;
657: if ((length == 1)
658: && (rowinstance[offset + clstrt] == '['))
659: return 0;
660: boolean maxvalue = true;
661: for (int i = 0; i < length; i++)
662: if (rowinstance[offset + clstrt + i] != '_') {
663: maxvalue = false;
664: break;
665: }
666: if (maxvalue)
667: return 0;
668: // stop - fix for badly stored parameters
669: return kelondroBase64Order.enhancedCoder.decodeLong(
670: rowinstance, offset + clstrt, length);
671: case kelondroColumn.encoder_b256:
672: return kelondroNaturalOrder.decodeLong(rowinstance,
673: offset + clstrt, length);
674: case kelondroColumn.encoder_bytes:
675: throw new kelondroException("ROW",
676: "getColLong of celltype bytes not applicable");
677: }
678: throw new kelondroException("ROW",
679: "getColLong did not find appropriate encoding");
680: }
681:
682: public final byte getColByte(String nickname, byte dflt) {
683: if (nickref == null)
684: genNickRef();
685: Object[] ref = (Object[]) nickref.get(nickname);
686: if (ref == null)
687: return dflt;
688: return rowinstance[offset + ((Integer) ref[1]).intValue()];
689: }
690:
691: public final byte getColByte(int column) {
692: return rowinstance[offset + colstart[column]];
693: }
694:
695: public final byte[] getPrimaryKeyBytes() {
696: byte[] c = new byte[primaryKeyLength];
697: System.arraycopy(rowinstance, offset
698: + ((primaryKeyIndex < 0) ? 0
699: : colstart[primaryKeyIndex]), c, 0,
700: primaryKeyLength);
701: return c;
702: }
703:
704: public final byte[] getColBytes(int column) {
705: assert offset + colstart[column] + row[column].cellwidth <= rowinstance.length : "column = "
706: + column
707: + ", offset = "
708: + offset
709: + ", colstart[column] = "
710: + colstart[column]
711: + ", row[column].cellwidth() = "
712: + row[column].cellwidth
713: + ", rowinstance.length = "
714: + rowinstance.length;
715: int w = row[column].cellwidth;
716: byte[] c = new byte[w];
717: System.arraycopy(rowinstance, offset + colstart[column], c,
718: 0, w);
719: return c;
720: }
721:
722: public final char[] getColChars(int column) {
723: int w = row[column].cellwidth;
724: char[] c = new char[w];
725: System.arraycopy(rowinstance, offset + colstart[column], c,
726: 0, w);
727: return c;
728: }
729:
730: public final void writeToArray(int column, byte[] target,
731: int targetOffset) {
732: // this method shall replace the getColBytes where possible, bacause it may reduce the number of new byte[] allocations
733: assert (targetOffset + row[column].cellwidth <= target.length) : "targetOffset = "
734: + targetOffset
735: + ", target.length = "
736: + target.length
737: + ", row[column].cellwidth() = "
738: + row[column].cellwidth;
739: System.arraycopy(rowinstance, offset + colstart[column],
740: target, targetOffset, row[column].cellwidth);
741: }
742:
743: public final String toPropertyForm(boolean includeBraces,
744: boolean decimalCardinal, boolean longname) {
745: serverByteBuffer bb = new serverByteBuffer();
746: if (includeBraces)
747: bb.append('{');
748: for (int i = 0; i < row.length; i++) {
749: bb.append((longname) ? row[i].description
750: : row[i].nickname);
751: bb.append('=');
752: if ((decimalCardinal)
753: && (row[i].celltype == kelondroColumn.celltype_cardinal)) {
754: bb.append(Long.toString(getColLong(i)));
755: } else if ((decimalCardinal)
756: && (row[i].celltype == kelondroColumn.celltype_bitfield)) {
757: bb.append((new kelondroBitfield(getColBytes(i)))
758: .exportB64());
759: } else if ((decimalCardinal)
760: && (row[i].celltype == kelondroColumn.celltype_binary)) {
761: assert row[i].cellwidth == 1;
762: bb.append(Integer.toString((0xff & getColByte(i))));
763: } else {
764: bb.append(rowinstance, offset + colstart[i],
765: row[i].cellwidth);
766: }
767: if (i < row.length - 1) {
768: bb.append(',');
769: if (longname)
770: bb.append(' ');
771: }
772: }
773: if (includeBraces)
774: bb.append('}');
775: //System.out.println("DEBUG-ROW " + bb.toString());
776: return bb.toString();
777: }
778:
779: public final String toString() {
780: return toPropertyForm(true, false, false);
781: }
782:
783: }
784:
785: public final class EntryIndex extends Entry {
786: private int index;
787:
788: public EntryIndex(byte[] row, int i) {
789: super (row, false);
790: this .index = i;
791: }
792:
793: public int index() {
794: return index;
795: }
796: }
797:
798: public final static void long2bytes(long x, byte[] b, int offset,
799: int length) {
800: for (int i = length - 1; i >= 0; i--) {
801: b[offset + i] = (byte) (x & 0XFF);
802: x >>= 8;
803: }
804: }
805:
806: public final static long bytes2long(byte[] b, int offset, int length) {
807: if (b == null)
808: return 0;
809: long x = 0;
810: for (int i = 0; i < length; i++)
811: x = (x << 8) | (0xff & b[offset + i]);
812: return x;
813: }
814:
815: public final boolean subsumes(kelondroRow otherRow) {
816: // returns true, if this row has at least all columns as the other row
817: // and possibly some more
818: if (this .objectsize < otherRow.objectsize)
819: return false;
820: for (int i = 0; i < otherRow.row.length; i++) {
821: if ((this .row[i].cellwidth == otherRow.row[i].cellwidth)
822: && (this .row[i].celltype == kelondroColumn.celltype_bitfield)
823: && (otherRow.row[i].celltype == kelondroColumn.celltype_binary))
824: continue;
825: if (!(this .row[i].equals(otherRow.row[i])))
826: return false;
827: }
828: return true;
829: }
830:
831: public final boolean equals(kelondroRow otherRow) {
832: if (this .objectsize != otherRow.objectsize)
833: return false;
834: if (this .columns() != otherRow.columns())
835: return false;
836: for (int i = 0; i < otherRow.row.length; i++) {
837: if (!(this .row[i].equals(otherRow.row[i])))
838: return false;
839: }
840: return true;
841: }
842:
843: }
|