// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/EncodingProvider.java
// public interface EncodingProvider {
// 
//     /**
//      * Return a raw byte encoding of the given time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public byte[] encodeAsBytes(long time, int sequence);
// 
//     /**
//      * Return a Long encoding of the given the time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public long encodeAsLong(long time, int sequence);
// 
//     /**
//      * Return a String encoding of the given the time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public String encodeAsString(long time, int sequence);
// 
//     /**
//      * Return the maximum number of sequence numbers that can be encoded for a
//      * given time by this implementation.
//      */
//     public int maxSequenceNumbers();
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/Id.java
// public interface Id {
// 
//     /**
//      * Return a unique identifier as a long.
//      */
//     public long asLong();
// 
//     /**
//      * Return a unique identifier as bytes.
//      */
//     public byte[] asBytes();
// 
//     /**
//      * Return a unique identifier as a String.
//      */
//     public String asString();
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/IdGenerator.java
// public interface IdGenerator {
// 
//     /**
//      * Return a unique identifier. This should be resilient enough to handle
//      * leap seconds, however, backwards time that occurs when the system time is
//      * updated, as from NTP, will result in an {@link InterruptedException}.
//      *
//      * NOTE: Generating more id's at a time than can be handled may result in
//      * the current thread blocking for maxWait ms to ensure a new timestamp is
//      * available.
//      *
//      * @param maxWait
//      *          the maximum amount of time to wait in ms before giving up
//      * @throws InterruptedException
//      *          thrown when thread is interrupted, the maximum amount of time
//      *          to wait for a new timestamp to become available has expired, or
//      *          backwards time has been detected
//      */
//     public Id generateId(int maxWait) throws InterruptedException;
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/TimeProvider.java
// public interface TimeProvider {
// 
//     /**
//      * Return the number of milliseconds from the Unix epoch.
//      */
//     public long getCurrentTime();
// }


import com.github.rholder.fauxflake.api.EncodingProvider;
import com.github.rholder.fauxflake.api.Id;
import com.github.rholder.fauxflake.api.IdGenerator;
import com.github.rholder.fauxflake.api.TimeProvider;
/*
 * Copyright 2012-2014 Ray Holder
 *
 * 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.github.rholder.fauxflake;


/**
 * This is the default reference implementation of the {@link IdGenerator}
 * interface that is resilient enough to handle leap seconds, however, backwards
 * time that occurs when the system time is updated, as from NTP, will result in
 * an {@link InterruptedException}.
 */
public class DefaultIdGenerator implements IdGenerator {

    // lock for modifying shared state
    private final Object LOCK = new Object();

    // rolling sequence number, 0 to encodingProvider.maxSequenceNumbers()
    private volatile int sequence;

    // last time we checked the current time
    private volatile long lastTime;

// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/EncodingProvider.java
// public interface EncodingProvider {
// 
//     /**
//      * Return a raw byte encoding of the given time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public byte[] encodeAsBytes(long time, int sequence);
// 
//     /**
//      * Return a Long encoding of the given the time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public long encodeAsLong(long time, int sequence);
// 
//     /**
//      * Return a String encoding of the given the time and sequence number.
//      *
//      * @param time      a time value to encode
//      * @param sequence  a sequence value to encode
//      */
//     public String encodeAsString(long time, int sequence);
// 
//     /**
//      * Return the maximum number of sequence numbers that can be encoded for a
//      * given time by this implementation.
//      */
//     public int maxSequenceNumbers();
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/Id.java
// public interface Id {
// 
//     /**
//      * Return a unique identifier as a long.
//      */
//     public long asLong();
// 
//     /**
//      * Return a unique identifier as bytes.
//      */
//     public byte[] asBytes();
// 
//     /**
//      * Return a unique identifier as a String.
//      */
//     public String asString();
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/IdGenerator.java
// public interface IdGenerator {
// 
//     /**
//      * Return a unique identifier. This should be resilient enough to handle
//      * leap seconds, however, backwards time that occurs when the system time is
//      * updated, as from NTP, will result in an {@link InterruptedException}.
//      *
//      * NOTE: Generating more id's at a time than can be handled may result in
//      * the current thread blocking for maxWait ms to ensure a new timestamp is
//      * available.
//      *
//      * @param maxWait
//      *          the maximum amount of time to wait in ms before giving up
//      * @throws InterruptedException
//      *          thrown when thread is interrupted, the maximum amount of time
//      *          to wait for a new timestamp to become available has expired, or
//      *          backwards time has been detected
//      */
//     public Id generateId(int maxWait) throws InterruptedException;
// }
// 
// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/api/TimeProvider.java
// public interface TimeProvider {
// 
//     /**
//      * Return the number of milliseconds from the Unix epoch.
//      */
//     public long getCurrentTime();
// }


// Path: fauxflake-core/src/main/java/com/github/rholder/fauxflake/DefaultIdGenerator.java
import com.github.rholder.fauxflake.api.EncodingProvider;
import com.github.rholder.fauxflake.api.Id;
import com.github.rholder.fauxflake.api.IdGenerator;
import com.github.rholder.fauxflake.api.TimeProvider;

/*
 * Copyright 2012-2014 Ray Holder
 *
 * 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.github.rholder.fauxflake;


/**
 * This is the default reference implementation of the {@link IdGenerator}
 * interface that is resilient enough to handle leap seconds, however, backwards
 * time that occurs when the system time is updated, as from NTP, will result in
 * an {@link InterruptedException}.
 */
public class DefaultIdGenerator implements IdGenerator {

    // lock for modifying shared state
    private final Object LOCK = new Object();

    // rolling sequence number, 0 to encodingProvider.maxSequenceNumbers()
    private volatile int sequence;

    // last time we checked the current time
    private volatile long lastTime;

    private final TimeProvider timeProvider;