/* * This file is part of the HyperGraphDB source distribution. This is copyrighted * software. For permitted uses, licensing options and redistribution, please see * the LicensingInformation file at the root level of the distribution. * * Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved. */ package org.hypergraphdb.indexing; import java.util.Comparator; import org.hypergraphdb.HGException; import org.hypergraphdb.HGHandle; import org.hypergraphdb.HyperGraph; import org.hypergraphdb.HGQuery.hg; import org.hypergraphdb.atom.AtomProjection; import org.hypergraphdb.atom.HGAtomRef; import org.hypergraphdb.storage.ByteArrayConverter; import org.hypergraphdb.type.AtomRefType; import org.hypergraphdb.type.HGAtomType; import org.hypergraphdb.type.HGCompositeType; import org.hypergraphdb.type.HGPrimitiveType; import org.hypergraphdb.type.HGProjection; import org.hypergraphdb.util.HGUtils; /** * * <p> * Represents by the value of a part in a composite type. * </p> * * @author Borislav Iordanov * */ public class ByPartIndexer<KeyType> extends HGKeyIndexer<KeyType> { private String [] dimensionPath; private HGProjection [] projections = null; private HGAtomType projectionType = null; private synchronized HGProjection [] getProjections(HyperGraph graph) { if (projections == null) { HGAtomType type = graph.getTypeSystem().getType(getType()); if (type == null) throw new HGException("Could not find type with handle " + getType()); projections = new HGProjection[dimensionPath.length]; for (int j = 0; j < dimensionPath.length; j++) { if (! (type instanceof HGCompositeType)) return null; projections[j] = ((HGCompositeType)type).getProjection(dimensionPath[j]); if (projections[j] == null) throw new HGException("There's no projection '" + dimensionPath[j] + "' in type '" + type + "'"); type = (HGAtomType)graph.get(projections[j].getType()); } HGProjection ours = projections[dimensionPath.length - 1]; HGHandle enclosingType = dimensionPath.length > 1 ? projections[dimensionPath.length - 2].getType() : getType(); // For HGAtomRef's, we want to index by the atom directly: HGHandle atomProj = hg.findOne(graph, hg.and(hg.type(AtomProjection.class), hg.incident(enclosingType), hg.incident(ours.getType()), hg.eq("name", ours.getName()))); if (atomProj != null) projectionType = graph.getTypeSystem().getAtomType(HGAtomRef.class); else projectionType = graph.get(ours.getType()); } return projections; } public ByPartIndexer() { } /** * <p> * Convenience constructor that allows passing a dot separated dimension path * that is converted to a <code>String[]</code>. * </p> * * @param type The type of the atoms to be indexed. * @param dimensionPath The dimension path in dot format (e.g. "person.address.street") */ public ByPartIndexer(HGHandle type, String dimensionPath) { this(type, dimensionPath.split("\\.")); } /** * <p> * Convenience constructor that allows passing a dot separated dimension path * that is converted to a <code>String[]</code>. * </p> * * @param name The name of the index. * @param type The type of the atoms to be indexed. * @param dimensionPath The dimension path in dot format (e.g. "person.address.street") */ public ByPartIndexer(String name, HGHandle type, String dimensionPath) { this(name, type, dimensionPath.split("\\.")); } public ByPartIndexer(HGHandle type, String [] dimensionPath) { super(type); this.dimensionPath = dimensionPath; } public ByPartIndexer(String name, HGHandle type, String [] dimensionPath) { super(name, type); this.dimensionPath = dimensionPath; } public String[] getDimensionPath() { return dimensionPath; } public void setDimensionPath(String[] dimensionPath) { this.dimensionPath = dimensionPath; } @SuppressWarnings("unchecked") public Comparator<byte[]> getComparator(HyperGraph graph) { // return null; //is this Ok??? if (projectionType == null) getProjections(graph); if (projectionType.getClass().equals(AtomRefType.class)) return null; else if (projectionType instanceof HGPrimitiveType) return ((HGPrimitiveType<?>)projectionType).getComparator(); else if (projectionType instanceof Comparator) return (Comparator<byte[]>)projectionType; else return null; } @SuppressWarnings("unchecked") public ByteArrayConverter<KeyType> getConverter(HyperGraph graph) { if (projectionType == null) getProjections(graph); return (ByteArrayConverter<KeyType>)projectionType; } @SuppressWarnings("unchecked") public KeyType getKey(HyperGraph graph, Object atom) { Object result = atom; for (HGProjection p : getProjections(graph)) result = p.project(result); return (KeyType)result; } @SuppressWarnings("unchecked") public boolean equals(Object other) { if (other == this) return true; if (! (other instanceof ByPartIndexer)) return false; ByPartIndexer<KeyType> idx = (ByPartIndexer<KeyType>)other; return getType().equals(idx.getType()) && HGUtils.eq(dimensionPath, idx.dimensionPath); } public int hashCode() { int hash = 7; hash = 31 * hash + HGUtils.hashIt(dimensionPath); hash = 31 * hash + getType().hashCode(); return hash; } }