/* * Copyright 2012 NGDATA nv * * 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 org.lilyproject.indexer.derefmap; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import com.google.common.collect.Sets; import org.apache.hadoop.hbase.util.Bytes; import org.lilyproject.hbaseindex.filter.IndexFilter; import org.lilyproject.repository.api.SchemaId; import org.lilyproject.repository.impl.id.IdGeneratorImpl; /** * Index filter (hbase-index) used when filtering results from a query on the dereference map. */ public class DerefMapIndexFilter extends IndexFilter { private static final byte[] FIELDS_KEY = Bytes.toBytes("fields"); private Set<SchemaId> queriedFields; private Map<String, String> dependencyRecordVariantProperties; private final DerefMapSerializationUtil serializationUtil = new DerefMapSerializationUtil(new IdGeneratorImpl()); public DerefMapIndexFilter() { // hadoop serialization } /** * @param dependencyRecordVariantProperties * the dependency record variant properties, used to match the variant property pattern * with * @param queriedFields the queried fields, used to match with the field information stored in the deref * map (the queried fields is allowed to be <code>null</code> in order to only match * results that express dependencies that do not go to a field) */ DerefMapIndexFilter(Map<String, String> dependencyRecordVariantProperties, Set<SchemaId> queriedFields) { super(Collections.singleton(FIELDS_KEY), Sets.newHashSet("variant_properties_pattern")); this.queriedFields = queriedFields; this.dependencyRecordVariantProperties = dependencyRecordVariantProperties; } @Override public boolean filterData(byte[] dataQualifier, byte[] data, int offset, int length) { if (queriedFields == null) { return false; } else { if (Arrays.equals(dataQualifier, FIELDS_KEY)) { final Set<SchemaId> dependencyFields = this.serializationUtil.deserializeFields(data, offset, length); if (!containsAtLeastOneElementOf(dependencyFields, queriedFields)) { return true; } } return false; } } @Override public boolean filterField(String name, Object value) { if ("variant_properties_pattern".equals(name)) { final DerefMapVariantPropertiesPattern variantPropertiesPattern = this.serializationUtil.deserializeVariantPropertiesPattern((byte[]) value); if (!variantPropertiesPattern.matches(dependencyRecordVariantProperties)) { return true; } } return false; } private <T> boolean containsAtLeastOneElementOf(Set<T> set, Set<T> elements) { set.retainAll(elements); return !set.isEmpty(); } @Override public void write(DataOutput out) throws IOException { super.write(out); if (queriedFields == null) { out.writeInt(-1); } else { out.writeInt(queriedFields.size()); for (SchemaId queriedField : queriedFields) { final byte[] bytes = queriedField.getBytes(); out.writeInt(bytes.length); out.write(bytes); } } out.writeInt(dependencyRecordVariantProperties.size()); for (Map.Entry<String, String> entry : dependencyRecordVariantProperties.entrySet()) { out.writeUTF(entry.getKey()); out.writeUTF(entry.getValue()); } } @Override public void readFields(DataInput in) throws IOException { super.readFields(in); final int queriedFieldsLength = in.readInt(); if (queriedFieldsLength != -1) { queriedFields = new HashSet<SchemaId>(queriedFieldsLength); for (int i = 0; i < queriedFieldsLength; i++) { final int l = in.readInt(); final byte[] bytes = new byte[l]; in.readFully(bytes); queriedFields.add(this.serializationUtil.deserializeSchemaId(bytes)); } } final int dependencyRecordVariantPropertiesLength = in.readInt(); dependencyRecordVariantProperties = new HashMap<String, String>(); for (int i = 0; i < dependencyRecordVariantPropertiesLength; i++) { dependencyRecordVariantProperties.put(in.readUTF(), in.readUTF()); } } }