1 /*
2  * This file is part of ELKI:
3  * Environment for Developing KDD-Applications Supported by Index-Structures
4  *
5  * Copyright (C) 2018
6  * ELKI Development Team
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Affero General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Affero General Public License for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 package de.lmu.ifi.dbs.elki.data;
22 
23 import java.io.IOException;
24 import java.nio.ByteBuffer;
25 import java.util.Collection;
26 
27 import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil;
28 import de.lmu.ifi.dbs.elki.utilities.io.ByteBufferSerializer;
29 import de.lmu.ifi.dbs.elki.utilities.io.FormatUtil;
30 
31 /**
32  * A list of string labels.
33  *
34  * @author Erich Schubert
35  * @since 0.4.0
36  *
37  * @composed - - - String
38  */
39 public class LabelList {
40   /**
41    * Serializer.
42    */
43   public static final ByteBufferSerializer<LabelList> SERIALIZER = new Serializer();
44 
45   /**
46    * Labels.
47    */
48   private String[] labels;
49 
50   /**
51    * Empty label list.
52    */
53   public static final LabelList EMPTY_LABELS = new LabelList(0);
54 
55   /**
56    * Constructor.
57    *
58    * @param initialCapacity initial size
59    */
LabelList(int initialCapacity)60   private LabelList(int initialCapacity) {
61     super();
62     labels = new String[initialCapacity];
63   }
64 
65   /**
66    * Private constructor. Use {@link #make}.
67    *
68    * @param array Label list
69    */
LabelList(String[] array)70   protected LabelList(String[] array) {
71     super();
72     this.labels = array;
73   }
74 
75   /**
76    * Constructor replacement.
77    *
78    * When the label list is empty, it will produce the same instance!
79    *
80    * @param labels Existing labels
81    * @return Label list instance.
82    */
make(Collection<String> labels)83   public static LabelList make(Collection<String> labels) {
84     int size = labels.size();
85     if(size == 0) {
86       return EMPTY_LABELS;
87     }
88     return new LabelList(labels.toArray(new String[size]));
89   }
90 
91   /**
92    * Size of label list.
93    *
94    * @return Size
95    */
size()96   public int size() {
97     return labels.length;
98   }
99 
100   /**
101    * Get the label at position i.
102    *
103    * @param i Position
104    * @return Label
105    */
get(int i)106   public String get(int i) {
107     return labels[i];
108   }
109 
110   @Override
toString()111   public String toString() {
112     return FormatUtil.format(labels, " ");
113   }
114 
115   /**
116    * Serialization class.
117    *
118    * @author Erich Schubert
119    *
120    * @assoc - serializes - SimpleClassLabel
121    */
122   public static class Serializer implements ByteBufferSerializer<LabelList> {
123     @Override
fromByteBuffer(ByteBuffer buffer)124     public LabelList fromByteBuffer(ByteBuffer buffer) throws IOException {
125       final int cnt = ByteArrayUtil.readUnsignedVarint(buffer);
126       LabelList ret = new LabelList(cnt);
127       for(int i = 0; i < cnt; i++) {
128         ret.labels[i] = ByteArrayUtil.STRING_SERIALIZER.fromByteBuffer(buffer);
129       }
130       return ret;
131     }
132 
133     @Override
toByteBuffer(ByteBuffer buffer, LabelList object)134     public void toByteBuffer(ByteBuffer buffer, LabelList object) throws IOException {
135       final int cnt = object.labels.length;
136       ByteArrayUtil.writeUnsignedVarint(buffer, cnt);
137       for(int i = 0; i < cnt; i++) {
138         ByteArrayUtil.STRING_SERIALIZER.toByteBuffer(buffer, object.labels[i]);
139       }
140     }
141 
142     @Override
getByteSize(LabelList object)143     public int getByteSize(LabelList object) throws IOException {
144       final int cnt = object.labels.length;
145       int size = ByteArrayUtil.getUnsignedVarintSize(cnt);
146       for(int i = 0; i < cnt; i++) {
147         size += ByteArrayUtil.STRING_SERIALIZER.getByteSize(object.labels[i]);
148       }
149       return size;
150     }
151   }
152 }
153