All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.securegraph.accumulo.ElementMaker Maven / Gradle / Ivy

The newest version!
package org.securegraph.accumulo;

import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.iterators.user.RowDeletingIterator;
import org.apache.accumulo.core.security.ColumnVisibility;
import org.apache.hadoop.io.Text;
import org.securegraph.Authorizations;
import org.securegraph.Property;
import org.securegraph.SecureGraphException;
import org.securegraph.Visibility;

import java.util.*;

public abstract class ElementMaker {
    private final Iterator> row;
    private final Map propertyNames = new HashMap<>();
    private final Map propertyColumnQualifier = new HashMap<>();
    private final Map propertyValues = new HashMap<>();
    private final Map propertyVisibilities = new HashMap<>();
    private final Map propertyMetadata = new HashMap<>();
    private final Map propertyTimestamps = new HashMap<>();
    private final Set hiddenProperties = new HashSet<>();
    private final Set hiddenVisibilities = new HashSet<>();
    private final AccumuloGraph graph;
    private final Authorizations authorizations;
    private String id;
    private Visibility visibility;

    public ElementMaker(AccumuloGraph graph, Iterator> row, Authorizations authorizations) {
        this.graph = graph;
        this.row = row;
        this.authorizations = authorizations;
    }

    public T make(boolean includeHidden) {
        while (row.hasNext()) {
            Map.Entry col = row.next();

            if (this.id == null) {
                this.id = getIdFromRowKey(col.getKey().getRow().toString());
            }

            Text columnFamily = col.getKey().getColumnFamily();
            Text columnQualifier = col.getKey().getColumnQualifier();
            ColumnVisibility columnVisibility = AccumuloGraph.visibilityToAccumuloVisibility(col.getKey().getColumnVisibility().toString());
            Value value = col.getValue();

            if (columnFamily.equals(AccumuloGraph.DELETE_ROW_COLUMN_FAMILY)
                    && columnQualifier.equals(AccumuloGraph.DELETE_ROW_COLUMN_QUALIFIER)
                    && value.equals(RowDeletingIterator.DELETE_ROW_VALUE)) {
                return null;
            }

            if (columnFamily.equals(AccumuloElement.CF_HIDDEN)) {
                if (includeHidden) {
                    this.hiddenVisibilities.add(AccumuloGraph.accumuloVisibilityToVisibility(columnVisibility));
                } else {
                    return null;
                }
            }

            if (columnFamily.equals(AccumuloElement.CF_PROPERTY_HIDDEN)) {
                extractPropertyHidden(columnQualifier, columnVisibility);
            }

            if (AccumuloElement.CF_PROPERTY.compareTo(columnFamily) == 0) {
                extractPropertyData(col, columnVisibility);
                continue;
            }

            if (AccumuloElement.CF_PROPERTY_METADATA.compareTo(columnFamily) == 0) {
                extractPropertyMetadata(columnQualifier, columnVisibility, value);
                continue;
            }

            if (getVisibilitySignal().equals(columnFamily.toString())) {
                this.visibility = AccumuloGraph.accumuloVisibilityToVisibility(columnVisibility);
            }

            processColumn(col.getKey(), col.getValue());
        }

        // If the org.securegraph.accumulo.iterator.ElementVisibilityRowFilter isn't installed this will catch stray rows
        if (this.visibility == null) {
            return null;
        }

        return makeElement(includeHidden);
    }

    protected abstract void processColumn(Key key, Value value);

    protected abstract String getIdFromRowKey(String rowKey);

    protected abstract String getVisibilitySignal();

    protected abstract T makeElement(boolean includeHidden);

    protected String getId() {
        return this.id;
    }

    protected Visibility getVisibility() {
        return this.visibility;
    }

    public AccumuloGraph getGraph() {
        return graph;
    }

    protected Set getHiddenVisibilities() {
        return hiddenVisibilities;
    }

    protected List getProperties(boolean includeHidden) {
        List results = new ArrayList<>(propertyValues.size());
        for (Map.Entry propertyValueEntry : propertyValues.entrySet()) {
            String key = propertyValueEntry.getKey();
            String propertyKey = getPropertyKeyFromColumnQualifier(propertyColumnQualifier.get(key));
            String propertyName = propertyNames.get(key);
            byte[] propertyValue = propertyValueEntry.getValue();
            Visibility propertyVisibility = propertyVisibilities.get(key);
            long propertyTimestamp = propertyTimestamps.get(key);
            Set propertyHiddenVisibilities = getPropertyHiddenVisibilities(propertyKey, propertyName, propertyVisibility);
            if (!includeHidden && isHidden(propertyKey, propertyName, propertyVisibility)) {
                continue;
            }
            LazyPropertyMetadata metadata = propertyMetadata.get(key);
            LazyMutableProperty property = new LazyMutableProperty(
                    getGraph(),
                    getGraph().getValueSerializer(),
                    propertyKey,
                    propertyName,
                    propertyValue,
                    metadata,
                    propertyHiddenVisibilities,
                    propertyVisibility,
                    propertyTimestamp
            );
            results.add(property);
        }
        return results;
    }

    private Set getPropertyHiddenVisibilities(String propertyKey, String propertyName, Visibility propertyVisibility) {
        Set hiddenVisibilities = null;
        for (HiddenProperty hiddenProperty : hiddenProperties) {
            if (hiddenProperty.matches(propertyKey, propertyName, propertyVisibility)) {
                if (hiddenVisibilities == null) {
                    hiddenVisibilities = new HashSet<>();
                }
                hiddenVisibilities.add(hiddenProperty.getHiddenVisibility());
            }
        }
        return hiddenVisibilities;
    }

    private boolean isHidden(String propertyKey, String propertyName, Visibility visibility) {
        for (HiddenProperty hiddenProperty : hiddenProperties) {
            if (hiddenProperty.matches(propertyKey, propertyName, visibility)) {
                return true;
            }
        }
        return false;
    }

    private void extractPropertyHidden(Text columnQualifier, ColumnVisibility columnVisibility) {
        String columnQualifierStr = columnQualifier.toString();
        int nameKeySep = columnQualifierStr.indexOf(ElementMutationBuilder.VALUE_SEPARATOR);
        if (nameKeySep < 0) {
            throw new SecureGraphException("Invalid property hidden column qualifier");
        }
        int keyVisSep = columnQualifierStr.indexOf(ElementMutationBuilder.VALUE_SEPARATOR, nameKeySep + 1);
        if (nameKeySep < 0) {
            throw new SecureGraphException("Invalid property hidden column qualifier");
        }

        String name = columnQualifierStr.substring(0, nameKeySep);
        String key = columnQualifierStr.substring(nameKeySep + 1, keyVisSep);
        String vis = columnQualifierStr.substring(keyVisSep + 1);

        this.hiddenProperties.add(new HiddenProperty(key, name, vis, AccumuloGraph.accumuloVisibilityToVisibility(columnVisibility)));
    }

    private void extractPropertyMetadata(Text columnQualifier, ColumnVisibility columnVisibility, Value value) {
        Visibility metadataVisibility = AccumuloGraph.accumuloVisibilityToVisibility(columnVisibility);
        String columnQualifierString = columnQualifier.toString();
        int i = columnQualifierString.lastIndexOf(ElementMutationBuilder.VALUE_SEPARATOR);
        if (i < 0) {
            throw new SecureGraphException("Invalid property metadata column qualifier: " + columnQualifierString);
        }
        String propertyKey = columnQualifierString.substring(0, i);
        String metadataKey = columnQualifierString.substring(i + 1);

        LazyPropertyMetadata lazyPropertyMetadata = getOrCreatePropertyMetadata(propertyKey);
        lazyPropertyMetadata.add(metadataKey, metadataVisibility, value.get());
    }

    private LazyPropertyMetadata getOrCreatePropertyMetadata(String propertyKey) {
        LazyPropertyMetadata lazyPropertyMetadata = propertyMetadata.get(propertyKey);
        if (lazyPropertyMetadata == null) {
            lazyPropertyMetadata = new LazyPropertyMetadata();
            propertyMetadata.put(propertyKey, lazyPropertyMetadata);
        }
        return lazyPropertyMetadata;
    }

    private void extractPropertyData(Map.Entry column, ColumnVisibility columnVisibility) {
        Text columnQualifier = column.getKey().getColumnQualifier();
        Value value = column.getValue();
        Visibility visibility = AccumuloGraph.accumuloVisibilityToVisibility(columnVisibility);
        String propertyName = getPropertyNameFromColumnQualifier(columnQualifier.toString());
        String key = propertyColumnQualifierToKey(columnQualifier, visibility);
        long timestamp = column.getKey().getTimestamp();
        propertyColumnQualifier.put(key, columnQualifier.toString());
        propertyNames.put(key, propertyName);
        propertyValues.put(key, value.get());
        propertyVisibilities.put(key, visibility);
        propertyTimestamps.put(key, timestamp);
    }

    private String propertyColumnQualifierToKey(Text columnQualifier, Visibility visibility) {
        return columnQualifier.toString() + ElementMutationBuilder.VALUE_SEPARATOR + visibility.toString();
    }

    private String getPropertyNameFromColumnQualifier(String columnQualifier) {
        int i = columnQualifier.indexOf(ElementMutationBuilder.VALUE_SEPARATOR);
        if (i < 0) {
            throw new SecureGraphException("Invalid property column qualifier");
        }
        return columnQualifier.substring(0, i);
    }

    private String getPropertyKeyFromColumnQualifier(String columnQualifier) {
        int i = columnQualifier.indexOf(ElementMutationBuilder.VALUE_SEPARATOR);
        if (i < 0) {
            throw new SecureGraphException("Invalid property column qualifier");
        }
        return columnQualifier.substring(i + 1);
    }

    public Authorizations getAuthorizations() {
        return authorizations;
    }

    private static class HiddenProperty {
        private final String key;
        private final String name;
        private final String visibility;
        private final Visibility hiddenVisibility;

        public HiddenProperty(String key, String name, String visibility, Visibility hiddenVisibility) {
            this.key = key;
            this.name = name;
            this.visibility = visibility;
            this.hiddenVisibility = hiddenVisibility;
        }

        public boolean matches(String propertyKey, String propertyName, Visibility visibility) {
            return propertyKey.equals(this.key)
                    && propertyName.equals(this.name)
                    && visibility.getVisibilityString().equals(this.visibility);
        }

        public Visibility getHiddenVisibility() {
            return hiddenVisibility;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }

            HiddenProperty that = (HiddenProperty) o;

            if (key != null ? !key.equals(that.key) : that.key != null) {
                return false;
            }
            if (name != null ? !name.equals(that.name) : that.name != null) {
                return false;
            }
            if (visibility != null ? !visibility.equals(that.visibility) : that.visibility != null) {
                return false;
            }

            return true;
        }

        @Override
        public int hashCode() {
            int result = key != null ? key.hashCode() : 0;
            result = 31 * result + (name != null ? name.hashCode() : 0);
            result = 31 * result + (visibility != null ? visibility.hashCode() : 0);
            return result;
        }

        @Override
        public String toString() {
            return "HiddenProperty{" +
                    "key='" + key + '\'' +
                    ", name='" + name + '\'' +
                    ", visibility='" + visibility + '\'' +
                    '}';
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy