// Path: src/main/java/com/netflix/nfgraph/util/OrdinalMap.java
// public class OrdinalMap<T> implements Iterable<T> {
// 
//     private int hashedOrdinalArray[];
//     private T objectsByOrdinal[];
//     
//     private int size;
//     
//     public OrdinalMap() {
//         this(10);
//     }
//     
//     @SuppressWarnings("unchecked")
//     public OrdinalMap(int expectedSize) {
//         int mapArraySize = 1 << (32 - Integer.numberOfLeadingZeros(expectedSize * 4 / 3));
//         int ordinalArraySize = mapArraySize * 3 / 4;
//         
//         hashedOrdinalArray = newHashedOrdinalArray(mapArraySize);
//         objectsByOrdinal = (T[]) new Object[ordinalArraySize];
//     }
//     
//     /**
//      * Add an object into this <code>OrdinalMap</code>.  If the same object (or an {@link Object#equals(Object)} object) is
//      * already in the map, then no changes will be made.
//      * 
//      * @return the ordinal of <code>obj</code>
//      */
//     public int add(T obj) {
//         int ordinal = get(obj);
//         if(ordinal != -1)
//             return ordinal;
//         
//         if(size == objectsByOrdinal.length)
//             growCapacity();
//         
//         objectsByOrdinal[size] = obj;
//         hashOrdinalIntoArray(size, hashedOrdinalArray);
//         
//         return size++;
//     }
//     
//     /**
//      * @return the ordinal of an object previously added to the map.  If the object has not been added to the map, returns -1 instead. 
//      */
//     public int get(T obj) {
//         int hash = Mixer.hashInt(obj.hashCode());
//         
//         int bucket = hash % hashedOrdinalArray.length;
//         int ordinal = hashedOrdinalArray[bucket];
//         
//         while(ordinal != -1) {
//             if(objectsByOrdinal[ordinal].equals(obj))
//                 return ordinal;
//             
//             bucket = (bucket + 1) % hashedOrdinalArray.length;
//             ordinal = hashedOrdinalArray[bucket];
//         }
//         
//         return -1;
//     }
//     
//     /**
//      * @return the object for a given ordinal.  If the ordinal does not yet exist, returns null.
//      */
//     public T get(int ordinal) {
//         if(ordinal >= size)
//             return null;
//         return objectsByOrdinal[ordinal];
//     }
//     
//     /**
//      * @return the number of objects in this map.
//      */
//     public int size() {
//         return size;
//     }
//     
//     private void growCapacity() {
//         int newHashedOrdinalArray[] = newHashedOrdinalArray(hashedOrdinalArray.length * 2);
//         
//         for(int i=0;i<objectsByOrdinal.length;i++) {
//             hashOrdinalIntoArray(i, newHashedOrdinalArray);
//         }
//         
//         objectsByOrdinal = Arrays.copyOf(objectsByOrdinal, objectsByOrdinal.length * 2);
//         hashedOrdinalArray = newHashedOrdinalArray;
//     }
//     
//     private void hashOrdinalIntoArray(int ordinal, int hashedOrdinalArray[]) {
//         int hash = Mixer.hashInt(objectsByOrdinal[ordinal].hashCode());
//         
//         int bucket = hash % hashedOrdinalArray.length;
//         
//         while(hashedOrdinalArray[bucket] != -1) {
//             bucket = (bucket + 1) % hashedOrdinalArray.length;
//         }
//         
//         hashedOrdinalArray[bucket] = ordinal;
//     }
//     
//     private int[] newHashedOrdinalArray(int length) {
//         int arr[] = new int[length];
//         Arrays.fill(arr, -1);
//         return arr;
//     }
// 
//     /**
//      * @return an {@link Iterator} over the objects in this mapping.
//      */
//     @Override
//     public Iterator<T> iterator() {
//         return new ArrayIterator<T>(objectsByOrdinal, size);
//     }
//     
// }


import java.util.Iterator;
import com.netflix.nfgraph.util.OrdinalMap;
/*
 *  Copyright 2013 Netflix, Inc.
 *
 *     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 com.netflix.nfgraph;



/**
 * <code>NFGraphModelHolder</code> maintains an ordering over the models in a given NFGraph.<p>
 * 
 * An {@link NFGraph} may contain one or more "connection models".  A "connection model" is a grouping of the set of connections
 * between nodes in the graph.<p>
 * 
 * Connections added for a connection model will be visible only for that model.  Use of multiple connection models will 
 * add a minimum of one byte per model-specific connection set per node.  As a result, this feature should be used only 
 * when the number of connection models is and will remain low.<p>
 * 
 * It is unlikely that this class will need to be used externally.
 */
public class NFGraphModelHolder implements Iterable<String> {

    public static final String CONNECTION_MODEL_GLOBAL = "global";

// Path: src/main/java/com/netflix/nfgraph/util/OrdinalMap.java
// public class OrdinalMap<T> implements Iterable<T> {
// 
//     private int hashedOrdinalArray[];
//     private T objectsByOrdinal[];
//     
//     private int size;
//     
//     public OrdinalMap() {
//         this(10);
//     }
//     
//     @SuppressWarnings("unchecked")
//     public OrdinalMap(int expectedSize) {
//         int mapArraySize = 1 << (32 - Integer.numberOfLeadingZeros(expectedSize * 4 / 3));
//         int ordinalArraySize = mapArraySize * 3 / 4;
//         
//         hashedOrdinalArray = newHashedOrdinalArray(mapArraySize);
//         objectsByOrdinal = (T[]) new Object[ordinalArraySize];
//     }
//     
//     /**
//      * Add an object into this <code>OrdinalMap</code>.  If the same object (or an {@link Object#equals(Object)} object) is
//      * already in the map, then no changes will be made.
//      * 
//      * @return the ordinal of <code>obj</code>
//      */
//     public int add(T obj) {
//         int ordinal = get(obj);
//         if(ordinal != -1)
//             return ordinal;
//         
//         if(size == objectsByOrdinal.length)
//             growCapacity();
//         
//         objectsByOrdinal[size] = obj;
//         hashOrdinalIntoArray(size, hashedOrdinalArray);
//         
//         return size++;
//     }
//     
//     /**
//      * @return the ordinal of an object previously added to the map.  If the object has not been added to the map, returns -1 instead. 
//      */
//     public int get(T obj) {
//         int hash = Mixer.hashInt(obj.hashCode());
//         
//         int bucket = hash % hashedOrdinalArray.length;
//         int ordinal = hashedOrdinalArray[bucket];
//         
//         while(ordinal != -1) {
//             if(objectsByOrdinal[ordinal].equals(obj))
//                 return ordinal;
//             
//             bucket = (bucket + 1) % hashedOrdinalArray.length;
//             ordinal = hashedOrdinalArray[bucket];
//         }
//         
//         return -1;
//     }
//     
//     /**
//      * @return the object for a given ordinal.  If the ordinal does not yet exist, returns null.
//      */
//     public T get(int ordinal) {
//         if(ordinal >= size)
//             return null;
//         return objectsByOrdinal[ordinal];
//     }
//     
//     /**
//      * @return the number of objects in this map.
//      */
//     public int size() {
//         return size;
//     }
//     
//     private void growCapacity() {
//         int newHashedOrdinalArray[] = newHashedOrdinalArray(hashedOrdinalArray.length * 2);
//         
//         for(int i=0;i<objectsByOrdinal.length;i++) {
//             hashOrdinalIntoArray(i, newHashedOrdinalArray);
//         }
//         
//         objectsByOrdinal = Arrays.copyOf(objectsByOrdinal, objectsByOrdinal.length * 2);
//         hashedOrdinalArray = newHashedOrdinalArray;
//     }
//     
//     private void hashOrdinalIntoArray(int ordinal, int hashedOrdinalArray[]) {
//         int hash = Mixer.hashInt(objectsByOrdinal[ordinal].hashCode());
//         
//         int bucket = hash % hashedOrdinalArray.length;
//         
//         while(hashedOrdinalArray[bucket] != -1) {
//             bucket = (bucket + 1) % hashedOrdinalArray.length;
//         }
//         
//         hashedOrdinalArray[bucket] = ordinal;
//     }
//     
//     private int[] newHashedOrdinalArray(int length) {
//         int arr[] = new int[length];
//         Arrays.fill(arr, -1);
//         return arr;
//     }
// 
//     /**
//      * @return an {@link Iterator} over the objects in this mapping.
//      */
//     @Override
//     public Iterator<T> iterator() {
//         return new ArrayIterator<T>(objectsByOrdinal, size);
//     }
//     
// }


// Path: src/main/java/com/netflix/nfgraph/NFGraphModelHolder.java
import java.util.Iterator;
import com.netflix.nfgraph.util.OrdinalMap;

/*
 *  Copyright 2013 Netflix, Inc.
 *
 *     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 com.netflix.nfgraph;



/**
 * <code>NFGraphModelHolder</code> maintains an ordering over the models in a given NFGraph.<p>
 * 
 * An {@link NFGraph} may contain one or more "connection models".  A "connection model" is a grouping of the set of connections
 * between nodes in the graph.<p>
 * 
 * Connections added for a connection model will be visible only for that model.  Use of multiple connection models will 
 * add a minimum of one byte per model-specific connection set per node.  As a result, this feature should be used only 
 * when the number of connection models is and will remain low.<p>
 * 
 * It is unlikely that this class will need to be used externally.
 */
public class NFGraphModelHolder implements Iterable<String> {

    public static final String CONNECTION_MODEL_GLOBAL = "global";

    private OrdinalMap<String> modelMap;