Example usage for com.google.common.collect HashBiMap create

List of usage examples for com.google.common.collect HashBiMap create

Introduction

In this page you can find the example usage for com.google.common.collect HashBiMap create.

Prototype

public static <K, V> HashBiMap<K, V> create(Map<? extends K, ? extends V> map) 

Source Link

Document

Constructs a new bimap containing initial values from map .

Usage

From source file:org.sonatype.plugin.nexus.testenvironment.AbstractEnvironmentMojo.java

@SuppressWarnings("unchecked")
private void validateStaticPorts() throws MojoExecutionException, MojoFailureException {
    if (this.staticPorts != null) {
        try {// w ww.ja  v a2  s.co m
            @SuppressWarnings("rawtypes")
            BiMap staticPortMap = HashBiMap.create(this.staticPorts.size());
            staticPortMap = MapConstraints.constrainedBiMap(staticPortMap, MapConstraints.notNull());
            staticPortMap.putAll(this.staticPorts);
            this.staticPorts = staticPortMap;
        } catch (NullPointerException npe) {
            throw new MojoExecutionException("Port names and values must not be null.", npe);
        } catch (IllegalArgumentException iae) {
            throw new MojoExecutionException("Port names and values must not be duplicated.", iae);
        }
    }
}

From source file:com.google.dart.engine.services.internal.refactoring.ExtractMethodRefactoringImpl.java

/**
 * Fills {@link #occurrences} field./*from w  w w .  j a  va2 s  . c o m*/
 */
private void initializeOccurrences() {
    // prepare selection
    SourcePattern selectionPattern = getSourcePattern(selectionRange);
    final String selectionSource = getNormalizedSource(selectionPattern.patternSource);
    final Map<String, String> patternToSelectionName = HashBiMap.create(selectionPattern.originalToPatternNames)
            .inverse();
    // prepare context and enclosing parent - class or unit
    ASTNode enclosingMemberParent;
    {
        ASTNode coveringNode = selectionAnalyzer.getCoveringNode();
        ASTNode parentMember = CorrectionUtils.getEnclosingExecutableNode(coveringNode);
        enclosingMemberParent = parentMember.getParent();
    }
    // visit nodes which will able to access extracted method
    enclosingMemberParent.accept(new GeneralizingASTVisitor<Void>() {
        boolean forceStatic = false;

        @Override
        public Void visitBlock(Block node) {
            if (selectionStatements != null) {
                List<Statement> blockStatements = node.getStatements();
                int beginStatementIndex = 0;
                int selectionCount = selectionStatements.size();
                while (beginStatementIndex + selectionCount <= blockStatements.size()) {
                    SourceRange nodeRange = SourceRangeFactory.rangeStartEnd(
                            blockStatements.get(beginStatementIndex),
                            blockStatements.get(beginStatementIndex + selectionCount - 1));
                    boolean found = tryToFindOccurrence(nodeRange);
                    // next statement
                    if (found) {
                        beginStatementIndex += selectionCount;
                    } else {
                        beginStatementIndex++;
                    }
                }
            }
            return super.visitBlock(node);
        }

        @Override
        public Void visitConstructorInitializer(ConstructorInitializer node) {
            forceStatic = true;
            try {
                return super.visitConstructorInitializer(node);
            } finally {
                forceStatic = false;
            }
        }

        @Override
        public Void visitExpression(Expression node) {
            if (selectionExpression != null && node.getClass() == selectionExpression.getClass()) {
                SourceRange nodeRange = SourceRangeFactory.rangeNode(node);
                tryToFindOccurrence(nodeRange);
            }
            return super.visitExpression(node);
        }

        @Override
        public Void visitMethodDeclaration(MethodDeclaration node) {
            forceStatic = node.isStatic();
            try {
                return super.visitMethodDeclaration(node);
            } finally {
                forceStatic = false;
            }
        }

        /**
         * Checks if given {@link SourceRange} matched selection source and adds {@link Occurrence}.
         */
        private boolean tryToFindOccurrence(SourceRange nodeRange) {
            // prepare normalized node source
            SourcePattern nodePattern = getSourcePattern(nodeRange);
            String nodeSource = getNormalizedSource(nodePattern.patternSource);
            // if matches normalized node source, then add as occurrence
            if (nodeSource.equals(selectionSource)) {
                Occurrence occurrence = new Occurrence(nodeRange, selectionRange.intersects(nodeRange));
                occurrences.add(occurrence);
                // prepare mapping of parameter names to the occurrence variables
                for (Entry<String, String> entry : nodePattern.originalToPatternNames.entrySet()) {
                    String patternName = entry.getValue();
                    String originalName = entry.getKey();
                    String selectionName = patternToSelectionName.get(patternName);
                    occurrence.parameterOldToOccurrenceName.put(selectionName, originalName);
                }
                // update static
                if (forceStatic) {
                    staticContext |= true;
                }
                // we have match
                return true;
            }
            // no match
            return false;
        }
    });
}

From source file:org.apache.rya.indexing.external.tupleSet.AccumuloIndexSet.java

/**
 *
 * @param order - prefix of a full variable order
 * @return - full variable order that includes all variables whose values
 * are stored in the table - used to obtain the locality group
 *//*w w w .  j  ava  2s . com*/
//given partial order of query vars, convert to PCJ vars and determine
//if converted partial order is a substring of a full var order of PCJ variables.
//if converted partial order is a prefix, convert corresponding full PCJ var order to query vars
private String prefixToOrder(String order) {
    final Map<String, String> invMap = HashBiMap.create(this.getTableVarMap()).inverse();
    final String[] temp = order.split(VAR_ORDER_DELIM);
    //get order in terms of PCJ variables
    for (int i = 0; i < temp.length; i++) {
        temp[i] = this.getTableVarMap().get(temp[i]);
    }
    order = Joiner.on(VAR_ORDER_DELIM).join(temp);
    for (final String s : varOrder) {
        //verify that partial order is prefix of a PCJ varOrder
        if (s.startsWith(order)) {
            return s;
        }
    }
    throw new NoSuchElementException("Order is not a prefix of any locality group value!");
}

From source file:com.analog.lyric.dimple.model.transform.JunctionTreeTransform.java

/**
 * Build junction tree transformation using a specified variable elimination ordering.
 * <p>//from  w w  w . j  a va2 s .  com
 * @param eliminationOrder is a valid variable ordering for this graph created by {@link VariableEliminator}
 * on this {@code model}.
 * 
 * @see #transform(FactorGraph)
 * @see #transform(FactorGraph, ArrayList)
 */
public JunctionTreeTransformMap transform(FactorGraph model, Ordering eliminationOrder) {
    // 1) Determine an elimination order

    final Stats orderStats = eliminationOrder.stats;

    if (orderStats.alreadyGoodForFastExactInference()) {
        // If elimination order introduces no edges, graph is already a tree. Done.
        return JunctionTreeTransformMap.identity(model);
    }

    if (orderStats.factorsWithDuplicateVariables() > 0) {
        // FIXME - support duplicate variables in JunctionTreeTransform
        throw DimpleException.unsupported("factors with duplicate variables");
    }

    // 2) Make copy of the factor graph

    final ArrayList<Variable> variables = eliminationOrder.variables;
    final int nVariables = variables.size();
    final int nFactors = model.getFactorCount();

    final BiMap<Object, Object> old2new = HashBiMap.create(nVariables * 2);
    final FactorGraph targetModel = model.copyRoot(old2new);
    targetModel.unsetOption(BPOptions.scheduler); // Don't use copied scheduler

    // Make copied factors undirected.
    for (Factor factor : targetModel.getFactors()) {
        factor.setUndirected();
    }

    final JunctionTreeTransformMap transformMap = JunctionTreeTransformMap.create(model, targetModel);

    for (Entry<Object, Object> entry : old2new.entrySet()) {
        final Object source = entry.getKey();
        if (source instanceof Variable) {
            transformMap.addVariableMapping((Variable) source,
                    Objects.requireNonNull((Variable) entry.getValue()));
        }
    }

    // 3) Disconnect conditioned variables from other variables in new graph

    disconnectConditionedVariables(eliminationOrder, transformMap);

    // 4) Create cliques using variable elimination order

    final List<Clique> cliques = createCliques(eliminationOrder, transformMap);
    final SetMultimap<Discrete, Clique> varToCliques = HashMultimap.create(nVariables,
            nVariables / Math.max(1, nFactors));
    for (Clique clique : cliques) {
        clique.addToMap(varToCliques);
    }

    // 5) Use Prim's algorithm to build max spanning tree over clique graph where the edge weight
    //    is the number of variables in common between the two cliques along each edge.

    final List<CliqueEdge> multiVariateEdges = formSpanningTree(transformMap, cliques, varToCliques);

    // 6) Merge factors in cliques

    for (Clique clique : cliques) {
        if (clique._variables.length > 0) {
            clique._mergedFactor = targetModel.join(clique._variables, clique._factors);
        }
    }

    // 7) Rewrite factors with multivariate edges

    for (Clique clique : cliques) {
        clique.joinMultivariateEdges();
        for (Factor cliqueFactor : clique._factors) {
            Factor sourceFactor = (Factor) old2new.inverse().get(cliqueFactor);
            transformMap.addFactorMapping(sourceFactor, Objects.requireNonNull(clique._mergedFactor));
        }
    }

    // 8) Find and reconnect orphaned variables.

    reconnectOrphanVariables(targetModel, multiVariateEdges);

    return transformMap;
}

From source file:com.google.dart.tools.internal.corext.refactoring.code.ExtractMethodRefactoring.java

/**
 * Fills {@link #occurrences} field.//from w ww.  j av  a  2s.co m
 */
private void initializeOccurrences() {
    // prepare selection
    SourcePattern selectionPattern = getSourcePattern(selectionRange);
    final String selectionSource = getNormalizedSource(selectionPattern.patternSource);
    final Map<String, String> patternToSelectionName = HashBiMap.create(selectionPattern.originalToPatternNames)
            .inverse();
    // prepare context and enclosing parent - class or unit
    DartNode enclosingMemberParent;
    {
        DartNode coveringNode = selectionAnalyzer.getLastCoveringNode();
        DartClassMember<?> parentMember = ASTNodes.getAncestor(coveringNode, DartClassMember.class);
        enclosingMemberParent = parentMember.getParent();
    }
    // visit nodes which will able to access extracted method
    enclosingMemberParent.accept(new ASTVisitor<Void>() {
        boolean forceStatic = false;

        @Override
        public Void visitBlock(DartBlock node) {
            if (selectionStatements != null) {
                List<DartStatement> blockStatements = node.getStatements();
                int beginStatementIndex = 0;
                int selectionCount = selectionStatements.size();
                while (beginStatementIndex + selectionCount <= blockStatements.size()) {
                    SourceRange nodeRange = SourceRangeFactory.forStartEnd(
                            blockStatements.get(beginStatementIndex),
                            blockStatements.get(beginStatementIndex + selectionCount - 1));
                    boolean found = tryToFindOccurrence(nodeRange);
                    // next statement
                    if (found) {
                        beginStatementIndex += selectionCount;
                    } else {
                        beginStatementIndex++;
                    }
                }
            }
            return super.visitBlock(node);
        }

        @Override
        public Void visitExpression(DartExpression node) {
            if (selectionExpression != null && node.getClass() == selectionExpression.getClass()) {
                SourceRange nodeRange = SourceRangeFactory.create(node);
                tryToFindOccurrence(nodeRange);
            }
            return super.visitExpression(node);
        }

        @Override
        public Void visitInitializer(DartInitializer node) {
            forceStatic = true;
            try {
                return super.visitInitializer(node);
            } finally {
                forceStatic = false;
            }
        }

        @Override
        public Void visitMethodDefinition(DartMethodDefinition node) {
            forceStatic = node.getModifiers().isStatic();
            try {
                return super.visitMethodDefinition(node);
            } finally {
                forceStatic = false;
            }
        }

        /**
         * Checks if given {@link SourceRange} matched selection source and adds {@link Occurrence}.
         */
        private boolean tryToFindOccurrence(SourceRange nodeRange) {
            // prepare normalized node source
            SourcePattern nodePattern = getSourcePattern(nodeRange);
            String nodeSource = getNormalizedSource(nodePattern.patternSource);
            // if matches normalized node source, then add as occurrence
            if (nodeSource.equals(selectionSource)) {
                Occurrence occurrence = new Occurrence(nodeRange,
                        SourceRangeUtils.intersects(selectionRange, nodeRange));
                occurrences.add(occurrence);
                // prepare mapping of parameter names to the occurrence variables
                for (Entry<String, String> entry : nodePattern.originalToPatternNames.entrySet()) {
                    String patternName = entry.getValue();
                    String originalName = entry.getKey();
                    String selectionName = patternToSelectionName.get(patternName);
                    occurrence.parameterOldToOccurrenceName.put(selectionName, originalName);
                }
                // update static
                if (forceStatic) {
                    staticContext |= true;
                }
                // we have match
                return true;
            }
            // no match
            return false;
        }
    });
}

From source file:org.artifactory.storage.db.build.service.BuildStoreServiceImpl.java

/**
 * Locates and fills in missing checksums of a build file bean
 *
 * @param buildFiles List of build files to populate
 *///  www .j  a v a2s .c o m
private void handleBeanPopulation(List<? extends BuildFileBean> buildFiles) {
    if (buildFiles != null && !buildFiles.isEmpty()) {
        Set<String> checksums = Sets.newHashSet();
        for (BuildFileBean buildFile : buildFiles) {
            boolean sha1Exists = StringUtils.isNotBlank(buildFile.getSha1());
            boolean md5Exists = StringUtils.isNotBlank(buildFile.getMd5());

            //If the bean has both or none of the checksums, return
            if ((sha1Exists && md5Exists) || ((!sha1Exists && !md5Exists))) {
                continue;
            }

            if (!sha1Exists) {
                checksums.add(buildFile.getMd5());
            } else {
                checksums.add(buildFile.getSha1());
            }
        }
        Set<BinaryInfo> binaryInfos = binaryStore.findBinaries(checksums);
        BiMap<String, String> found = HashBiMap.create(binaryInfos.size());
        for (BinaryInfo binaryInfo : binaryInfos) {
            found.put(binaryInfo.getSha1(), binaryInfo.getMd5());
        }
        for (BuildFileBean buildFile : buildFiles) {
            boolean sha1Exists = StringUtils.isNotBlank(buildFile.getSha1());
            boolean md5Exists = StringUtils.isNotBlank(buildFile.getMd5());

            //If the bean has both or none of the checksums, return
            if ((sha1Exists && md5Exists) || ((!sha1Exists && !md5Exists))) {
                continue;
            }

            if (!sha1Exists) {
                String newSha1 = found.inverse().get(buildFile.getMd5());
                if (ChecksumType.sha1.isValid(newSha1)) {
                    buildFile.setSha1(newSha1);
                }
            } else {
                String newMd5 = found.get(buildFile.getSha1());
                if (ChecksumType.md5.isValid(newMd5)) {
                    buildFile.setMd5(newMd5);
                }
            }
        }
    }
}

From source file:org.sosy_lab.cpachecker.cpa.octagon.OctagonState.java

public OctagonState intersect(OctagonState other) {
    return new OctagonState(octagonManager.intersection(octagon, other.octagon),
            HashBiMap.create(variableToIndexMap), new HashMap<>(variableToTypeMap), logger);
}

From source file:org.sosy_lab.cpachecker.cpa.octagon.OctagonState.java

private OctagonState removeVars(String varPrefix) {
    List<MemoryLocation> keysToRemove = new ArrayList<>();
    for (MemoryLocation var : variableToIndexMap.keySet()) {
        if (var.getAsSimpleString().startsWith(varPrefix)) {
            keysToRemove.add(var);
        }//from   w  ww  .j a  v  a 2  s  .com
    }

    if (keysToRemove.size() == 0) {
        return this;
    }

    OctagonState newState = new OctagonState(octagonManager.removeDimension(octagon, keysToRemove.size()),
            HashBiMap.create(variableToIndexMap), new HashMap<>(variableToTypeMap), logger);
    newState.variableToIndexMap.keySet().removeAll(keysToRemove);
    newState.variableToTypeMap.keySet().removeAll(keysToRemove);

    for (int i = 0; i < newState.variableToIndexMap.size(); i++) {
        if (newState.variableToIndexMap.inverse().get(i) == null) {
            assert false;
        }
    }
    assert octagonManager.dimension(newState.octagon) == newState.sizeOfVariables();
    return newState;
}

From source file:com.haulmont.yarg.formatters.impl.XlsxFormatter.java

/**
 * XLSX document does not store empty cells and it might be an issue for formula calculations and etc.
 * So we need to create fake template cell for each empty cell.
 *///from   w ww .  j  a  v a 2  s .  com
protected void createFakeTemplateCellsForEmptyOnes(Range oneRowRange,
        Map<CellReference, Cell> cellsForOneRowRange, List<Cell> templateCells) {
    if (oneRowRange.toCellReferences().size() != templateCells.size()) {
        final HashBiMap<CellReference, Cell> referencesToCells = HashBiMap.create(cellsForOneRowRange);

        for (CellReference cellReference : oneRowRange.toCellReferences()) {
            if (!cellsForOneRowRange.containsKey(cellReference)) {
                Cell newCell = Context.getsmlObjectFactory().createCell();
                newCell.setV(null);
                newCell.setT(STCellType.STR);
                newCell.setR(cellReference.toReference());
                templateCells.add(newCell);
                referencesToCells.put(cellReference, newCell);
            }
        }

        Collections.sort(templateCells, new Comparator<Cell>() {
            @Override
            public int compare(Cell o1, Cell o2) {
                CellReference cellReference1 = referencesToCells.inverse().get(o1);
                CellReference cellReference2 = referencesToCells.inverse().get(o2);
                return cellReference1.compareTo(cellReference2);
            }
        });
    }
}

From source file:org.kiji.schema.layout.KijiTableLayout.java

/**
 * Constructs a KijiTableLayout from an Avro descriptor and an optional reference layout.
 *
 * @param desc Avro layout descriptor (relative to the reference layout).
 * @param reference Optional reference layout, or null.
 * @throws InvalidLayoutException if the descriptor is invalid or inconsistent wrt reference.
 *///  ww  w  .  j ava2  s  .  c  o  m
private KijiTableLayout(TableLayoutDesc desc, KijiTableLayout reference) throws InvalidLayoutException {
    // Deep-copy the descriptor to prevent mutating a parameter:
    mDesc = TableLayoutDesc.newBuilder(Preconditions.checkNotNull(desc)).build();

    // Ensure the array of locality groups is mutable:
    mDesc.setLocalityGroups(Lists.newArrayList(mDesc.getLocalityGroups()));

    // Check that the version specified in the layout matches the features used.
    // Any compatibility checks belong in this section.
    mLayoutVersion = computeLayoutVersion(mDesc.getVersion());

    if (!Objects.equal(LAYOUT_PROTOCOL_NAME, mLayoutVersion.getProtocolName())) {
        final String exceptionMessage;
        if (Objects.equal(Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName(),
                mLayoutVersion.getProtocolName())) {
            // Warn the user if they tried a version number like 'kiji-0.9' or 'kiji-1.1'.
            exceptionMessage = String.format(
                    "Deprecated layout version protocol '%s' only valid for version '%s',"
                            + " but received version '%s'. You should specify a layout version protocol"
                            + " as '%s-x.y', not '%s-x.y'.",
                    Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName(),
                    Versions.LAYOUT_KIJI_1_0_0_DEPRECATED, mLayoutVersion, LAYOUT_PROTOCOL_NAME,
                    Versions.LAYOUT_KIJI_1_0_0_DEPRECATED.getProtocolName());
        } else {
            exceptionMessage = String.format("Invalid version protocol: '%s'. Expected '%s'.",
                    mLayoutVersion.getProtocolName(), LAYOUT_PROTOCOL_NAME);
        }
        throw new InvalidLayoutException(exceptionMessage);
    }

    if (Versions.MAX_LAYOUT_VERSION.compareTo(mLayoutVersion) < 0) {
        throw new InvalidLayoutException("The maximum layout version we support is "
                + Versions.MAX_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion);
    } else if (Versions.MIN_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) {
        throw new InvalidLayoutException("The minimum layout version we support is "
                + Versions.MIN_LAYOUT_VERSION + "; this layout requires " + mLayoutVersion);
    }

    // max_filesize and memstore_flushsize were introduced in version 1.2.
    if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) {
        if (mDesc.getMaxFilesize() != null) {
            // Cannot use max_filesize if this is the case.
            throw new InvalidLayoutException("Support for specifying max_filesize begins with layout version "
                    + Versions.BLOCK_SIZE_LAYOUT_VERSION.toString());
        }

        if (mDesc.getMemstoreFlushsize() != null) {
            // Cannot use memstore_flushsize if this is the case.
            throw new InvalidLayoutException(
                    "Support for specifying memstore_flushsize begins with layout version "
                            + Versions.BLOCK_SIZE_LAYOUT_VERSION);
        }
    } else {
        if (mDesc.getMaxFilesize() != null && mDesc.getMaxFilesize() <= 0) {
            throw new InvalidLayoutException("max_filesize must be greater than 0");
        }

        if (mDesc.getMemstoreFlushsize() != null && mDesc.getMemstoreFlushsize() <= 0) {
            throw new InvalidLayoutException("memstore_flushsize must be greater than 0");
        }
    }

    // Ability to configure column name translation was introduced in version 1.5
    if (Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION.compareTo(mLayoutVersion) > 0) {
        if (mDesc.getColumnNameTranslator() != ColumnNameTranslator.SHORT) {
            throw new InvalidLayoutException(
                    "Support for specifiying non-short column name translators begins with layout version "
                            + Versions.CONFIGURE_COLUMN_NAME_TRANSLATION_VERSION);
        }
    }

    // Composite keys and RowKeyFormat2 was introduced in version 1.1.
    if (Versions.RKF2_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0
            && mDesc.getKeysFormat() instanceof RowKeyFormat2) {
        // Cannot use RowKeyFormat2 if this is the case.
        throw new InvalidLayoutException(
                "Support for specifying keys_format as a RowKeyFormat2 begins with layout version "
                        + Versions.RKF2_LAYOUT_VERSION);
    }

    if (!isValidName(getName())) {
        throw new InvalidLayoutException(String.format("Invalid table name: '%s'.", getName()));
    }

    if (reference != null) {
        if (!getName().equals(reference.getName())) {
            throw new InvalidLayoutException(String.format(
                    "Invalid layout update: layout name '%s' does not match reference layout name '%s'.",
                    getName(), reference.getName()));
        }

        if (!mDesc.getKeysFormat().equals(reference.getDesc().getKeysFormat())) {
            throw new InvalidLayoutException(String.format(
                    "Invalid layout update from reference row keys format '%s' to row keys format '%s'.",
                    reference.getDesc().getKeysFormat(), mDesc.getKeysFormat()));
        }
    }

    // Layout ID:
    if (mDesc.getLayoutId() == null) {
        try {
            final long refLayoutId = (reference == null) ? 0
                    : Long.parseLong(reference.getDesc().getLayoutId());
            final long layoutId = refLayoutId + 1;
            mDesc.setLayoutId(Long.toString(layoutId));
        } catch (NumberFormatException nfe) {
            throw new InvalidLayoutException(
                    String.format("Reference layout for table '%s' has an invalid layout ID: '%s'", getName(),
                            reference.getDesc().getLayoutId()));
        }
    }

    if (mDesc.getKeysFormat() instanceof RowKeyFormat) {
        isValidRowKeyFormat1((RowKeyFormat) mDesc.getKeysFormat());
    } else if (mDesc.getKeysFormat() instanceof RowKeyFormat2) {
        // Check validity of row key format.
        isValidRowKeyFormat2((RowKeyFormat2) mDesc.getKeysFormat());
    }

    // Build localities:

    /**
     * Reference map from locality group name to locality group ID.
     * Entries are removed as we process locality group descriptors in the new layout.
     * At the end of the process, this map must be empty.
     */
    final BiMap<String, ColumnId> refLGIdMap = (reference == null) ? HashBiMap.<String, ColumnId>create()
            : HashBiMap.create(reference.mLocalityGroupIdNameMap.inverse());

    /** Map of locality groups in the new layout. */
    final List<LocalityGroupLayout> localityGroups = Lists.newArrayList();
    final Map<String, LocalityGroupLayout> lgMap = Maps.newHashMap();
    final BiMap<ColumnId, String> idMap = HashBiMap.create();

    /** Locality group with no ID assigned yet. */
    final List<LocalityGroupLayout> unassigned = Lists.newArrayList();

    /** All the families in the table. */
    final List<FamilyLayout> families = Lists.newArrayList();

    /** Map from family name or alias to family layout. */
    final Map<String, FamilyLayout> familyMap = Maps.newHashMap();

    /** All primary column names (including map-type families). */
    final Set<KijiColumnName> columnNames = Sets.newTreeSet();

    final Map<KijiColumnName, ColumnLayout> columnMap = Maps.newHashMap();

    final Iterator<LocalityGroupDesc> itLGDesc = mDesc.getLocalityGroups().iterator();
    while (itLGDesc.hasNext()) {
        final LocalityGroupDesc lgDesc = itLGDesc.next();
        final boolean isRename = (lgDesc.getRenamedFrom() != null);
        final String refLGName = isRename ? lgDesc.getRenamedFrom() : lgDesc.getName();
        lgDesc.setRenamedFrom(null);
        if (isRename && (reference == null)) {
            throw new InvalidLayoutException(String
                    .format("Invalid rename: no reference table layout for locality group '%s'.", refLGName));
        }
        final LocalityGroupLayout refLGLayout = (reference != null) ? reference.mLocalityGroupMap.get(refLGName)
                : null;
        if (isRename && (refLGLayout == null)) {
            throw new InvalidLayoutException(
                    String.format("Invalid rename: cannot find reference locality group '%s'.", refLGName));
        }

        final ColumnId refLGId = refLGIdMap.remove(refLGName);

        if (lgDesc.getDelete()) {
            // This locality group is deleted:
            if (refLGId == null) {
                throw new InvalidLayoutException(String.format(
                        "Attempting to delete locality group '%s' unknown in reference layout.", refLGName));
            }
            itLGDesc.remove();
            continue;
        }

        // BloomType, block_size were introduced in version 1.2.
        if (Versions.BLOCK_SIZE_LAYOUT_VERSION.compareTo(mLayoutVersion) > 0) {
            if (lgDesc.getBlockSize() != null) {
                // Cannot use max_filesize if this is the case.
                throw new InvalidLayoutException("Support for specifying block_size begins with layout version "
                        + Versions.BLOCK_SIZE_LAYOUT_VERSION);
            }
            if (lgDesc.getBloomType() != null) {
                // Cannot use bloom_type if this is the case.
                throw new InvalidLayoutException("Support for specifying bloom_type begins with layout version "
                        + Versions.BLOCK_SIZE_LAYOUT_VERSION);
            }
        } else {
            if (lgDesc.getBlockSize() != null && lgDesc.getBlockSize() <= 0) {
                throw new InvalidLayoutException("block_size must be greater than 0");
            }
        }

        final LocalityGroupLayout lgLayout = new LocalityGroupLayout(lgDesc, refLGLayout);
        localityGroups.add(lgLayout);
        for (String lgName : lgLayout.getNames()) {
            Preconditions.checkState(lgMap.put(lgName, lgLayout) == null,
                    "Duplicate locality group name: " + lgName);
        }

        if (lgLayout.getId() != null) {
            final String previous = idMap.put(lgLayout.getId(), lgLayout.getName());
            Preconditions.checkState(previous == null,
                    String.format("Duplicate locality group ID '%s' associated to '%s' and '%s'.",
                            lgLayout.getId(), lgLayout.getName(), previous));
        } else {
            unassigned.add(lgLayout);
        }

        families.addAll(lgLayout.getFamilies());
        for (FamilyLayout familyLayout : lgLayout.getFamilies()) {
            for (String familyName : familyLayout.getNames()) {
                if (null != familyMap.put(familyName, familyLayout)) {
                    throw new InvalidLayoutException(
                            String.format("Layout for table '%s' contains duplicate family name '%s'.",
                                    getName(), familyName));
                }
            }

            if (familyLayout.isMapType()) {
                Preconditions.checkState(columnNames.add(KijiColumnName.create(familyLayout.getName(), null)));
            }

            for (ColumnLayout columnLayout : familyLayout.getColumns()) {
                for (String columnName : columnLayout.getNames()) {
                    final KijiColumnName column = KijiColumnName.create(familyLayout.getName(), columnName);
                    if (null != columnMap.put(column, columnLayout)) {
                        throw new InvalidLayoutException(String.format(
                                "Layout for table '%s' contains duplicate column '%s'.", getName(), column));
                    }
                }
                Preconditions.checkState(
                        columnNames.add(KijiColumnName.create(familyLayout.getName(), columnLayout.getName())));
            }
        }
    }

    if (!refLGIdMap.isEmpty()) {
        throw new InvalidLayoutException(String.format("Missing descriptor(s) for locality group(s): %s.",
                Joiner.on(",").join(refLGIdMap.keySet())));
    }

    mLocalityGroups = ImmutableList.copyOf(localityGroups);
    mLocalityGroupMap = ImmutableMap.copyOf(lgMap);

    mFamilies = ImmutableList.copyOf(families);
    mFamilyMap = ImmutableMap.copyOf(familyMap);

    mColumnNames = ImmutableSet.copyOf(columnNames);

    // Assign IDs to locality groups:
    int nextColumnId = 1;
    for (LocalityGroupLayout localityGroup : unassigned) {
        Preconditions.checkState(localityGroup.getId() == null);
        while (true) {
            final ColumnId columnId = new ColumnId(nextColumnId);
            nextColumnId += 1;
            if (!idMap.containsKey(columnId)) {
                localityGroup.setId(columnId);
                idMap.put(columnId, localityGroup.getName());
                break;
            }
        }
    }

    mLocalityGroupIdNameMap = ImmutableBiMap.copyOf(idMap);
}