// Path: src/main/java/com/yet/dsync/dto/DropboxFileData.java
// @Data
// @Builder(toBuilder = true)
// public final class DropboxFileData {
// 
//     private final DropboxChangeType changeType;
// 
//     private final String pathDisplay;
// 
//     private final String pathLower;
// 
//     private final String id;
// 
//     private final String rev;
// 
//     private final Long size;
// 
//     private final LocalDateTime serverModified;
// 
//     private final LocalDateTime clientModified;
// 
//     public boolean isFile() {
//         return rev != null;
//     }
// 
//     public boolean isDirectory() {
//         return id != null && rev == null;
//     }
// 
//     @Override
//     public String toString() {
//         String str = this.getClass().getSimpleName() + " [" + changeType + " " + pathDisplay;
// 
//         if (DropboxChangeType.FOLDER == changeType) {
//             str += ", id: " + id;
//         } else if (DropboxChangeType.FILE == changeType) {
//             str += ", id: " + id + ", rev: " + rev + ", size: " + size
//                     + ", client: " + clientModified + ", server: " + serverModified;
//         }
// 
//         str += "]";
//         return str;
//     }
// }
// 
// Path: src/main/java/com/yet/dsync/exception/DSyncClientException.java
// public class DSyncClientException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public DSyncClientException(final String message) {
//         super(message);
//     }
// 
//     public DSyncClientException(final Throwable cause) {
//         super(cause);
//     }
// 
//     public DSyncClientException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     public DSyncClientException(final String message, final Throwable cause,
//                                 final boolean enableSuppression, final boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
// }


import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.yet.dsync.dto.DropboxFileData;
import com.yet.dsync.exception.DSyncClientException;
import lombok.SneakyThrows;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Set;

    private static final int COL_PATH_LOWER = COL_PATH + 1;
    private static final int COL_LOADED = COL_PATH_LOWER + 1;
    private static final int COL_REV = COL_LOADED + 1;
    private static final int COL_SIZE = COL_REV + 1;
    private static final int COL_SRVDATE = COL_SIZE + 1;
    private static final int COL_CLIDATE = COL_SRVDATE + 1;

    private static final int UPD_PARAM_PATH = 1;
    private static final int UPD_PARAM_PATH_LOWER = UPD_PARAM_PATH + 1;
    private static final int UPD_PARAM_REV = UPD_PARAM_PATH_LOWER + 1;
    private static final int UPD_PARAM_SIZE = UPD_PARAM_REV + 1;
    private static final int UPD_PARAM_SRVDATE = UPD_PARAM_SIZE + 1;
    private static final int UPD_PARAM_CLIDATE = UPD_PARAM_SRVDATE + 1;
    private static final int UPD_PARAM_ID = UPD_PARAM_CLIDATE + 1;

    private final PreparedStatement readByIdStatement;
    private final PreparedStatement readNotLoadedStatement;
    private final PreparedStatement readByPLowerStatement;
    private final PreparedStatement insertStatement;
    private final PreparedStatement updateLoadedStatement;
    private final PreparedStatement updateFieldsStatement;
    private final PreparedStatement deleteByPathStatement;

    private final Lock syncLock = new ReentrantLock(true);

    @SneakyThrows
    public MetadataDao(final Connection connection) {
        readByIdStatement = connection.prepareStatement(SELECT_BY_ID_STATEMENT);
        readNotLoadedStatement = connection.prepareStatement(SELECT_NOT_LOADED_STATEMENT);
        readByPLowerStatement = connection.prepareStatement(SELECT_BY_PLOWER_STATEMENT);

// Path: src/main/java/com/yet/dsync/dto/DropboxFileData.java
// @Data
// @Builder(toBuilder = true)
// public final class DropboxFileData {
// 
//     private final DropboxChangeType changeType;
// 
//     private final String pathDisplay;
// 
//     private final String pathLower;
// 
//     private final String id;
// 
//     private final String rev;
// 
//     private final Long size;
// 
//     private final LocalDateTime serverModified;
// 
//     private final LocalDateTime clientModified;
// 
//     public boolean isFile() {
//         return rev != null;
//     }
// 
//     public boolean isDirectory() {
//         return id != null && rev == null;
//     }
// 
//     @Override
//     public String toString() {
//         String str = this.getClass().getSimpleName() + " [" + changeType + " " + pathDisplay;
// 
//         if (DropboxChangeType.FOLDER == changeType) {
//             str += ", id: " + id;
//         } else if (DropboxChangeType.FILE == changeType) {
//             str += ", id: " + id + ", rev: " + rev + ", size: " + size
//                     + ", client: " + clientModified + ", server: " + serverModified;
//         }
// 
//         str += "]";
//         return str;
//     }
// }
// 
// Path: src/main/java/com/yet/dsync/exception/DSyncClientException.java
// public class DSyncClientException extends RuntimeException {
// 
//     private static final long serialVersionUID = 1L;
// 
//     public DSyncClientException(final String message) {
//         super(message);
//     }
// 
//     public DSyncClientException(final Throwable cause) {
//         super(cause);
//     }
// 
//     public DSyncClientException(final String message, final Throwable cause) {
//         super(message, cause);
//     }
// 
//     public DSyncClientException(final String message, final Throwable cause,
//                                 final boolean enableSuppression, final boolean writableStackTrace) {
//         super(message, cause, enableSuppression, writableStackTrace);
//     }
// 
// }


// Path: src/main/java/com/yet/dsync/dao/MetadataDao.java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import com.yet.dsync.dto.DropboxFileData;
import com.yet.dsync.exception.DSyncClientException;
import lombok.SneakyThrows;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Set;

    private static final int COL_PATH_LOWER = COL_PATH + 1;
    private static final int COL_LOADED = COL_PATH_LOWER + 1;
    private static final int COL_REV = COL_LOADED + 1;
    private static final int COL_SIZE = COL_REV + 1;
    private static final int COL_SRVDATE = COL_SIZE + 1;
    private static final int COL_CLIDATE = COL_SRVDATE + 1;

    private static final int UPD_PARAM_PATH = 1;
    private static final int UPD_PARAM_PATH_LOWER = UPD_PARAM_PATH + 1;
    private static final int UPD_PARAM_REV = UPD_PARAM_PATH_LOWER + 1;
    private static final int UPD_PARAM_SIZE = UPD_PARAM_REV + 1;
    private static final int UPD_PARAM_SRVDATE = UPD_PARAM_SIZE + 1;
    private static final int UPD_PARAM_CLIDATE = UPD_PARAM_SRVDATE + 1;
    private static final int UPD_PARAM_ID = UPD_PARAM_CLIDATE + 1;

    private final PreparedStatement readByIdStatement;
    private final PreparedStatement readNotLoadedStatement;
    private final PreparedStatement readByPLowerStatement;
    private final PreparedStatement insertStatement;
    private final PreparedStatement updateLoadedStatement;
    private final PreparedStatement updateFieldsStatement;
    private final PreparedStatement deleteByPathStatement;

    private final Lock syncLock = new ReentrantLock(true);

    @SneakyThrows
    public MetadataDao(final Connection connection) {
        readByIdStatement = connection.prepareStatement(SELECT_BY_ID_STATEMENT);
        readNotLoadedStatement = connection.prepareStatement(SELECT_NOT_LOADED_STATEMENT);
        readByPLowerStatement = connection.prepareStatement(SELECT_BY_PLOWER_STATEMENT);

        insertStatement = connection.prepareStatement(INSERT_STATEMENT);
