Skip to content
The Chat Archive
gpt-4-0314· OpenAI WildChat-4.8M (AI2)

java.lang.IllegalArgumentException: Illegal pattern character ‘e’ println(…

  1. User

    java.lang.IllegalArgumentException: Illegal pattern character ‘e’

    println( DateUtils.currentWeek() )

    fun currentWeek(): String { val weekNum = currentDate[Calendar.WEEK_OF_YEAR] val dateFormat = SimpleDateFormat(“Week_” + weekNum + “_MMM_yyyy”, Locale.getDefault()) return dateFormat.format(currentDate.time) }

  2. Assistant

    It seems there is a wrong type of double quote character (“”) in your code. You should use the correct double quote character (") for the strings. Please change the double quote characters and try again.

    Here's the corrected code:

    import java.text.SimpleDateFormat
    import java.util.Calendar
    import java.util.Locale
    import java.util.Date
    
    fun main() {
        println(currentWeek())
    }
    
    fun currentWeek(): String {
        val currentDate = Calendar.getInstance()
        val weekNum = currentDate[Calendar.WEEK_OF_YEAR]
        val dateFormat = SimpleDateFormat("Week_" + weekNum + "_MMM_yyyy", Locale.getDefault())
        return dateFormat.format(currentDate.time)
    }
    

    This code should work without the java.lang.IllegalArgumentException.

  3. User

    db.collection("expenses") .document(userId) .collection("yearly") .document(currentDate[Calendar.YEAR].toString()) .set(initData)

        db.collection("expenses")
            .document(userId)
            .collection("monthly")
            .document(currentMonth())
            .set(initData)
    
        db.collection("expenses")
            .document(userId)
            .collection("weekly")
            .document(currentWeek())
            .set(initData)
    
        db.collection("expenses")
            .document(userId)
            .collection("daily")
            .document(currentDay())
            .set(initData)
    

    is there anyway to add a successful and failure listener for all of those queries?

  4. Assistant

    Yes, you can add success and failure listeners to each query. In order to do that, you can use the addOnSuccessListener and addOnFailureListener methods to your write operations.

    You can create a function that handles success and failure listeners:

    import com.google.android.gms.tasks.Task
    import java.lang.Exception
    
    private fun handleTask(task: Task<Void>, successMessage: String, failureMessage: String) {
        task.addOnSuccessListener {
            Log.d("TAG", successMessage)
        }.addOnFailureListener { exception ->
            Log.e("TAG", failureMessage, exception)
        }
    }
    

    Then, you can modify your write operations to use this function:

    val yearlyTask = db.collection("expenses")
        .document(userId)
        .collection("yearly")
        .document(currentDate[Calendar.YEAR].toString())
        .set(initData)
    
    val monthlyTask = db.collection("expenses")
        .document(userId)
        .collection("monthly")
        .document(currentMonth())
        .set(initData)
    
    val weeklyTask = db.collection("expenses")
        .document(userId)
        .collection("weekly")
        .document(currentWeek())
        .set(initData)
    
    val dailyTask = db.collection("expenses")
        .document(userId)
        .collection("daily")
        .document(currentDay())
        .set(initData)
    
    handleTask(yearlyTask, "Yearly data saved successfully", "Error saving yearly data")
    handleTask(monthlyTask, "Monthly data saved successfully", "Error saving monthly data")
    handleTask(weeklyTask, "Weekly data saved successfully", "Error saving weekly data")
    handleTask(dailyTask, "Daily data saved successfully", "Error saving daily data")
    

    This code will add success and failure listeners to each of your write operations, and you will see logs for success and failure events. Please make sure to have imported the required classes in your file.

  5. User

    when I update the document that have the same name it will replace the expenses and quantity what I want instead is it will do an addition if its the same name, and create a new field if its a new name, I think we need to use array in the firestore field

  6. Assistant

    Yes, you can use Firestore transactions or FieldValue.increment() to perform this update operation. I would suggest using FieldValue.increment(), as it is simpler and easier to use. Here's how you can update the document with the increment.

    Assuming you have fields "expenses" and "quantity" in your document, this code will perform the addition if the fields already exist or add new fields if they don't:

    import com.google.firebase.firestore.FieldValue
    import com.google.firebase.firestore.FirebaseFirestore
    
    val db = FirebaseFirestore.getInstance()
    val expensesRef = db.collection("expenses").document(userId)
    
    val newData = hashMapOf(
        "expenses" to FieldValue.increment(1),
        "quantity" to FieldValue.increment(1)
    )
    
    // Performs addition if the fields already exist or creates new fields if they don't.
    expensesRef.update(newData)
        .addOnSuccessListener {
            Log.d("TAG", "Document updated successfully")
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error updating document", exception)
        }
    

    Remember to replace 1 with the desired values for updating "expenses" and "quantity".

  7. User

    okay, another problem I'm facing is for example I've added a new item with name = ABC, and I from the app I input a new name which is CBA, It will replace the current name field, whats the solution?

  8. Assistant

    If you want to add data to Firestore without overwriting the old data, you can use the .update() method with a combination of different types of data.

    You can add a new field to hold the list of items and only update the elements within the list. Here's an example of your requirement, creating a new field called "items" which is an array containing your items with names and quantity.

    Assuming you have an "items" array with an "name" and "quantity" attribute for each element:

    import com.google.firebase.firestore.FieldValue
    import com.google.firebase.firestore.FirebaseFirestore
    
    // Replace these values with the actual name and quantity of the new item
    val newItemName = "CBA"
    val newItemQuantity = 1
    
    // Replace the document id with your userId
    val userId = "your_user_id"
    
    val db = FirebaseFirestore.getInstance()
    
    val docRef = db.collection("expenses").document(userId)
    
    docRef.get()
        .addOnSuccessListener { document ->
            if (document.exists()) {
                val items = document.get("items") as MutableList<HashMap<String, Any>>
    
                var itemFound = false
                items.forEach { item ->
                    if (item["name"] == newItemName) {
                        item["quantity"] = (item["quantity"] as Int) + newItemQuantity
                        itemFound = true
                    }
                }
    
                if (!itemFound) {
                    val newItem = hashMapOf("name" to newItemName, "quantity" to newItemQuantity)
                    items.add(newItem)
                }
    
                docRef.update("items", items)
                    .addOnSuccessListener {
                        Log.d("TAG", "Document updated successfully")
                    }
                    .addOnFailureListener { exception ->
                        Log.e("TAG", "Error updating document", exception)
                    }
            } else {
                Log.d("TAG", "No such document")
            }
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error getting the document", exception)
        }
    

    This example retrieves the document from Firestore, checks if it exists, and then looks for the desired item within the 'items' array. If the item is found, it updates the 'quantity' attribute; if not, it adds a new item. Finally, it updates the array in Firestore.

    Replace your_user_id with the actual userId, and newItemName and newItemQuantity with the values you want to add or update.

  9. User

    right now I have 3 fields of array types name, quantity and expenses, and it will store the different values, how to write the code?

  10. Assistant

    You can modify the existing code to handle all three arrays: name, quantity, and expenses. In this example, I assume that each index in the arrays correspond to the respective name, quantity, and expenses of an item.

    import com.google.firebase.firestore.FirebaseFirestore
    
    val newItemName = "CBA"
    val newItemQuantity = 1
    val newExpensesValue = 100
    val userId = "your_user_id"
    
    val db = FirebaseFirestore.getInstance()
    val docRef = db.collection("expenses").document(userId)
    
    docRef.get()
        .addOnSuccessListener { document ->
            if (document.exists()) {
                val names = document.get("name") as MutableList<String>
                val quantities = document.get("quantity") as MutableList<Int>
                val expenses = document.get("expenses") as MutableList<Int>
    
                var itemFound = false
                var itemIndex = -1
                names.forEachIndexed { index, itemName ->
                    if (itemName == newItemName) {
                      itemFound = true
                      itemIndex = index
                    }
                }
    
                if (itemFound) {
                    quantities[itemIndex] += newItemQuantity
                    expenses[itemIndex] += newExpensesValue
                } else {
                    names.add(newItemName)
                    quantities.add(newItemQuantity)
                    expenses.add(newExpensesValue)
                }
    
                val updateData = hashMapOf(
                    "name" to names,
                    "quantity" to quantities,
                    "expenses" to expenses
                )
    
                docRef.update(updateData)
                    .addOnSuccessListener {
                        Log.d("TAG", "Document updated successfully")
                    }
                    .addOnFailureListener { exception ->
                        Log.e("TAG", "Error updating document", exception)
                    }
            } else {
                Log.d("TAG", "No such document")
            }
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error getting the document", exception)
        }
    

    Replace your_user_id with the actual userId, and newItemName, newItemQuantity, and newExpensesValue with the values you want to add or update.

  11. User

    db.collection("expenses") .document(userId) .collection("yearly") .document(currentDate[Calendar.YEAR].toString()) .set(initData) .addOnSuccessListener { Toast.makeText(context, "Berhasil", Toast.LENGTH_SHORT).show() } .addOnFailureListener { Toast.makeText(context, "Gagal", Toast.LENGTH_SHORT).show() }

        db.collection("expenses")
            .document(userId)
            .collection("monthly")
            .document(currentMonth())
            .set(initData)
            .addOnSuccessListener { Toast.makeText(context, "Berhasil", Toast.LENGTH_SHORT).show() }
            .addOnFailureListener { Toast.makeText(context, "Gagal", Toast.LENGTH_SHORT).show() }
    
        db.collection("expenses")
            .document(userId)
            .collection("weekly")
            .document(currentWeek())
            .set(initData)
            .addOnSuccessListener { Toast.makeText(context, "Berhasil", Toast.LENGTH_SHORT).show() }
            .addOnFailureListener { Toast.makeText(context, "Gagal", Toast.LENGTH_SHORT).show() }
    
        db.collection("expenses")
            .document(userId)
            .collection("daily")
            .document(currentDay())
            .set(initData)
            .addOnSuccessListener { Toast.makeText(context, "Berhasil", Toast.LENGTH_SHORT).show() }
            .addOnFailureListener { Toast.makeText(context, "Gagal", Toast.LENGTH_SHORT).show() }
    

    can you merge the above code with the array code, so that it automatically updates all the collections at once?

  12. Assistant

    You can create a function that updates the document with the specified name, quantity, and expenses, and then call that function for every document that needs updating. Here's how to do that:

    import com.google.firebase.firestore.FirebaseFirestore
    
    fun updateDocumentWithNewItem(
        userId: String,
        collectionName: String,
        documentId: String,
        newItemName: String,
        newItemQuantity: Int,
        newExpensesValue: Int
    ) {
        val db = FirebaseFirestore.getInstance()
        val docRef = db.collection("expenses").document(userId).collection(collectionName).document(documentId)
    
        docRef.get()
            .addOnSuccessListener { document ->
                if (document.exists()) {
                    val names = document.get("name") as MutableList<String>
                    val quantities = document.get("quantity") as MutableList<Int>
                    val expenses = document.get("expenses") as MutableList<Int>
    
                    var itemFound = false
                    var itemIndex = -1
                    names.forEachIndexed { index, itemName ->
                        if (itemName == newItemName) {
                            itemFound = true
                            itemIndex = index
                        }
                    }
    
                    if (itemFound) {
                        quantities[itemIndex] += newItemQuantity
                        expenses[itemIndex] += newExpensesValue
                    } else {
                        names.add(newItemName)
                        quantities.add(newItemQuantity)
                        expenses.add(newExpensesValue)
                    }
    
                    val updateData = hashMapOf(
                        "name" to names,
                        "quantity" to quantities,
                        "expenses" to expenses
                    )
    
                    docRef.update(updateData)
                        .addOnSuccessListener {
                            Toast.makeText(context, "Berhasil - $documentId", Toast.LENGTH_SHORT).show()
                        }
                        .addOnFailureListener { exception ->
                            Toast.makeText(context, "Gagal - $documentId", Toast.LENGTH_SHORT).show()
                        }
                } else {
                    Log.d("TAG", "No such document")
                }
            }
            .addOnFailureListener { exception ->
                Log.e("TAG", "Error getting the document", exception)
            }
    }
    
    // Usage
    val newItemName = "CBA"
    val newItemQuantity = 1
    val newExpensesValue = 100
    val userId = "your_user_id"
    
    updateDocumentWithNewItem(userId, "yearly", currentDate[Calendar.YEAR].toString(), newItemName, newItemQuantity, newExpensesValue)
    updateDocumentWithNewItem(userId, "monthly", currentMonth(), newItemName, newItemQuantity, newExpensesValue)
    updateDocumentWithNewItem(userId, "weekly", currentWeek(), newItemName, newItemQuantity, newExpensesValue)
    updateDocumentWithNewItem(userId, "daily", currentDay(), newItemName, newItemQuantity, newExpensesValue)
    

    Replace your_user_id with the actual userId, and newItemName, newItemQuantity, and newExpensesValue with the values you want to add or update. Make sure to import all the necessary classes and functions from previous code snippets to use functions like currentMonth(), currentWeek(), and currentDay().

  13. User

    docRef.get() .addOnSuccessListener { document -> if (document.exists()) { val names = document.get("name") as MutableList val quantities = document.get("quantity") as MutableList val expenses = document.get("expenses") as MutableList

    java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List

  14. Assistant

    The error you encountered is related to trying to cast a field to the wrong type. The Firestore field types are encoded differently and need to be decoded using a type token. You can use toArray with a typed array to handle this problem:

    if (document.exists()) {
        val namesArray = document.get("name")?.let { (it as List<*>).toTypedArray() as Array<String> }
        val quantitiesArray =
            document.get("quantity")?.let { (it as List<*>).toTypedArray() as Array<Int> }
        val expensesArray =
            document.get("expenses")?.let { (it as List<*>).toTypedArray() as Array<Double> }
    
        if (namesArray != null && quantitiesArray != null && expensesArray != null) {
            val names = namesArray.toMutableList()
            val quantities = quantitiesArray.toMutableList()
            val expenses = expensesArray.toMutableList()
    
            // The rest of the code goes here ...
        } else {
            Log.d("TAG", "Error processing document data")
        }
    } else {
        Log.d("TAG", "No such document")
    }
    

    This code snippet checks if the document exists, then gets the arrays using a type token when decoding the Firestore field types. If arrays are not null, the code continues to process the document. Make sure to import all the necessary classes and replace the comment with the corresponding code from the previous example.

  15. User

    java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.String[]

  16. Assistant

    I apologize for the confusion. Let's update the approach slightly to avoid the ClassCastException.

    You can use a DocumentSnapshot's toObjects method to extract an array in Firestore as a list of the expected type:

    if (document.exists()) {
        val names = document.toObject(object : TypeToken<Map<String, List<String>>>() {}.type)["name"]?.toMutableList()
        val quantities = document.toObject(object : TypeToken<Map<String, List<Int>>>() {}.type)["quantity"]?.toMutableList()
        val expenses = document.toObject(object : TypeToken<Map<String, List<Double>>>() {}.type)["expenses"]?.toMutableList()
    
        if (names != null && quantities != null && expenses != null) {
            // The rest of the code goes here ...
        } else {
            Log.d("TAG", "Error processing document data")
        }
    } else {
        Log.d("TAG", "No such document")
    }
    

    This method should handle Firestore field types correctly, and you won't encounter any ClassCastException. Make sure to import the necessary classes:

    import com.google.gson.reflect.TypeToken
    
  17. User

    val names = document.get(“name”) as MutableList

    java.lang.String cannot be cast to java.util.List

  18. Assistant

    My apologies for the confusion. It seems that we need to get the List from the DocumentSnapshot differently.

    You can try this alternative way of getting the list of data from the DocumentSnapshot:

    if (document.exists()) {
        val names = document.get("name") as? List<String> ?: mutableListOf()
        val quantities = document.get("quantity") as? List<Int> ?: mutableListOf()
        val expenses = document.get("expenses") as? List<Double> ?: mutableListOf()
        
        // Mutable conversion
        val mutableNames = names.toMutableList()
        val mutableQuantities = quantities.toMutableList()
        val mutableExpenses = expenses.toMutableList()
    
        // The rest of the code goes here ...
    } else {
        Log.d("TAG", "No such document")
    }
    

    Use the as? operator with the desired type, followed by the Elvis operator ?: and an empty mutableList. This will try to cast the field values to the desired type. If the casting fails, it will create a new empty mutable list.

    After the operation, the code continues to process the document with mutable versions of the name, quantity, and expenses lists. Replace the comment with the corresponding code from the previous example.

  19. User

    no error but there is no update happening

  20. Assistant

    My apologies if the previous code snippet didn't work as expected. Let's try another approach to retrieve the data from the Firestore document.

    First, create a helper function getListFromDocument to make it easier to retrieve the lists from the document:

    import com.google.firebase.firestore.DocumentSnapshot
    
    fun <T> getListFromDocument(document: DocumentSnapshot, field: String): MutableList<T> {
        return (document.get(field) as? List<T>)?.toMutableList() ?: mutableListOf()
    }
    

    Then, use this helper function to retrieve the names, quantities, and expenses lists in the addOnSuccessListener:

    if (document.exists()) {
        val names = getListFromDocument<String>(document, "name")
        val quantities = getListFromDocument<Int>(document, "quantity")
        val expenses = getListFromDocument<Double>(document, "expenses")
    
        // The rest of the code goes here ...
    } else {
        Log.d("TAG", "No such document")
    }
    

    Ensure that the rest of the code that updates the lists and the Firestore document is correctly implemented. Replace the comment with the corresponding code from the previous example.

    If the document is still not updating, you might want to add some logs to see which part of the code is failing to locate the issue. Try adding log statements to the if conditions and in the addOnSuccessListener and addOnFailureListener listeners for the docRef.update(updateData).

  21. User

    docRef.update(updateData) .addOnSuccessListener { Log.d("TAG", "Document updated successfully") } .addOnFailureListener { exception -> Log.e("TAG", "Error updating document", exception) }

    Java type mismatch expected (Mutable)Map<String!, Any!> but found kotlin.collections.HashMap<String, List<{Comparable<> & java.io.Serializable}>> / = java.util.HashMap<String, List<{Comparable<*> & java.io.Serializable}>> */. Use explicit cast

  22. Assistant

    The error message indicates a type mismatch in the updateData. You can explicitly cast the updateData variable to type Map<String, Any> to resolve the issue. Here's the updated code:

    val updateData: Map<String, Any> = hashMapOf(
        "name" to names,
        "quantity" to quantities,
        "expenses" to expenses
    )
    
    docRef.update(updateData)
        .addOnSuccessListener {
            Log.d("TAG", "Document updated successfully")
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error updating document", exception)
        }
    

    This should resolve the type mismatch issue and update the document correctly.

  23. User

    docRef.get() .addOnSuccessListener { document -> if (document.exists()) { val names = document.get("name") as? List ?: mutableListOf() val quantities = document.get("quantity") as? List ?: mutableListOf() val expenses = document.get("expenses") as? List ?: mutableListOf()

                    val mutableNames = names.toMutableList()
                    val mutableQuantities = quantities.toMutableList()
                    val mutableExpenses = expenses.toMutableList()
    
                        var itemFound = false
                        var itemIndex = -1
                        names.forEachIndexed { index, itemName ->
                            if (itemName == name) {
                                itemFound = true
                                itemIndex = index
                            }
                        }
    
                        if (itemFound) {
                            mutableQuantities[itemIndex] += quantity
                            mutableExpenses[itemIndex] += expense
                        } else {
                            mutableNames.add(name)
                            mutableQuantities.add(quantity)
                            mutableExpenses.add(expense)
                        }
    
                        val updateData: Map<String, Any>  = hashMapOf(
                            "name" to names,
                            "quantity" to quantities,
                            "expenses" to expenses
                        )
    
                        docRef.update(updateData)
                            .addOnSuccessListener {
                                Log.d("TAG", "Document updated successfully")
                            }
                            .addOnFailureListener { exception ->
                                Log.e("TAG", "Error updating document", exception)
                            }
                    } else {
                        Log.d("TAG", "No such document")
                    }
                }
    
            .addOnFailureListener { exception ->
                Log.e("TAG", "Error getting the document", exception)
            }
    

    Checking the log it says "Document updated successfully" but checking the firestore nothing has changed

  24. Assistant

    There seems to be a minor oversight in the code. In the updateData HashMap, you're currently adding the original (non-mutable) lists names, quantities, and expenses. You should be adding their mutable versions instead, which have the updated values.

    Here's the corrected code snippet:

    val updateData: Map<String, Any> = hashMapOf(
        "name" to mutableNames,
        "quantity" to mutableQuantities,
        "expenses" to mutableExpenses
    )
    
    docRef.update(updateData)
        .addOnSuccessListener {
            Log.d("TAG", "Document updated successfully")
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error updating document", exception)
        }
    

    This should now correctly update the document in Firestore.

  25. User

    I added a fourth field which is a number type and it will be the sum of expenses across all the value in expenses array

  26. Assistant

    You can add another field, for example, "totalExpenses", which will hold the sum of all expenses in the "expenses" array. You can calculate the sum before creating the updateData HashMap and include it in the HashMap.

    Here's how you can integrate the "totalExpenses" field into the existing code snippet:

    // ...
    val mutableNames = names.toMutableList()
    val mutableQuantities = quantities.toMutableList()
    val mutableExpenses = expenses.toMutableList()
    
    // ...
    
    // Calculate the total expenses
    val totalExpenses = mutableExpenses.sum()
    
    val updateData: Map<String, Any> = hashMapOf(
        "name" to mutableNames,
        "quantity" to mutableQuantities,
        "expenses" to mutableExpenses,
        "totalExpenses" to totalExpenses
    )
    
    docRef.update(updateData)
        .addOnSuccessListener {
            Log.d("TAG", "Document updated successfully")
        }
        .addOnFailureListener { exception ->
            Log.e("TAG", "Error updating document", exception)
        }
    

    With this update, the document will include a new field named "totalExpenses", which will hold the sum of all expenses in the "expenses" array. The sum() function calculates the total expenses using the updated values in the mutableExpenses list.