The final version for lede-gui (the phone app for device registration)
[iot2.git] / others / lede-gui / src / main / java / com / example / lede2 / ApplicationWithRelations.java
diff --git a/others/lede-gui/src/main/java/com/example/lede2/ApplicationWithRelations.java b/others/lede-gui/src/main/java/com/example/lede2/ApplicationWithRelations.java
new file mode 100644 (file)
index 0000000..30c533c
--- /dev/null
@@ -0,0 +1,443 @@
+package com.example.lede2;\r
+\r
+import android.app.ProgressDialog;\r
+import android.content.Context;\r
+import android.support.design.widget.Snackbar;\r
+import android.support.v7.app.AppCompatActivity;\r
+import android.util.Log;\r
+import android.util.Pair;\r
+import android.util.SparseBooleanArray;\r
+import android.view.View;\r
+import android.widget.ArrayAdapter;\r
+import android.widget.Button;\r
+import android.widget.ListView;\r
+import android.widget.Spinner;\r
+import android.widget.Toast;\r
+\r
+import com.jcraft.jsch.HASH;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Properties;\r
+import java.util.Scanner;\r
+import java.util.Set;\r
+\r
+\r
+/**\r
+ * Created by Brian on 4/27/2018.\r
+ */\r
+\r
+public class ApplicationWithRelations extends AppCompatActivity  implements View.OnClickListener {\r
+    protected HashMap<String, ArrayList<String>> addedSetList; //list of sets that is currently being added and their values\r
+    protected int numFields;\r
+    protected Properties prop;\r
+    protected HashMap<String, HashSet<Pair<String, String>>> addedRelations;\r
+    protected HashMap<String, HashSet<String>> addedIndependentSets;\r
+    protected Context context;\r
+    protected HashMap<String, Pair<String, String>> relations;\r
+    protected HashMap<String, String> setHashMap;\r
+    protected Spinner relationNameSpinner;\r
+    protected Spinner relationLeftSpinner;\r
+    protected Spinner relationRightSpinner;\r
+    protected Spinner setOrRelationSpinner;\r
+    protected Button addRelationButton;\r
+    protected Button doneRelationButton;\r
+    protected Button deleteRelationButton;\r
+    protected HashMap<String, String> independentSetList;\r
+    protected ArrayList<String> independentSetNames;\r
+    protected boolean hasIndependentSets;\r
+    protected boolean hasRelations;\r
+    ArrayList addedRelationsArrayList;\r
+    ProgressDialog dialog;\r
+    protected Scanner scanner;\r
+    ArrayAdapter adapter;\r
+    ListView addRelationsListView;\r
+    protected HashSet<String> applicationSetList; //list of all sets that should be used\r
+\r
+\r
+\r
+\r
+    protected void deleteFromSet(String device){\r
+        Set<String> keyset = addedSetList.keySet();\r
+        for(String s: keyset){\r
+            ArrayList<String> tempSet =  addedSetList.get(s);\r
+            tempSet.remove(device);\r
+        }\r
+    }\r
+\r
+    protected void addSSHResultsToConfig(List<String> results, String filename) {\r
+        ConfigFileIO.writeToNewFile(filename,"", this );\r
+        File dir = getFilesDir();\r
+        File file = new File(dir, filename);\r
+        file.delete();\r
+        for (int i = 0; i < results.size(); i++) {\r
+            ConfigFileIO.writeToFile(filename, results.get(i), this);\r
+        }\r
+    }\r
+\r
+    protected void callSSHCommandAddComm(){\r
+        //default already in bin/installer  (RELATION)\r
+        String installCommPatternCommand = "";\r
+        for(int i = 0; i < numFields; i++){\r
+            if(prop.getProperty("FIELD_TYPE_" + i).equals("IoTRelation")){\r
+                String writeToRelConfigFileCommand = "";\r
+                writeToRelConfigFileCommand += this.getString(R.string.changeToSQLConfigFileLocation);\r
+\r
+                String filename = prop.getProperty("FIELD_CONFIG_FILENAME_"+i);\r
+                HashSet<Pair<String,String>> tempSet =  addedRelations.get(prop.getProperty("FIELD_" + i));\r
+\r
+                //insert roomCameraReal.config writing\r
+                writeToRelConfigFileCommand += "echo \"" + "SELECT RELATION FROM\n"+\r
+                        "FIRST\n" +\r
+                        prop.getProperty("FIELD_CLASS_0_" + i) + "\n" +\r
+                        "OTHER\n" +\r
+                        prop.getProperty("FIELD_CLASS_1_" + i) + "\n" +\r
+                        "WHERE\n"; //need to add where clauses for each case\r
+                int counter = 0;\r
+                //iterates through all of the added relations under the current relationName\r
+                //ex all relations under roomCameraRel\r
+                for(Pair<String, String> pair: tempSet){\r
+                    int size = tempSet.size();\r
+                    Scanner scanner = new Scanner(pair.first);\r
+                    String typeFirst = scanner.next();\r
+                    String idFirst = scanner.next();\r
+                    typeFirst += idFirst;\r
+                    scanner = new Scanner(pair.second);\r
+                    String typeSecond = scanner.next();\r
+                    String idSecond = scanner.next();\r
+                    typeSecond += idSecond;\r
+\r
+                    writeToRelConfigFileCommand += "(TYPE_SOURCE='" + typeFirst + "' AND TYPE_DESTINATION='" + typeSecond + "')";\r
+\r
+\r
+                    installCommPatternCommand += this.getString(R.string.changeToCommConfigFileLocation) + "echo \"" + idFirst + " " + typeFirst + "\n" +\r
+                            idSecond + " " + typeSecond + "\n" +\r
+                            "WRITE\" > " + filename + ";" +\r
+                            "java -cp .:..:/usr/share/java/* iotinstaller.IoTInstaller -install_comm " + filename + ";" +\r
+                            "rm " + filename + ";";\r
+\r
+                    //if this is the last item, finish it by writing it into file\r
+                    if(counter == size-1){\r
+                        writeToRelConfigFileCommand += "\n;\" > " + prop.getProperty("FIELD_" + i) + ".config; \n";\r
+                        installCommPatternCommand = writeToRelConfigFileCommand + installCommPatternCommand;\r
+                        System.out.println("COMM"  + installCommPatternCommand);\r
+                    }\r
+\r
+                    //if it is not the last item, concatenate or and continue\r
+                    else{\r
+                        writeToRelConfigFileCommand += "\nOR\n";\r
+                        System.out.println(installCommPatternCommand);\r
+                    }\r
+\r
+                    SSH_MySQL ssh_mySQL = new SSH_MySQL();\r
+                    List<String> results = new ArrayList<>();\r
+                    try {\r
+                        ssh_mySQL.execute(installCommPatternCommand);\r
+                        Thread.sleep(1000);//To execute asyntask in ssh object, we have to sleep main thread\r
+                        results = ssh_mySQL.getResultLines();\r
+                        while(results.size() == 0){\r
+                            Thread.sleep(500);\r
+                            results = ssh_mySQL.getResultLines();\r
+                            System.out.println(results);\r
+                        }\r
+                        System.out.println(results);\r
+                    } catch (Exception e) {\r
+                        Log.d("Sleep exception", "exception at getSetsAndRelations");\r
+                    }\r
+                    installCommPatternCommand = "";\r
+                    counter++;\r
+                }\r
+\r
+            }\r
+        }\r
+    }\r
+\r
+\r
+    protected HashMap<String, ArrayList<String>> createSetList(String filename){\r
+        HashMap<String, ArrayList<String>> setListHashMap = new HashMap<>();\r
+        String setData = ConfigFileIO.readFromFile(filename, context);\r
+        Scanner scanner = new Scanner(setData);\r
+        while (scanner.hasNextLine()){\r
+            String temp = scanner.nextLine();\r
+            if(temp.equals("START")){\r
+                String setName = scanner.nextLine();\r
+                temp = scanner.nextLine();\r
+                ArrayList<String> availableDevices = new ArrayList<>();\r
+                while (!temp.equals("END")){\r
+                    availableDevices.add(temp);\r
+                    temp = scanner.nextLine();\r
+                }\r
+                setListHashMap.put(setName, availableDevices);\r
+            }\r
+        }\r
+        return setListHashMap;\r
+    }\r
+\r
+\r
+    //relationofTwoItems comes in form of ex: RoomSmart,LightBulbSmart. Splits them by commma and adds them to hashmap\r
+    protected void addPair(String name, String relationOfTwoItems){\r
+        String firstItem = relationOfTwoItems.substring(0, relationOfTwoItems.indexOf(","));\r
+        String secondItem = relationOfTwoItems.substring(relationOfTwoItems.indexOf(",")+1, relationOfTwoItems.length());\r
+        Pair<String, String> pair = new Pair<>(firstItem, secondItem);\r
+        relations.put(name,pair);\r
+    }\r
+\r
+    protected ArrayList<String> removeDuplicates(ArrayList<String> list){\r
+        HashSet<String> set = new HashSet<>();\r
+        set.addAll(list);\r
+        ArrayList<String> noDups = new ArrayList<>();\r
+        noDups.addAll(set);\r
+        return noDups;\r
+    }\r
+    protected String generateSQLQuery(String setName, ArrayList<String> listOfDevices){\r
+        String query = "";\r
+        query = "SELECT * FROM\n" +\r
+                setName + "\n" +\r
+                "WHERE\n";\r
+        for(int i = 0; i < listOfDevices.size(); i++){\r
+            Scanner scanner = new Scanner(listOfDevices.get(i));\r
+            String type = scanner.next();\r
+            String id = scanner.next();\r
+            query += "(TYPE='" + type + "' AND ID='" + id + "')";\r
+            if(i == listOfDevices.size() -1){\r
+                query +="\n;";\r
+            }\r
+            else{\r
+                query += "\nOR\n";\r
+            }\r
+        }\r
+        return query;\r
+    }\r
+\r
+    protected String generateSSHCommandRelation(){\r
+        String command = "";\r
+        //move to directory where the sql file should be located  (SET)\r
+        command += this.getString(R.string.changeToSQLConfigFileLocation);\r
+        //go through all sets, and find their set type.\r
+        Set<String> keySet = setHashMap.keySet();\r
+        for(String s: keySet){\r
+            String setType = setHashMap.get(s);\r
+            ArrayList<String> list = addedSetList.get(setType);\r
+            list = removeDuplicates(list);\r
+            command += "echo \"" + generateSQLQuery(setType, list) + "\" > " + s + ".config" + ";";\r
+        }\r
+\r
+        keySet = addedIndependentSets.keySet();\r
+        for(String s:keySet){\r
+            String setType = independentSetList.get(s);\r
+            ArrayList<String> list = new ArrayList<>();\r
+            HashSet<String> set = addedIndependentSets.get(s);\r
+            list.addAll(set);\r
+            command += "echo \"" + generateSQLQuery(setType, list) + "\" > " + s + ".config" + ";";\r
+        }\r
+\r
+        return command;\r
+    }\r
+\r
+    @Override\r
+    public void onClick(View view) {\r
+        if(view == addRelationButton){\r
+            if(setOrRelationSpinner.getSelectedItem().toString().equals("RELATIONS")) {\r
+                //adding the user selected relation into a relationset\r
+                String leftValue = relationLeftSpinner.getSelectedItem().toString();\r
+                String rightValue = relationRightSpinner.getSelectedItem().toString();\r
+                Pair<String, String> pair = new Pair<>(leftValue, rightValue);\r
+                if ((addedRelations.get(relationNameSpinner.getSelectedItem().toString())) == null) {\r
+                    HashSet<Pair<String, String>> tempSet = new HashSet<>();\r
+                    tempSet.add(pair);\r
+                    addedRelations.put(relationNameSpinner.getSelectedItem().toString(), tempSet);\r
+                    adapter.notifyDataSetChanged();\r
+                } else {\r
+                    (addedRelations.get(relationNameSpinner.getSelectedItem().toString())).add(pair);\r
+                    adapter.notifyDataSetChanged();\r
+                }\r
+\r
+                //adding selected Objects into their respective sets\r
+                String relationName = relationNameSpinner.getSelectedItem().toString();\r
+                //get the left hand side of the generic selected relation\r
+                // ex: IoTRelation<RoomSmart, CameraSmart> roomCameraRel, get "RoomSmart"\r
+                Pair<String, String> tempPair = relations.get(relationName);\r
+                ArrayList<String> tempArrayList = addedSetList.get(tempPair.first);\r
+                //add the selected Left Value to RoomSmart set\r
+                if (tempArrayList == null) {\r
+                    tempArrayList = new ArrayList<>();\r
+                    tempArrayList.add(leftValue);\r
+                    addedSetList.put(tempPair.first, tempArrayList);\r
+                } else {\r
+                    tempArrayList.add(leftValue);\r
+                    addedSetList.put(tempPair.first, tempArrayList);\r
+                }\r
+\r
+                //repeat for the right side\r
+                tempArrayList = addedSetList.get(tempPair.second);\r
+                //ex: add to the selected Right Value CameraSmart set\r
+                if (tempArrayList == null) {\r
+                    tempArrayList = new ArrayList<>();\r
+                    tempArrayList.add(rightValue);\r
+                    addedSetList.put(tempPair.second, tempArrayList);\r
+                } else {\r
+                    tempArrayList.add(rightValue);\r
+                    addedSetList.put(tempPair.second, tempArrayList);\r
+                }\r
+                addedRelationsArrayList = new ArrayList<>();\r
+                Set<String> relationTypes = addedRelations.keySet();\r
+                for (String s : relationTypes) {\r
+                    for (Pair<String, String> temp : addedRelations.get(s)) {\r
+                        addedRelationsArrayList.add(temp.first + " " + temp.second);\r
+                    }\r
+                }\r
+                if(hasIndependentSets){\r
+                    Set<String> keys= addedIndependentSets.keySet();\r
+                    for (String s : keys) {\r
+                        for (String temp : addedIndependentSets.get(s)) {\r
+                            addedRelationsArrayList.add(temp);\r
+                        }\r
+                    }\r
+                    adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_multiple_choice, addedRelationsArrayList);\r
+                    addRelationsListView.setAdapter(adapter);\r
+                }\r
+                else {\r
+                    adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_multiple_choice, addedRelationsArrayList);\r
+                    addRelationsListView.setAdapter(adapter);\r
+                }\r
+\r
+            }\r
+            else {\r
+                //user is adding to independent sets (sets that are not part of a relation)\r
+                String leftValue = relationLeftSpinner.getSelectedItem().toString();\r
+                if ((addedIndependentSets.get(relationNameSpinner.getSelectedItem().toString())) == null) {\r
+                    HashSet<String> tempSet = new HashSet<>();\r
+                    tempSet.add(leftValue);\r
+                    addedIndependentSets.put(relationNameSpinner.getSelectedItem().toString(), tempSet);\r
+                    adapter.notifyDataSetChanged();\r
+                } else {\r
+                    (addedIndependentSets.get(relationNameSpinner.getSelectedItem().toString())).add(leftValue);\r
+                    adapter.notifyDataSetChanged();\r
+                }\r
+                addedRelationsArrayList = new ArrayList<>();\r
+                Set<String> relationTypes = addedRelations.keySet();\r
+                for (String s : relationTypes) {\r
+                    for (Pair<String, String> temp : addedRelations.get(s)) {\r
+                        addedRelationsArrayList.add(temp.first + " " + temp.second);\r
+                    }\r
+                }\r
+                Set<String> keys= addedIndependentSets.keySet();\r
+                for (String s : keys) {\r
+                    for (String temp : addedIndependentSets.get(s)) {\r
+                        addedRelationsArrayList.add(temp);\r
+                    }\r
+                }\r
+                adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_multiple_choice, addedRelationsArrayList);\r
+                addRelationsListView.setAdapter(adapter);\r
+\r
+            }\r
+        }\r
+\r
+        if(view == doneRelationButton){\r
+\r
+            boolean allSetsHaveEntry = true;\r
+            for(String s: applicationSetList){\r
+                ArrayList<String> list = addedSetList.get(s);\r
+                if(list== null || list.size() == 0){\r
+                    allSetsHaveEntry = false;\r
+                    System.out.println("NOT ALL RELATIONS HAVE ENTRIES");\r
+                    Toast t = Toast.makeText(ApplicationWithRelations.this, "Insufficient Entries",Toast.LENGTH_SHORT);\r
+                    t.show();\r
+                    continue;\r
+                }\r
+            }\r
+            if(hasIndependentSets) {\r
+                for (int i = 0; i < independentSetNames.size(); i++) {\r
+                    if (addedIndependentSets.get(independentSetNames.get(i)) == null ||\r
+                            (addedIndependentSets.get(independentSetNames.get(i))).size() == 0) {\r
+                        allSetsHaveEntry = false;\r
+                        System.out.println("NOT ALL SETS HAVE ENTRIES");\r
+                        continue;\r
+                    }\r
+                }\r
+            }\r
+            System.out.println("all sets have entry" + allSetsHaveEntry);\r
+            if(allSetsHaveEntry){\r
+\r
+                //the ssh execution is within the following command. Add comm patterns to database\r
+                callSSHCommandAddComm();\r
+\r
+                //adding relations and their derived sets, add to localconfig/mysql files\r
+                String command = generateSSHCommandRelation();\r
+                //System.out.println(command)\r
+                SSH_MySQL addConfigFiles = new SSH_MySQL();\r
+                addConfigFiles.execute(command);\r
+                try {\r
+                    Thread.sleep(1500);\r
+                    List<String> result = addConfigFiles.getResultLines();\r
+                    for (int i = 0; i < result.size(); i++) {\r
+                        System.out.println("result" + result.get(i));\r
+                    }\r
+                }\r
+                catch (Exception e){\r
+                    e.printStackTrace();\r
+                }\r
+\r
+\r
+\r
+\r
+                //add independent sets to their respective localconfig/mysql files\r
+                finish();\r
+            }\r
+\r
+        }\r
+        if (view == deleteRelationButton) {\r
+            //SparseBooleanArray's data is True or False\r
+            SparseBooleanArray checkedItems = addRelationsListView.getCheckedItemPositions();//to check which devices are checked in listview(check -> true, no check -> false)\r
+            int count = adapter.getCount();//number of items in listview\r
+            for (int i = count - 1; i >= 0; i--) {//scan from back\r
+                //i : index of IoT device which will be removed in tmp array\r
+                if (checkedItems.get(i)) {//if check\r
+                    System.out.println("delete relation: " + i);\r
+                    String selectedValue = (String)addRelationsListView.getItemAtPosition(i);\r
+                    scanner = new Scanner(selectedValue);\r
+                    String left = scanner.next() + " " + scanner.next();\r
+\r
+                    if(scanner.hasNext()) {\r
+                        String right = scanner.next() + " " + scanner.next();\r
+                        Pair<String, String> pair = new Pair<>(left, right);\r
+                        //remove from user-selected relations\r
+                        Set<String> relationTypes = addedRelations.keySet();\r
+                        for (String s : relationTypes) {\r
+                            if (addedRelations.get(s).contains(pair)) {\r
+                                addedRelations.get(s).remove(pair);\r
+                            }\r
+                        }\r
+                        //remove from displaying on the check list\r
+                        String temp = pair.first + " " + pair.second;\r
+                        addedRelationsArrayList.remove(temp);\r
+                        adapter.notifyDataSetChanged();\r
+                        //remove from addedsetlist\r
+                        deleteFromSet(left);\r
+                        deleteFromSet(right);\r
+                    }\r
+                    else{\r
+                        System.out.println("only has one word");\r
+                        Set<String> keySet = addedIndependentSets.keySet();\r
+                        for(String s: keySet){\r
+                            HashSet<String> tempSet =  addedIndependentSets.get(s);\r
+                            tempSet.remove(left);\r
+                        }\r
+                        addedRelationsArrayList.remove(left);\r
+                        adapter.notifyDataSetChanged();\r
+                    }\r
+                }\r
+            }\r
+\r
+            //update\r
+            adapter.notifyDataSetChanged();\r
+            //delete checked mark in listview\r
+            addRelationsListView.clearChoices();\r
+\r
+        }\r
+\r
+    }\r
+}\r