//Dieses Skriptist ein Beispiel um Dokumente per DMS-Api hochzuladen
//Eine Beispieldatei wird bei Ausführung des Skripts erstellt
//In den Konfigurationsparametern muss für die Verbindung die Base-Url, RepoId und ein Api-Key angeben werden. Der Benutzer hinter dem Api-Key braucht mindestens die Berechtigungen "Dokument importieren" und "Eigenschaften aktualisieren"
//Per docType kann eine Dokumentart angeben werden. Die Eigenschaften können weiter unten im Skript (suche nach {to be configured}) angegeben werden. Dazu wird in diesem Beispiel das DMS-Default Mapping verwendet -> https://BASE-URL/dms/r/REPO-ID/source Beispiel: https://dms-test.local/dms/r/074ef140-250d-5a76-9c0c-311835e900e2/source
 
 
import groovy.json.JsonBuilder
import groovyx.net.http.FromServer
import groovyx.net.http.HttpBuilder
import groovyx.net.http.ContentTypes
 
import java.text.SimpleDateFormat
import java.time.YearMonth
 
 
class Configuration
{
    // login data, used to perform operations which need authentication
    // public static String API_KEY = "{yourApiKey}"
    public static String API_KEY = "DOz4JkcUEl2nu+NWmh9ylqFtIz2bDtcA+UpWikbwFpqzHGlnQuaAj5XzM+6XKTI/IPDRQomgoTN6h8y2MDkojGHUeWvqN6qJaMEZ/wNxvXMIQyiCRsDgx4yqSmKmlfEM&_z_A0V5ayCSpMjWpAFIyddgzAJPQsAloshCGVuKs-6Sxam3gyUxmKVy45yP5jqdXY0HQyCzH9im5FHDT4fboog8erv_t0Anu"
    // Base Url of d.3 system, to target API endpoints
    // public static String baseUrl = "https://{yourUrl}.de"
    public static String baseUrl = "https://w2019-sql2019en.vcloud.d-velop.de/"
    // repository of destination, is used to target right repository for searching documents
    public static String repositoryId = "1ddde1e8-2431-56c0-8cd1-b05dc1ae7dc3"
    //public static String repositoryId = "{yourRepostoryId}"
 
 
    //d.3 destination data
    public static String docType = "DTEST"
     
     
    //Do not edit these variables
    public static String dmsUrl = "/dms/r/" + repositoryId
    public static HttpBuilder httpBuilder = null
    public static String authSessionId = ""
    public static String sessionExpire = ""
    public static File csvLog = null
    public static String logDirPath = "./log/"
    public static File logFile = new File(logDirPath + System.currentTimeMillis() + "_log.csv")
}
     
    // must be allowed to set origin header
    System.setProperty( "sun.net.http.allowRestrictedHeaders", "true")
    // create httpBuilde with baseUrl
    log("Create httpBuilder")
    Configuration.httpBuilder = HttpBuilder.configure {
        request.uri = Configuration.baseUrl
        request.headers['Accept'] = 'application/json'
        request.headers['Origin'] = Configuration.baseUrl
    }
    log("httpBuilder created")
     
    login()
    uploadDocument()
     
    /**
     * Function to upload document / create placeholder
     */
    void uploadDocument(){
 
        // check if login is valid
        if(isLoginExpired()) {
            login()
        }
        String requestUUID = UUID.randomUUID().toString()
 
        // create new file
        // check if directory "Tmp" exists
        File tmpDir = new File("./Tmp/")
        if(!tmpDir.exists() || !tmpDir.isDirectory()) {
            // create directory for tmp files
            tmpDir.mkdirs()
        }
        File tmpFile = new File("./Tmp/mydoc.hc")
        tmpFile.createNewFile()
        tmpFile.text = "New mydoc: " + System.currentTimeMillis()
 
        Configuration.httpBuilder.post {
            request.uri.path = Configuration.dmsUrl + "/blob/chunk/"
            request.headers['Authorization'] = 'Bearer ' + Configuration.authSessionId
            request.headers['Accept'] = 'application/hal+json'
            request.headers['x-dv-request-id'] = requestUUID
            request.contentType = ContentTypes.BINARY[0]
            request.body = tmpFile.bytes
            response.exception { e ->
                log("RequestUUID: ${requestUUID} - Upload exception: ${e.message}")
            }
            response.failure { f ->
                log("RequestUUID: ${requestUUID} - Upload failed: ${f.message}")
 
                // if request failed because of "Unathorized" ir "Forbidden" try new login and then send request again
                if(f.message.toString().equals("Unauthorized") || f.message.toString().equals("Forbidden") ) {
                    login()
                }
            }
            response.success { s, bytes ->
                // get header for Location
                String locationUrl =  FromServer.Header.find(s.getHeaders(), "Location").parsed
                if(locationUrl != null && !locationUrl.equals("")) {
                    log("RequestUUID: ${requestUUID} - Upload of binary successful -> locationUrl: ${locationUrl} ")
                    //Now assign metadata to uploaded document
                    saveNewUploadedDocument(locationUrl)
                }
 
            }
        }
    }
 
 
    /**
     * Function to assign metadata to uploaded document
     */
    void saveNewUploadedDocument(String locationUrl){
        // check if login is valid
        if(isLoginExpired()) {
            login()
        }
 
        String requestUUID = UUID.randomUUID().toString()
 
        Map bodyMap = new HashMap<>()
        //Your file
        bodyMap.put("filename", "mydoc.hc")
        bodyMap.put("sourceCategory", Configuration.docType)
        bodyMap.put("sourceId", Configuration.dmsUrl + "/source")
        bodyMap.put("contentLocationUri", locationUrl)
         
        List propertiesList = new ArrayList()
        Map propertiesMap = new HashMap()
        Map propertyMap1 = new HashMap<>()
        Map propertyMap2 = new HashMap<>()
        //ToDo: Adjust Key and value. Have a look at this URL to find out the keys for your metadata: https://BASE-URL/dms/r/REPO-ID/source Example: https://dms-test.local/dms/r/074ef140-250d-5a76-9c0c-311835e900e2/source
        //Your metadata (single value) {to be configured}
        propertyMap1.put("key", "1")
        propertyMap1.put("values", ["myValue"])
        propertiesList.add(propertyMap1)
        propertiesMap.put("properties", propertiesList)
        bodyMap.put("sourceProperties", propertiesMap)
         
        //Your metadata (multi value) {to be configured}
        propertyMap2.put("key", "12")
        propertyMap2.put("values", ["myDocMultiValue1", "myDocMultiValue2"])
        propertiesList.add(propertyMap2)
        propertiesMap.put("properties", propertiesList)
        bodyMap.put("sourceProperties", propertiesMap)
         
        JsonBuilder jsonBuilder = new JsonBuilder()
        jsonBuilder.content = bodyMap
         
        Configuration.httpBuilder.post {
            request.uri.path = Configuration.dmsUrl + "/o2m"
            request.headers['Authorization'] = 'Bearer ' + Configuration.authSessionId
            request.headers['Accept'] = 'application/hal+json'
            request.headers['x-dv-request-id'] = requestUUID
            request.contentType = ContentTypes.JSON[0]//'application/hal+json'
            request.body = jsonBuilder.toPrettyString()
            response.parser(ContentTypes.JSON[0]) {config, resp ->
                String responseText = resp.inputStream.getText()
                log("RequestUUID: ${requestUUID} - ResponseText: ${responseText}")
            }
            response.exception { e ->
                log("RequestUUID: ${requestUUID} - Save uploaded file exception: ${e.message}")
            }
            response.failure { f ->
                log("RequestUUID: ${requestUUID} - Save uploaded file failed: ${f.message}")
 
                // if request failed because of "Unathorized" ir "Forbidden" try new login and then send request again
                if(f.message.toString().equals("Unauthorized") || f.message.toString().equals("Forbidden") ) {
                    login()
                }
            }
            response.success { s ->
             
                log("RequestUUID: ${requestUUID} - Save uploaded file successful")
 
                // get docId from Location Header
                String locationHeader =  FromServer.Header.find(s.getHeaders(), "Location").parsed
                if(locationHeader != null && !locationHeader.equals("")) {
                    String[] locationParts = locationHeader.split("/o2m/")
                    if(locationParts.size() == 2) {
                        String[] secondParts = locationParts[1].split("\\?")
                        String docId = secondParts[0]
             
                        log("RequestUUID: ${requestUUID} - Save uploaded file successful: DocId - " + docId)
                    }
                }
            }
        }
    }
 
    /**
     * Function to perform login request
     */
    void login() {
        String requestUUID = UUID.randomUUID().toString()
         
        Configuration.httpBuilder.get {
            request.uri.path = '/identityprovider/login'
            request.headers['Authorization'] = 'Bearer ' + Configuration.API_KEY
            request.headers['x-dv-request-id'] = requestUUID
            request.contentType = ContentTypes.URLENC
            response.exception { e ->
                log("RequestUUID: ${requestUUID} - Login exception")
            }
            response.failure { f ->
                log("RequestUUID: ${requestUUID} - Login failed: ${f.message}")
            }
            response.success { s, json ->
             
                log("RequestUUID: ${requestUUID} - Login success")
 
                Configuration.authSessionId = json.getAt("authSessionId")
                Configuration.sessionExpire = json.getAt("expire")
 
                if(Configuration.authSessionId == null || Configuration.authSessionId.equals("") || Configuration.authSessionId.equals("null")) {
                    log("AuthSessionId not given with first letter small, try upper case")
                    Configuration.authSessionId = json.getAt("AuthSessionId")
                }
                if(Configuration.sessionExpire == null || Configuration.sessionExpire.equals("") || Configuration.sessionExpire.equals("null")) {
                    log("Expire not given with first letter small, try upper case")
                    Configuration.sessionExpire = json.getAt("Expire")
                }
            }
        }
    }
 
    /**
     * Function to check if authSessionId is given and still not expired
     *
     * @return boolean true if login is not valid
     */
    boolean isLoginExpired() {
        boolean result = false
 
        if(Configuration.authSessionId == null || Configuration.authSessionId.equals("")) {
            result = true
        }
 
        if(Configuration.sessionExpire == null || Configuration.sessionExpire.equals("")) {
            result = true
        } else {
            // check if sessionExpire is grater then current timestamp
            long nowTimestamp = System.currentTimeMillis()
 
            // convert sessionExpire to timestamp
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'H:m:s.S'Z'")
            Date expireDate = inputFormat.parse(Configuration.sessionExpire)
            long expireTimestamp = expireDate.time
 
            if(nowTimestamp>=expireTimestamp) {
                result = true
            }
        }
 
        return result
    }
     
    /**
     * Function to log given message to log file and to console
     * @param message
     */
    void log(String message) {
        String messageWithTimestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(System.currentTimeMillis())) + " : ${message}"
        println(messageWithTimestamp)
 
        if(!Configuration.logFile.exists()) {
            // check if directory exists
            // check if directory "Log" exists
            File logDir = new File(Configuration.logDirPath)
            if(!logDir.exists() || !logDir.isDirectory()) {
                // create directory for log files
                logDir.mkdirs()
            }
 
            Configuration.logFile.createNewFile()
        }
        Configuration.logFile.append(messageWithTimestamp + "\n")
    }