/***********************************************************************************************************************
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* 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 eu.stratosphere.compiler.postpass;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import eu.stratosphere.types.Value;
/**
* Class encapsulating a schema map (int column position -> column type) and a reference counter.
*/
public class DenseValueSchema extends AbstractSchema<Class<? extends Value>> {
private final List<Class<? extends Value>> schema;
private int numFields = -1;
public DenseValueSchema() {
this.schema = new ArrayList<Class<? extends Value>>();
}
// --------------------------------------------------------------------------------------------
@Override
public void addType(int pos, Class<? extends Value> type) throws ConflictingFieldTypeInfoException {
if (pos == schema.size()) {
// right at the end, most common case
schema.add(type);
} else if (pos < schema.size()) {
// in the middle, check for existing conflicts
Class<? extends Value> previous = schema.get(pos);
if (previous == null) {
schema.set(pos, type);
} else if (previous != type) {
throw new ConflictingFieldTypeInfoException(pos, previous, type);
}
} else {
// grow to the end
for (int i = schema.size(); i <= pos; i++) {
schema.add(null);
}
schema.set(pos, type);
}
}
@Override
public Class<? extends Value> getType(int field) {
return schema.get(field);
}
@Override
public Iterator<Map.Entry<Integer, Class<? extends Value>>> iterator() {
final Iterator<Class<? extends Value>> iter = schema.iterator();
return new Iterator<Map.Entry<Integer,Class<? extends Value>>>() {
private int pos = 0;
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public java.util.Map.Entry<Integer, Class<? extends Value>> next() {
return new Entry(pos++, iter.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
public int getNumFields() {
return numFields;
}
public void setNumFields(int numFields) {
this.numFields = numFields;
}
// --------------------------------------------------------------------------------------------
@Override
public int hashCode() {
return schema.hashCode() ^ getNumConnectionsThatContributed();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DenseValueSchema) {
DenseValueSchema other = (DenseValueSchema) obj;
return schema.equals(other.schema) &&
getNumConnectionsThatContributed() == other.getNumConnectionsThatContributed();
} else {
return false;
}
}
@Override
public String toString() {
return "<" + getNumConnectionsThatContributed() + "> : " + schema.toString();
}
// --------------------------------------------------------------------------------------------
private static final class Entry implements Map.Entry<Integer, Class<? extends Value>> {
private Integer key;
private Class<? extends Value> value;
public Entry(Integer key, Class<? extends Value> value) {
this.key = key;
this.value = value;
}
@Override
public Integer getKey() {
return this.key;
}
@Override
public Class<? extends Value> getValue() {
return this.value;
}
@Override
public Class<? extends Value> setValue(Class<? extends Value> value) {
throw new UnsupportedOperationException();
}
}
}