/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package doublex.lib.locks;

/**
 *
 * @author DoubleX
 * @param <K>
 */
public final class CountedLock<K> implements ICountable, ILockable<K> {

    private final ILockable<K> mLock;

    private int mKeyMismatchCount;
    private int mMaxKeyMismatchCount;

    public CountedLock(final int maxKeyMismatchCount, final ILockable<K> lock) {
        resetKeyMismatchCount();
        mMaxKeyMismatchCount = maxKeyMismatchCount;
        mLock = lock;
    }

    @Override
    public boolean isLocked() {
        return mLock.isLocked();
    }

    @Override
    public void lock() {
        mLock.lock();
    }

    @Override
    public void tryUnlock(final K key) {
        if (isReachMaxKeyMismatchCount()) {
            return;
        }
        mLock.tryUnlock(key);
        if (isLocked()) {
            addKeyMismatchCount();
        }
    }

    @Override
    public int count() {
        return mKeyMismatchCount;
    }

    @Override
    public void tryChangeMaxCount(final int maxCount) {
        if (canChangeMaxCount(maxCount)) {
            changeMaxKeyMismatchCount(maxCount);
        }
    }

    @Override
    public void tryResetCount() {
        if (!isLocked()) {
            resetKeyMismatchCount();
        }
    }

    private boolean isReachMaxKeyMismatchCount() {
        return count() >= mMaxKeyMismatchCount;
    }

    private void addKeyMismatchCount() {
        mKeyMismatchCount++;
    }

    private boolean canChangeMaxCount(final int maxCount) {
        return !isLocked() && isExceedCurKeyMismatchCount(maxCount);
    }

    private boolean isExceedCurKeyMismatchCount(final int maxCount) {
        return maxCount > count();
    }

    private void changeMaxKeyMismatchCount(final int maxCount) {
        mMaxKeyMismatchCount = maxCount;
    }

    private void resetKeyMismatchCount() {
        mKeyMismatchCount = 0;
    }

}

@@ -203,16 +203,287 @@
 ib.locks
+.lock;%0A%0Aimport doublex.lib.locks.ICountable;%0Aimport doublex.lib.locks.ILockable;%0Aimport doublex.lib.locks.exceptions.KeyMismatchException;%0Aimport doublex.lib.locks.exceptions.MaxKeyMismatchCountReachedException;%0Aimport doublex.lib.locks.exceptions.ResetCountFailException
 ;%0A%0A/**%0A 
@@ -670,25 +670,9 @@
 ount
-;%0A    private int
+,
  mMa
@@ -1092,16 +1092,44 @@
 l K key)
+ throws KeyMismatchException
  %7B%0A     
@@ -1131,21 +1131,22 @@
         
-if (i
+checkI
 sReachMa
@@ -1168,41 +1168,9 @@
 nt()
-) %7B%0A            return;%0A        %7D
+;
 %0A   
@@ -1249,32 +1249,79 @@
 ismatchCount();%0A
+            checkIsReachMaxKeyMismatchCount();%0A
         %7D%0A    %7D%0A
@@ -1473,23 +1473,99 @@
 nt) 
-%7B%0A        if (c
+%0A            throws ResetCountFailException %7B%0A        if (!isLocked()) %7B%0A            checkC
 anCh
@@ -1586,19 +1586,17 @@
 axCount)
-) %7B
+;
 %0A       
@@ -1718,32 +1718,33 @@
 if (!isLocked())
+ 
  %7B%0A            r
@@ -1776,32 +1776,282 @@
        %7D%0A    %7D%0A%0A
+    private void checkIsReachMaxKeyMismatchCount() throws KeyMismatchException %7B%0A        if (isReachMaxKeyMismatchCount()) %7B%0A            throw new KeyMismatchException(%0A                    new MaxKeyMismatchCountReachedException());%0A        %7D%0A    %7D%0A%0A
     private bool
@@ -2233,17 +2233,19 @@
 ate 
-boolean c
+void checkC
 anCh
@@ -2269,33 +2269,32 @@
 l int maxCount) 
-%7B
 %0A        return 
@@ -2290,68 +2290,218 @@
     
-return !isLocked() && isExceedCurKeyMismatchCount(maxCount);
+    throws ResetCountFailException %7B%0A        if (isExceedCurKeyMismatchCount(maxCount)) %7B%0A            throw new ResetCountFailException(%0A                    new MaxKeyMismatchCountReachedException());%0A        %7D
 %0A   

Update CountedLock.java