diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 9e9d742..76acd1f 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/Deliverables/R3/README.md b/Deliverables/R3/README.md new file mode 100644 index 0000000..6a43c01 --- /dev/null +++ b/Deliverables/R3/README.md @@ -0,0 +1,35 @@ +###### Παραδοτέο R3 + +> Έχει γίνει και μερική υλοποίηση του παραδοτέου με Guice (dependency injection) και Mockito στο branch R3-Guice. + +# Εισαγωγή + +Στο παρών έγγραφο θα αναλυθούν η λογική της αρχιτεκτονικής και τα διαγράμματα ακολουθίας για την λογική πεδίου. Στο τέλος θα αναρτηθεί coverage report για τον κώδικα. + +# Αρχιτεκτονική Λογισμικού + +## Διάγραμμα πακέτων + +![](package-diagram.png) + +Τα πακέτα builder, configurations, lab, people, schedule ανήκουν στο domain model. Το πακέτα dao & memorydao προσφέρουν πρόσβαση στα δεδομένα μας (Direct Memory Access). Τέλος έχουμε εφαρμόσει το μοντέλο model view presenter για τα fragments που θα δημιουργηθούν στο R4. + +# Στατική Όψη Λογικής Πεδίου + +Παρακάτω παρουσιάζεται διαγραμματικά η στατική όψη της λογικής πεδίου. + +![](static-view.png) + +# Διαγράμματα Ακολουθίας Δυναμικής Όψης Λογικής Πεδίου + +Παρακάτω παρουσιάζεται διαγραμματικά το διάγραμμα ακολουθίας για το signIn ενός χρήστη. + +![](signin-seq.png) + +# Υλοποίηση Λογικής Πεδίου & Testing + +Η υλοποίηση της λογικής πεδίου και το testing μπορούν να βρεθούν στο Android Studio Project που έχει αναρτηθεί. + +# Coverage Reports + +Το report για το coverage του κώδικα μπορεί να δημιουργηθεί μέσα από το Android Studio (Analyze -> Generate Coverage Report), αλλά συνοπτικά είχαμε 95% coverage στις κλάσεις, 99% coverage στις μεθόδους & 96% coverage στις γραμμές. diff --git a/Deliverables/R3/package-diagram_old.png b/Deliverables/R3/package-diagram_old.png new file mode 100644 index 0000000..25d8739 Binary files /dev/null and b/Deliverables/R3/package-diagram_old.png differ diff --git a/Deliverables/R3/static-view.png b/Deliverables/R3/static-view.png index 9fed921..7e0373d 100644 Binary files a/Deliverables/R3/static-view.png and b/Deliverables/R3/static-view.png differ diff --git a/Deliverables/R4/class-diagram.png b/Deliverables/R4/class-diagram.png new file mode 100644 index 0000000..b27c778 Binary files /dev/null and b/Deliverables/R4/class-diagram.png differ diff --git a/Deliverables/R4/configuration-save.png b/Deliverables/R4/configuration-save.png new file mode 100644 index 0000000..2cec1a7 Binary files /dev/null and b/Deliverables/R4/configuration-save.png differ diff --git a/Deliverables/R4/history-read.png b/Deliverables/R4/history-read.png new file mode 100644 index 0000000..b40ab2f Binary files /dev/null and b/Deliverables/R4/history-read.png differ diff --git a/Deliverables/R4/sign-in.png b/Deliverables/R4/sign-in.png new file mode 100644 index 0000000..dc5a81b Binary files /dev/null and b/Deliverables/R4/sign-in.png differ diff --git a/README.md b/README.md index ca7acb7..f4bf2f1 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,35 @@ -###### Παραδοτέο R3 - -> Έχει γίνει και μερική υλοποίηση του παραδοτέου με Guice (dependency injection) και Mockito στο branch R3-Guice. +###### Παραδοτέο R4 # Εισαγωγή -Στο παρών έγγραφο θα αναλυθούν η λογική της αρχιτεκτονικής και τα διαγράμματα ακολουθίας για την λογική πεδίου. Στο τέλος θα αναρτηθεί coverage report για τον κώδικα. +Στο παρών έγγραφο θα αναλυθεί η τελική υλοποίηση της εφαρμογής στο Android framework. # Αρχιτεκτονική Λογισμικού -## Διάγραμμα πακέτων +## Διάγραμμα κλάσεων -![](Deliverables/R3/package-diagram.png) +Παρακάτων παρουσιάζεται το διάγραμμα κλάσεων που εμπεριέχει όλο το project. Δυστυχώς είναι δυσανάγνωστο από το αρχείο της Markdown. -Τα πακέτα builder, configurations, lab, people, schedule ανήκουν στο domain model. Το πακέτα dao & memorydao προσφέρουν πρόσβαση στα δεδομένα μας (Direct Memory Access). Τέλος έχουμε εφαρμόσει το μοντέλο model view presenter για τα fragments που θα δημιουργηθούν στο R4. +![](Deliverables/R4/class-diagram.png) -# Στατική Όψη Λογικής Πεδίου +## Διάγραμμα πακέτων -Παρακάτω παρουσιάζεται διαγραμματικά η στατική όψη της λογικής πεδίου. +![](Deliverables/R3/package-diagram.png) -![](Deliverables/R3/static-view.png) +Τα πακέτα builder, configurations, lab, people, schedule ανήκουν στο domain model. +Το πακέτα dao & memorydao προσφέρουν πρόσβαση στα δεδομένα μας (Direct Memory Access). +Το πακέτο services περιέχει τις υπηρεσίες (services), που εδώ λειτουργούν ως presenters. -# Διαγράμματα Ακολουθίας Δυναμικής Όψης Λογικής Πεδίου +## Παραδείγματα λειτουργειών -Παρακάτω παρουσιάζεται διαγραμματικά το διάγραμμα ακολουθίας για το signIn ενός χρήστη. +Ακολουθούν τα sequence diagrams για την συνδεση, και ως παράδειγμα την ανάγνωση ιστορικού ανά terminal και την αποθήκευση νέου configuration. -![](Deliverables/R3/signin-seq.png) +![](Deliverables/R4/sign-in.png) -# Υλοποίηση Λογικής Πεδίου & Testing +![](Deliverables/R4/history-read.png) -Η υλοποίηση της λογικής πεδίου και το testing μπορούν να βρεθούν στο Android Studio Project που έχει αναρτηθεί. +![](Deliverables/R4/configuration-save.png) # Coverage Reports -Το report για το coverage του κώδικα μπορεί να δημιουργηθεί μέσα από το Android Studio (Analyze -> Generate Coverage Report), αλλά συνοπτικά είχαμε 95% coverage στις κλάσεις, 99% coverage στις μεθόδους & 96% coverage στις γραμμές. +Το report για το coverage του κώδικα μπορεί να δημιουργηθεί μέσα από το Android Studio (Analyze -> Generate Coverage Report). Συνοπτικά με τις κλάσεις των activities και των fragments που απαιτούν Android tests είχαμε 46% συνολικό coverage, 50% στα services/presenters (λόγω μεθόδων Android) και 100% σε DAO και μοντέλο πεδίου. diff --git a/app/build.gradle b/app/build.gradle index 5f08f1d..6ecf2dc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdkVersion 28 defaultConfig { applicationId "gr.aueb.se.labadministration" - minSdkVersion 22 + minSdkVersion 26 targetSdkVersion 28 versionCode 1 versionName "1.0" @@ -24,7 +24,11 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'com.google.android.material:material:1.1.0-alpha06' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.preference:preference:1.1.0-alpha05' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/app/src/androidTest/java/gr/aueb/se/labadministration/ExampleInstrumentedTest.java b/app/src/androidTest/java/gr/aueb/se/labadministration/ExampleInstrumentedTest.java deleted file mode 100644 index 3a472c2..0000000 --- a/app/src/androidTest/java/gr/aueb/se/labadministration/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package gr.aueb.se.labadministration; - -import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("gr.aueb.se.labadministration", appContext.getPackageName()); - } -} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9bc54ab..b6b1a2d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,48 @@ + - + android:theme="@style/AppTheme"> + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png new file mode 100644 index 0000000..2bd4472 Binary files /dev/null and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/gr/aueb/se/labadministration/activities/MainActivity.java b/app/src/main/java/gr/aueb/se/labadministration/activities/MainActivity.java new file mode 100644 index 0000000..f3856ea --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/activities/MainActivity.java @@ -0,0 +1,91 @@ +package gr.aueb.se.labadministration.activities; + +import android.content.SharedPreferences; +import android.os.Bundle; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import com.google.android.material.bottomnavigation.BottomNavigationView; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.fragments.ConfigurationFragment; +import gr.aueb.se.labadministration.fragments.HistoryFragment; +import gr.aueb.se.labadministration.fragments.LabFragment; + +/** + * The main activity of the application, redirects to sign in activity + */ +public class MainActivity extends AppCompatActivity { + + /** + * The bottom navigation bar, in case of admin the nav_history and nav_configuration options appear + */ + private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener + = item -> { + switch (item.getItemId()) { + case R.id.nav_history: + switchFragment(new HistoryFragment()); + break; + case R.id.nav_labs: + switchFragment(new LabFragment()); + break; + case R.id.nav_configuration: + switchFragment(new ConfigurationFragment()); + break; + default: return false; + } + return true; + }; + + /** + * Fragment transaction method + * @param fragment to switch to + */ + public void switchFragment(Fragment fragment) { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + transaction.replace(R.id.fragment_view, fragment); + transaction.commit(); + } + + /** + * Default Android Methods + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + makeActionBar(); + BottomNavigationView navView = findViewById(R.id.nav_view); + navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); + + if (getIntent().getBooleanExtra("configurations", false)) { + navView.setSelectedItemId(R.id.nav_configuration); + switchFragment(new ConfigurationFragment()); + } else { + switchFragment(new LabFragment()); + } + + SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("user", MODE_PRIVATE); + boolean administrator = sharedPreferences.getBoolean("administrator", false); + + navView.getMenu().findItem(R.id.nav_history).setVisible(administrator); + navView.getMenu().findItem(R.id.nav_configuration).setVisible(administrator); + } + + @Override + public void onBackPressed() { + getSupportFragmentManager().popBackStack(); + } + + // makes the action bar. + private void makeActionBar() { + ActionBar actionBar = getSupportActionBar(); + actionBar.setIcon(R.drawable.app_icon); + actionBar.setDisplayUseLogoEnabled(true);// display app_icon. + actionBar.setDisplayShowHomeEnabled(true);// display back button. + } + +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/activities/NewConfigurationActivity.java b/app/src/main/java/gr/aueb/se/labadministration/activities/NewConfigurationActivity.java new file mode 100644 index 0000000..05b8215 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/activities/NewConfigurationActivity.java @@ -0,0 +1,144 @@ +package gr.aueb.se.labadministration.activities; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import java.util.ArrayList; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.configurations.SoftwarePackage; +import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import gr.aueb.se.labadministration.fragments.AddSoftwarePackageFragment; +import gr.aueb.se.labadministration.services.ConfigurationService; + +/** + * The activity that registers a new terminal configuration + */ +public class NewConfigurationActivity extends AppCompatActivity { + + private EditText hardwareConfName, os, graphics, processor, storage, ram; + private ArrayList softwarePackageArrayList = new ArrayList<>(); + + private ConfigurationService service; + + /** + * Method that initiates connection with configuration service + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + NewConfigurationActivity.this.service = ((ConfigurationService.ConfigurationServiceBinder) service).getService(); + } + @Override + public void onServiceDisconnected(ComponentName name) { + NewConfigurationActivity.this.service = null; + } + }; + + /** + * Default Android Method + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_configuration); + bindService(new Intent(this, ConfigurationService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + Button addButton = findViewById(R.id.addConfigurationButton); + Button addSoftwareButton = findViewById(R.id.addSoftwareButton); + hardwareConfName = findViewById(R.id.hardwareConfigurationName); + + os = findViewById(R.id.os); + graphics = findViewById(R.id.graphicsCard); + processor = findViewById(R.id.processor); + storage = findViewById(R.id.storageCapacity); + ram = findViewById(R.id.ram); + + Spinner spinner = findViewById(R.id.softwarePackages); + ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, softwarePackageArrayList); + spinner.setAdapter(adapter); + + addSoftwareButton.setOnClickListener(e -> { + new AddSoftwarePackageFragment(pack -> { + softwarePackageArrayList.add(pack); + adapter.notifyDataSetChanged(); + }).show(getSupportFragmentManager(), "add"); + }); + + addButton.setOnClickListener(e->{ + if(!hardwareInputValidation()){return;} + + TerminalConfiguration configuration = new TerminalConfiguration( + processor.getText().toString(), + graphics.getText().toString(), + Integer.parseInt(storage.getText().toString()), + Integer.parseInt(ram.getText().toString()), + os.getText().toString(), + hardwareConfName.getText().toString() + ); + softwarePackageArrayList.forEach(configuration::addSoftwarePackage); + service.saveConfiguration(configuration); + + startActivity(new Intent(getApplicationContext(), MainActivity.class) + .putExtra("configurations", true)); + finish(); + Toast.makeText(getApplicationContext(), "Configuration addition success", Toast.LENGTH_SHORT).show(); + }); + + TerminalConfiguration terminalConfiguration = (TerminalConfiguration) getIntent().getSerializableExtra("configuration"); + if (terminalConfiguration != null) { + hardwareConfName.setEnabled(false); + hardwareConfName.setText(terminalConfiguration.getName()); + os.setText(terminalConfiguration.getOperatingSystem()); + graphics.setText(terminalConfiguration.getGraphicsCard()); + processor.setText(terminalConfiguration.getProcessor()); + storage.setText(String.valueOf(terminalConfiguration.getStorateCapacity())); + ram.setText(String.valueOf(terminalConfiguration.getTotalMemory())); + softwarePackageArrayList.clear(); + softwarePackageArrayList.addAll(terminalConfiguration.listSoftwarePackages()); + } + } + + /** + * Method that checks all the inputs for a new terminal configuration + * @return true or false + */ + private boolean hardwareInputValidation(){ + if(!storage.getText().toString().trim().matches("\\d+") || + !ram.getText().toString().trim().matches("\\d+") ){ + Toast.makeText(getApplicationContext(), "Error: Storage and RAM should be integers", Toast.LENGTH_SHORT).show(); + return false; + } + if(processor.getText().toString().trim().equals("") || + graphics.getText().toString().trim().equals("") || + os.getText().toString().trim().equals("") || + hardwareConfName.getText().toString().trim().equals("")){ + Toast.makeText(getApplicationContext(), "Error: all fields are requiered", Toast.LENGTH_SHORT).show(); + return false; + } + return true; + } + + + /** + * Default Android Method + * Unbinds services in order to avoid leakages + */ + @Override + protected void onStop() { + super.onStop(); + stopService(getIntent()); + unbindService(serviceConnection); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/activities/NewTerminalActivity.java b/app/src/main/java/gr/aueb/se/labadministration/activities/NewTerminalActivity.java new file mode 100644 index 0000000..1d28868 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/activities/NewTerminalActivity.java @@ -0,0 +1,202 @@ +package gr.aueb.se.labadministration.activities; + +import androidx.appcompat.app.AppCompatActivity; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.Toast; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.builder.TerminalBuilder; +import gr.aueb.se.labadministration.domain.configurations.SoftwarePackage; +import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import gr.aueb.se.labadministration.domain.lab.Laboratory; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.services.ConfigurationService; +import gr.aueb.se.labadministration.services.LabService; + +/** + * The activity that registers a new Terminal + */ +public class NewTerminalActivity extends AppCompatActivity { + + private LabService labService; + private ConfigurationService configurationService; + private EditText term_name, term_hostname, term_ip, term_posx, term_posy; + private Spinner term_config, lab_select; + private TerminalConfiguration configuration; + private Laboratory laboratory; + private Button term_sumbit; + private List labs; + private Collection configurations; + private ArrayAdapter adapter; + private ArrayAdapter adapter1; + private int posx, posy; + + /** + * Method that initiates connection with lab service + */ + private ServiceConnection labServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + NewTerminalActivity.this.labService = ((LabService.LabServiceBinder) iBinder).getService(); + + adapter = new ArrayAdapter<>(getApplication(), android.R.layout.simple_list_item_1, labService.listLabs()); + lab_select.setAdapter(adapter); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + NewTerminalActivity.this.labService = null; + } + }; + + /** + * Method that initiates connection with configuration service + */ + private ServiceConnection configurationServiceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + NewTerminalActivity.this.configurationService = ((ConfigurationService.ConfigurationServiceBinder) iBinder).getService(); + + adapter1 = new ArrayAdapter<>(getApplication(), android.R.layout.simple_list_item_1, new ArrayList<>(configurationService.listAllConfigs())); + term_config.setAdapter(adapter1); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + NewTerminalActivity.this.configurationService = null; + } + }; + + /** + * Default Android Method + * After submission the method closes the activity + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_terminal); + + bindService(new Intent(this, LabService.class), labServiceConnection, Context.BIND_AUTO_CREATE); + bindService(new Intent(this, ConfigurationService.class), configurationServiceConnection, Context.BIND_AUTO_CREATE); + + term_name = findViewById(R.id.terminal_name); + term_hostname = findViewById(R.id.terminal_hostname); + term_ip = findViewById(R.id.ip_address); + term_posx = findViewById(R.id.term_posx); + term_posy = findViewById(R.id.term_posy); + term_config = findViewById(R.id.terminal_config); + lab_select = findViewById(R.id.lab_selection); + term_sumbit = findViewById(R.id.terminal_submit); + + term_sumbit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + posx = Integer.parseInt(term_posx.getText().toString()); + posy = Integer.parseInt(term_posy.getText().toString()); + + configuration = (TerminalConfiguration) term_config.getSelectedItem(); + + laboratory = (Laboratory) lab_select.getSelectedItem(); + + if(terminalInputValidation()){ + InetAddress ip = null; + try { + ip = InetAddress.getByName(term_ip.getText().toString()); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + + Terminal terminal = new TerminalBuilder() + .setName(term_name.getText().toString()) + .setHostname(term_hostname.getText().toString()) + .setIpAddress(ip) + .setPositionX(posx) + .setPositionY(posy) + .setConfiguration(configuration) + .createTerminal(); + + terminal.setStatus(Terminal.TerminalStatus.AVAILABLE); + + labService.saveTerminal(laboratory, terminal); + + Toast.makeText(getApplicationContext(), "Successful Addition", Toast.LENGTH_LONG).show(); + + finish(); + } + } + }); + + } + + /** + * Method that checks if all the data inputs are correct + * @return true or false based on the data given + */ + private boolean terminalInputValidation() { + + if(posx <= 0 || posy <= 0){ + Toast.makeText(this, "Error: Terminal coordinates must be positive", Toast.LENGTH_LONG).show(); + return false; + } + + if(configuration == null){ + Toast.makeText(this, "Error: Please select a configuration", Toast.LENGTH_LONG).show(); + return false; + } + + if(laboratory == null){ + Toast.makeText(this, "Error: Please select a laboratory", Toast.LENGTH_LONG).show(); + return false; + } + + InetAddress ip = null; + try { + ip = InetAddress.getByName(term_ip.getText().toString()); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + + Terminal terminal = new TerminalBuilder() + .setName(term_name.getText().toString()) + .setHostname(term_hostname.getText().toString()) + .setIpAddress(ip) + .setPositionX(posx) + .setPositionY(posy) + .setConfiguration(configuration) + .createTerminal(); + if(terminal != null)return true; + + Toast.makeText(this, "Error: Unknown error", Toast.LENGTH_LONG).show(); + return false; + } + + /** + * Default Android Method + * Unbinds services in order to avoid leakages + */ + @Override + protected void onStop() { + super.onStop(); + stopService(getIntent()); + unbindService(labServiceConnection); + unbindService(configurationServiceConnection); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/activities/SignInActivity.java b/app/src/main/java/gr/aueb/se/labadministration/activities/SignInActivity.java new file mode 100644 index 0000000..d385276 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/activities/SignInActivity.java @@ -0,0 +1,102 @@ +package gr.aueb.se.labadministration.activities; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.IBinder; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.services.SignInService; +import gr.aueb.se.labadministration.utilities.RequestResult; + +/** + * The activity that handles the sign in process + */ +public class SignInActivity extends AppCompatActivity { + + private EditText usernameEditText; + private EditText passwordEditText; + private Button submitButton; + + private SignInService service; + + /** + * The method that initiates connection with the sign in service + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + SignInActivity.this.service = ((SignInService.SignInBinder) service).getService(); + } + @Override + public void onServiceDisconnected(ComponentName name) { + SignInActivity.this.service = null; + } + }; + + /** + * Default Android Method + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_sign_in); + bindService(new Intent(this, SignInService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + // Initialization of activity components + usernameEditText = findViewById(R.id.usernameEditText); + passwordEditText = findViewById(R.id.passwordEditText); + submitButton = findViewById(R.id.submitButton); + + passwordEditText.setOnEditorActionListener((view, id, button) -> submitButton.callOnClick()); + submitButton.setOnClickListener(view -> { + RequestResult requestResult = this.service.signInRequest(getUsername(), getPassword()); + if (requestResult.isSuccessful()) { + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + + SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences("user", MODE_PRIVATE); + sharedPreferences.edit().putBoolean("administrator", requestResult.isAdministrator()).apply(); + + startActivity(intent); + } else { + Toast.makeText(getApplicationContext(), requestResult.getReasonOfFailure(), Toast.LENGTH_SHORT).show(); + } + }); + } + + /** + * Method that extracts the data from the EditText + * @return string or null + */ + public String getUsername() { + return (usernameEditText == null) ? null : usernameEditText.getText().toString(); + } + + /** + * Method that extracts the data from the EditText + * @return string or null + */ + public String getPassword() { + return (passwordEditText == null) ? null : passwordEditText.getText().toString(); + } + + /** + * Default Android Method + * Unbinds services in order to avoid leakages + */ + @Override + protected void onStop() { + super.onStop(); + stopService(getIntent()); + unbindService(serviceConnection); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/dao/LaboratoryDAO.java b/app/src/main/java/gr/aueb/se/labadministration/dao/LaboratoryDAO.java index 98cdb95..3447d8b 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/dao/LaboratoryDAO.java +++ b/app/src/main/java/gr/aueb/se/labadministration/dao/LaboratoryDAO.java @@ -1,16 +1,43 @@ package gr.aueb.se.labadministration.dao; import gr.aueb.se.labadministration.domain.lab.Laboratory; +import gr.aueb.se.labadministration.domain.lab.Terminal; import java.util.ArrayList; +/** + * The interface the communicates with databases for the laboratories + */ public interface LaboratoryDAO { + /** + * The method that saves a lab to the database + * @param laboratory + */ void save(Laboratory laboratory); + /** + * The method that removes a lab from the database + * @param laboratory + */ void remove(Laboratory laboratory); + /** + * The method that adds a terminal to the lab + * @param terminal + */ + void addTerminal(Laboratory laboratory, Terminal terminal); + + /** + * The method that searches if a lab exists with that name + * @param name + * @return a lab or null + */ Laboratory findByName(String name); + /** + * The method that returns all the labs + * @return + */ ArrayList listAll(); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/dao/SoftwarePackageDAO.java b/app/src/main/java/gr/aueb/se/labadministration/dao/SoftwarePackageDAO.java index 1fad590..acc1d3c 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/dao/SoftwarePackageDAO.java +++ b/app/src/main/java/gr/aueb/se/labadministration/dao/SoftwarePackageDAO.java @@ -4,14 +4,34 @@ import java.util.ArrayList; +/** + * The interface the communicates with databases for the software packages + */ public interface SoftwarePackageDAO { + /** + * The method that saves a software package to the database + * @param softwarePackage + */ void save(SoftwarePackage softwarePackage); + /** + * The method that removes a software package from the database + * @param softwarePackage + */ void delete(SoftwarePackage softwarePackage); + /** + * The method that searches if a software package exists with that name + * @param softPackageName + * @return software package or null + */ SoftwarePackage findByName(String softPackageName); + /** + * The method that returns all the software packages + * @return + */ ArrayList listAll(); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalConfigurationDAO.java b/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalConfigurationDAO.java index 4d56241..dc5f0a9 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalConfigurationDAO.java +++ b/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalConfigurationDAO.java @@ -3,15 +3,36 @@ import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; import java.util.ArrayList; +import java.util.Collection; +/** + * The interface the communicates with databases for the terminal configurations + */ public interface TerminalConfigurationDAO { + /** + * The method that saves a terminal configuration to the database + * @param configuration + */ void save(TerminalConfiguration configuration); + /** + * The method that removes a terminal configuration from the database + * @param configuration + */ void delete(TerminalConfiguration configuration); + /** + * The method that searches if a terminal configuration exists with that name + * @param configurationName + * @return terminal configuration or null + */ TerminalConfiguration findByName(String configurationName); - ArrayList listAll(); + /** + * The method that returns all terminal configurations + * @return + */ + Collection listAll(); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalDAO.java b/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalDAO.java index ad08fcb..0f8ce6f 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalDAO.java +++ b/app/src/main/java/gr/aueb/se/labadministration/dao/TerminalDAO.java @@ -1,22 +1,53 @@ package gr.aueb.se.labadministration.dao; +import gr.aueb.se.labadministration.domain.lab.Laboratory; import gr.aueb.se.labadministration.domain.lab.Terminal; import java.net.InetAddress; import java.util.ArrayList; +/** + * The interface the communicates with databases for the terminals + */ public interface TerminalDAO { + /** + * The method that saves a terminal to the database + * @param terminal + */ void save(Terminal terminal); + /** + * The method that removes a terminal from the database + * @param terminal + */ void delete(Terminal terminal); + /** + * The method that searches if a terminal exists with that name + * @param terminalName + * @return terminal or null + */ Terminal findByName(String terminalName); + /** + * The method that searches if a terminal exists with that ip + * @param inetAddress + * @return terminal or null + */ Terminal findByIP(InetAddress inetAddress); + /** + * The method that saves changes to the terminal + * @param terminal + * @param status of the terminal that moment + */ void updateStatus(Terminal terminal, Terminal.TerminalStatus status); + /** + * Returns all terminals + * @return + */ ArrayList listAll(); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/dao/UserDAO.java b/app/src/main/java/gr/aueb/se/labadministration/dao/UserDAO.java index 0cd4a7b..c3958cb 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/dao/UserDAO.java +++ b/app/src/main/java/gr/aueb/se/labadministration/dao/UserDAO.java @@ -6,15 +6,46 @@ import java.util.ArrayList; +/** + * The interface the communicates with databases for the users + */ public interface UserDAO { + /** + * The method that saves users to the database + * @param user + */ void save(User user); + /** + * The method that removes users from a database + * @param user + */ void delete(User user); + /** + * The method that finds users by their username + * @param username + * @return user or null + */ User find(String username); + /** + * The method that returns all users + * @return + */ + ArrayList listUsers(); + + /** + * The method that returns the data from which terminals have been used by the user + * @param user + * @return user or null + */ ArrayList listAllSessions(User user); + /** + * The method that returns all the administrators + * @return all users that are admins + */ ArrayList listAllAdministrators(); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalBuilder.java b/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalBuilder.java index d6586e7..433436d 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalBuilder.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalBuilder.java @@ -1,10 +1,15 @@ package gr.aueb.se.labadministration.domain.builder; import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import gr.aueb.se.labadministration.domain.lab.Laboratory; import gr.aueb.se.labadministration.domain.lab.Terminal; import java.net.InetAddress; +import java.util.Objects; +/** + * The class that builds a terminal + */ public class TerminalBuilder { private String name; @@ -44,11 +49,15 @@ public TerminalBuilder setConfiguration(TerminalConfiguration configuration) { return this; } + /** + * The method that creates a terminal + * @return Terminal + */ public Terminal createTerminal() { - if (name == null) return null; - if (hostname == null) return null; - if (ipAddress == null) return null; - if (configuration == null) return null; + Objects.requireNonNull(name, "name is null"); + Objects.requireNonNull(hostname, "hostname is null"); + Objects.requireNonNull(ipAddress, "ipAddress is null"); + Objects.requireNonNull(configuration, "configuration is null"); return new Terminal(name, hostname, ipAddress, positionX, positionY, configuration); } } \ No newline at end of file diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalConfigurationBuilder.java b/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalConfigurationBuilder.java index 97138f1..fd7daba 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalConfigurationBuilder.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/builder/TerminalConfigurationBuilder.java @@ -2,6 +2,9 @@ import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +/** + * The class that builds a TerminalConfiguration + */ public class TerminalConfigurationBuilder { private String processor; private String graphicsCard; @@ -40,6 +43,10 @@ public TerminalConfigurationBuilder setName(String name) { return this; } + /** + * The method that creates a terminal configuration + * @return TerminalConfiguration + */ public TerminalConfiguration createTerminalConfiguration() { if (processor == null) return null; if (operatingSystem == null) return null; diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/SoftwarePackage.java b/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/SoftwarePackage.java index df7d1f9..4270e26 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/SoftwarePackage.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/SoftwarePackage.java @@ -1,17 +1,33 @@ package gr.aueb.se.labadministration.domain.configurations; -public class SoftwarePackage { +import androidx.annotation.NonNull; + +import java.io.Serializable; + +/** + * The class that defines a SoftwarePackage + */ +public class SoftwarePackage implements Serializable { private String name; private String installationCommand; private String uninstallCommand; + /** + * Constructor + * @param name of package + * @param installationCommand of package + * @param uninstallCommand of package + */ public SoftwarePackage(String name, String installationCommand, String uninstallCommand) { this.name = name; this.installationCommand = installationCommand; this.uninstallCommand = uninstallCommand; } + /** + * Setters & Getters + */ public String getName() { return name; } @@ -35,4 +51,10 @@ public String getUninstallCommand() { public void setUninstallCommand(String uninstallCommand) { this.uninstallCommand = uninstallCommand; } + + @NonNull + @Override + public String toString() { + return getName(); + } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/TerminalConfiguration.java b/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/TerminalConfiguration.java index 1c7974b..f5c41ce 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/TerminalConfiguration.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/configurations/TerminalConfiguration.java @@ -1,8 +1,16 @@ package gr.aueb.se.labadministration.domain.configurations; +import androidx.annotation.NonNull; + +import java.io.Serializable; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; -public class TerminalConfiguration { +/** + * The class that defines a TerminalConfiguration + */ +public class TerminalConfiguration implements Serializable { private String processor; private String graphicsCard; @@ -12,6 +20,15 @@ public class TerminalConfiguration { private String name; private ArrayList softwarePackages; + /** + * Constructor + * @param processor of terminal + * @param graphicsCard of terminal + * @param storateCapacity of terminal + * @param totalMemory of terminal + * @param operatingSystem of terminal + * @param name of terminal + */ public TerminalConfiguration(String processor, String graphicsCard, int storateCapacity, int totalMemory, String operatingSystem, String name) { this.processor = processor; this.graphicsCard = graphicsCard; @@ -22,6 +39,10 @@ public TerminalConfiguration(String processor, String graphicsCard, int storateC this.softwarePackages = new ArrayList(); } + /** + * Copy constructor + * @param terminalConfiguration to copy from + */ public TerminalConfiguration(TerminalConfiguration terminalConfiguration) { this.processor = terminalConfiguration.processor; this.graphicsCard = terminalConfiguration.graphicsCard; @@ -32,6 +53,9 @@ public TerminalConfiguration(TerminalConfiguration terminalConfiguration) { this.softwarePackages = terminalConfiguration.softwarePackages; } + /** + * Setters & Getters + */ public String getProcessor() { return processor; } @@ -56,11 +80,35 @@ public String getName() { return name; } + /** + * Method that adds a software package + * @param softwarePackage to add + * @return result as boolean + */ public boolean addSoftwarePackage(SoftwarePackage softwarePackage){ return this.softwarePackages.add(softwarePackage); } + /** + * Method that removes a software package + * @param softwarePackage to remove + * @return result as boolean + */ public boolean removeSoftwarePackage(SoftwarePackage softwarePackage){ return this.softwarePackages.remove(softwarePackage); } + + /** + * Method that returns a list of the software packages that the terminal configuration includes + * @return list with SoftwarePackage + */ + public List listSoftwarePackages() { + return Collections.unmodifiableList(softwarePackages); + } + + @NonNull + @Override + public String toString() { + return getName(); + } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Laboratory.java b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Laboratory.java index 39dee45..a7482d1 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Laboratory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Laboratory.java @@ -1,11 +1,14 @@ package gr.aueb.se.labadministration.domain.lab; +import androidx.annotation.NonNull; + import gr.aueb.se.labadministration.domain.people.Administrator; import gr.aueb.se.labadministration.domain.schedule.DaySchedule; +import java.io.Serializable; import java.util.ArrayList; -public class Laboratory { +public class Laboratory implements Serializable { private String name; private String location; @@ -104,4 +107,9 @@ public boolean removeAdministrator(Administrator administrator){ return this.administrators.remove(administrator); } + @NonNull + @Override + public String toString() { + return getName(); + } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Session.java b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Session.java index 97dc143..487558e 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Session.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Session.java @@ -2,9 +2,15 @@ import gr.aueb.se.labadministration.domain.people.User; +import java.io.Serializable; +import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; -public class Session { +/** + * The class that defines a Session + */ +public class Session implements Serializable { public enum SessionStatus{STARTING, STARTED, FINISHED, INTERRUPTED}; @@ -14,14 +20,28 @@ public enum SessionStatus{STARTING, STARTED, FINISHED, INTERRUPTED}; private Date startTime; private Date endTime; + /** + * Constructor + * @param terminal of session + * @param user of session + * @param status of session + * @param startTime of session + * @param endTime of session + */ public Session(Terminal terminal, User user, SessionStatus status, Date startTime, Date endTime) { this.terminal = terminal; this.user = user; this.status = status; this.startTime = startTime; this.endTime = endTime; + + this.user.registerSession(this); + this.terminal.registerSession(this); } + /** + * Setters & Getters + */ public Terminal getTerminal() { return terminal; } @@ -46,7 +66,11 @@ public Date getEndTime() { return endTime; } - public boolean updateSessions(){ - return this.user.registerSession(this) && this.terminal.registerSession(this); + @Override + public String toString() { + return String.format("%s (%s): %s", + terminal.getName(), + new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).format(startTime), + user.getUsername()); } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Terminal.java b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Terminal.java index 5db8c58..5ef98fc 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Terminal.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/lab/Terminal.java @@ -2,10 +2,14 @@ import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import java.io.Serializable; import java.net.InetAddress; import java.util.ArrayList; -public class Terminal { +/** + * The class that defines a Terminal + */ +public class Terminal implements Serializable { public enum TerminalStatus{OFFLINE, AVAILABLE, IN_USE, IN_MAINTENANCE}; @@ -18,6 +22,15 @@ public enum TerminalStatus{OFFLINE, AVAILABLE, IN_USE, IN_MAINTENANCE}; private TerminalConfiguration configuration; private ArrayList sessions; + /** + * Constructor + * @param name of terminal + * @param hostname of terminal + * @param ipAddress of terminal + * @param positionX of terminal + * @param positionY of terminal + * @param configuration of terminal + */ public Terminal(String name, String hostname, InetAddress ipAddress, int positionX, int positionY, TerminalConfiguration configuration) { this.name = name; this.hostname = hostname; @@ -28,6 +41,9 @@ public Terminal(String name, String hostname, InetAddress ipAddress, int positio this.sessions = new ArrayList(); } + /** + * Setters & Getters + */ public String getName() { return name; } @@ -84,7 +100,19 @@ public void setConfiguration(TerminalConfiguration configuration) { this.configuration = configuration; } + /** + * The method that registers a session + * @param session to add + */ public boolean registerSession(Session session){ return this.sessions.add(session); } + + /** + * The method that returns all sessions associated with this terminal + * @return a list of sessions + */ + public ArrayList getSessions(){ + return sessions; + } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/people/Administrator.java b/app/src/main/java/gr/aueb/se/labadministration/domain/people/Administrator.java index e0b411f..490a8a8 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/people/Administrator.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/people/Administrator.java @@ -1,6 +1,11 @@ package gr.aueb.se.labadministration.domain.people; -public class Administrator extends User { +import java.io.Serializable; + +/** + * The class that defines an administrator + */ +public class Administrator extends User implements Serializable { public Administrator(String username, String passwordHash, String affiliation) { super(username, passwordHash, affiliation); diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/people/User.java b/app/src/main/java/gr/aueb/se/labadministration/domain/people/User.java index f16398b..84b7e04 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/people/User.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/people/User.java @@ -4,15 +4,25 @@ import gr.aueb.se.labadministration.utilities.Password; import gr.aueb.se.labadministration.utilities.RequestResult; +import java.io.Serializable; import java.util.ArrayList; -public class User { +/** + * The class that defines a User + */ +public class User implements Serializable { private String username; private String passwordHash; private String affiliation; private ArrayList sessions; + /** + * Constructor + * @param username of user + * @param passwordHash of user + * @param affiliation of user + */ public User(String username, String passwordHash, String affiliation) { this.username = username; this.passwordHash = passwordHash; @@ -20,6 +30,9 @@ public User(String username, String passwordHash, String affiliation) { this.sessions = new ArrayList<>(); } + /** + * Setters & Getters + */ public String getUsername() { return username; } @@ -32,23 +45,36 @@ public String getAffiliation() { return affiliation; } + /** + * The method that registers a session + * @param session to add + */ public boolean registerSession(Session session){ return this.sessions.add(session); } + /** + * The method that returns a list of sessions associated with this user + * @return a list of sessions + */ public ArrayList listSessions(){ return this.sessions; } + /** + * Method that performs sign in of user + * @param password in plaintext + * @return a RequestResult that indicates success or failure of sign in + */ public RequestResult signIn(String password) { - if (password == null) return new RequestResult(false, "Password cannot be empty"); + if (password == null) return new RequestResult(false, false, "Password cannot be empty"); if (username != null && !username.startsWith("p3") && affiliation.equals("student")) - return new RequestResult(false, "You are not allowed to login"); + return new RequestResult(false, false, "You are not allowed to login"); String hashedPassword = Password.hash(password); if(hashedPassword.equals(getPasswordHash())){ - return new RequestResult(true, "Success"); + return new RequestResult(true, !affiliation.equals("student"), "Success"); } - return new RequestResult(false, "Wrong password"); + return new RequestResult(false, false,"Wrong password"); } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/DaySchedule.java b/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/DaySchedule.java index e3adcdc..792af0f 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/DaySchedule.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/DaySchedule.java @@ -1,34 +1,61 @@ package gr.aueb.se.labadministration.domain.schedule; +import java.io.Serializable; import java.util.ArrayList; -public class DaySchedule { +/** + * The class that defines a DaySchedule + */ +public class DaySchedule implements Serializable { private int day; private ArrayList slots; + /** + * Constructor + * @param day of schedule + */ public DaySchedule(int day) { this.day = day; this.slots = new ArrayList(); } + /** + * Copy constructor + * @param daySchedule to copy + */ public DaySchedule(DaySchedule daySchedule) { this.day = daySchedule.day; this.slots = daySchedule.slots; } + /** + * Setters & Getters + */ public int getDay() { return day; } + /** + * Method that returns all slots of this DaySchedule + * @return a list of ScheduleSlot + */ public ArrayList getSlots() { return slots; } + /** + * Method that adds a Slot + * @param slot + */ public boolean addSlot(ScheduleSlot slot){ return this.slots.add(slot); } + /** + * Method that removes a Slot + * @param slot + */ public boolean removeSlot(ScheduleSlot slot){ return this.slots.remove(slot); } diff --git a/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/ScheduleSlot.java b/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/ScheduleSlot.java index 26f6c3e..00bd20c 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/ScheduleSlot.java +++ b/app/src/main/java/gr/aueb/se/labadministration/domain/schedule/ScheduleSlot.java @@ -2,6 +2,9 @@ import java.util.Date; +/** + * The class that defines a ScheduleSlot + */ public class ScheduleSlot { private Date start; @@ -9,6 +12,13 @@ public class ScheduleSlot { private String lesson; private String teacher; + /** + * Constructor + * @param start of slot + * @param end of slot + * @param lesson of slot + * @param teacher of slot + */ public ScheduleSlot(Date start, Date end, String lesson, String teacher) { this.start = start; this.end = end; @@ -16,6 +26,9 @@ public ScheduleSlot(Date start, Date end, String lesson, String teacher) { this.teacher = teacher; } + /** + * Setters & Getters + */ public Date getStart() { return start; } diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/.gitkeep b/app/src/main/java/gr/aueb/se/labadministration/fragments/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/AddSoftwarePackageFragment.java b/app/src/main/java/gr/aueb/se/labadministration/fragments/AddSoftwarePackageFragment.java new file mode 100644 index 0000000..d85ac0f --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/fragments/AddSoftwarePackageFragment.java @@ -0,0 +1,87 @@ +package gr.aueb.se.labadministration.fragments; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; + +import java.util.function.Consumer; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.configurations.SoftwarePackage; + +/** + * The fragment that registers a software package + */ +public class AddSoftwarePackageFragment extends DialogFragment { + + private Consumer softwarePackageConsumer; + + private EditText softwareConfName; + private EditText creationCommand; + private EditText deleteCommand; + + /** + * Default Constructor + */ + public AddSoftwarePackageFragment() { + } + + /** + * Constructor + * @param softwarePackageConsumer consumer for software packages + */ + public AddSoftwarePackageFragment(Consumer softwarePackageConsumer) { + this.softwarePackageConsumer = softwarePackageConsumer; + } + + /** + * Method that checkes the data given + * @return true or false based on the data given + */ + private boolean softwareInputValidation(){ + if( softwareConfName.getText().toString().trim().equals("") || + creationCommand.getText().toString().trim().equals("") || + deleteCommand.getText().toString().trim().equals("")){ + Toast.makeText(getContext(), "Error: all fields are requiered", Toast.LENGTH_SHORT).show(); + return false; + } + return true; + } + + /** + * Default Android Methods + */ + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_add_software_package, container, false); + } + + @Override + public void onStart() { + super.onStart(); + + softwareConfName = getView().findViewById(R.id.softwareConfigurationName); + creationCommand = getView().findViewById(R.id.creationCommand); + deleteCommand = getView().findViewById(R.id.deleteCommand); + + Button addButton = getView().findViewById(R.id.addConfigurationButton); + addButton.setOnClickListener(event -> { + if (softwareInputValidation() && softwarePackageConsumer != null) { + softwarePackageConsumer.accept(new SoftwarePackage( + softwareConfName.getText().toString(), + creationCommand.getText().toString(), + deleteCommand.getText().toString())); + dismiss(); + } + }); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/ConfigurationFragment.java b/app/src/main/java/gr/aueb/se/labadministration/fragments/ConfigurationFragment.java new file mode 100644 index 0000000..06d3524 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/fragments/ConfigurationFragment.java @@ -0,0 +1,90 @@ +package gr.aueb.se.labadministration.fragments; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import java.util.ArrayList; +import java.util.List; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.activities.NewConfigurationActivity; +import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import gr.aueb.se.labadministration.services.ConfigurationService; + +/** + * The fragment that registers a TerminalConfiguration + */ +public class ConfigurationFragment extends Fragment { + + private List configurationList = new ArrayList<>(); + private ArrayAdapter adapter; + + private ConfigurationService service; + + /** + * Method that initiates connection with configuration service + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + ConfigurationFragment.this.service = ((ConfigurationService.ConfigurationServiceBinder) service).getService(); + configurationList.clear(); + configurationList.addAll(ConfigurationFragment.this.service.listAllConfigs()); + adapter.notifyDataSetChanged(); + } + @Override + public void onServiceDisconnected(ComponentName name) { + ConfigurationFragment.this.service = null; + } + }; + + /** + * Default Android Methods + */ + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_configuration, container, false); + } + + @Override + public void onStart() { + super.onStart(); + + adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, configurationList); + ListView listView = getView().findViewById(R.id.configurations); + listView.setAdapter(adapter); + + getActivity().bindService(new Intent(getContext(), ConfigurationService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + listView.setOnItemClickListener((parent, view, position, id) -> { + TerminalConfiguration configuration = configurationList.get(position); + Intent intent = new Intent(getContext(), NewConfigurationActivity.class); + intent.putExtra("configuration", configuration); + startActivity(intent); + }); + + FloatingActionButton button = getView().findViewById(R.id.fab); + button.setOnClickListener(click -> { + startActivity(new Intent(getContext(), NewConfigurationActivity.class)); + }); + } + +} + + diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/HistoryFragment.java b/app/src/main/java/gr/aueb/se/labadministration/fragments/HistoryFragment.java new file mode 100644 index 0000000..282ff2e --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/fragments/HistoryFragment.java @@ -0,0 +1,110 @@ +package gr.aueb.se.labadministration.fragments; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.RadioGroup; +import android.widget.SearchView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import java.util.ArrayList; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.lab.Session; +import gr.aueb.se.labadministration.services.HistoryService; + +/** + * The fragment that presents the history of a user or a terminal + */ +public class HistoryFragment extends Fragment { + + private SearchView historySearchView; + private ListView resultListView; + + private ArrayAdapter adapter; + private ArrayList resultsArrayList = new ArrayList<>(); + private RadioGroup radioGroup; + + private HistoryService service; + + /** + * Method that initiates connection with history service + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + HistoryFragment.this.service = ((HistoryService.HistoryServiceBinder) service).getService(); + } + @Override + public void onServiceDisconnected(ComponentName name) { + HistoryFragment.this.service = null; + } + }; + + /** + * Default Android Methods + */ + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_history, container, false); + } + + @Override + public void onStart() { + super.onStart(); + getActivity().bindService(new Intent(getContext(), HistoryService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + historySearchView = getView().findViewById(R.id.historySearchView); + resultListView = getView().findViewById(R.id.resultListView); + radioGroup = getView().findViewById(R.id.radioGroup); + + adapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1 , resultsArrayList); + resultListView.setAdapter(adapter); + + historySearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + resultsArrayList.clear(); + if (s.isEmpty()) { + resultsArrayList.addAll(service.allSessions()); + adapter.notifyDataSetChanged(); + return true; + } + switch (radioGroup.getCheckedRadioButtonId()) { + case R.id.userRadioButton: { + resultsArrayList.addAll(service.findSessionsByUser(s)); + adapter.notifyDataSetChanged(); + break; + } + case R.id.computerRadioButton: { + resultsArrayList.addAll(service.findSessionsByComputer(s)); + adapter.notifyDataSetChanged(); + break; + } + default: return false; + } + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + + historySearchView.setIconified(false); + historySearchView.clearFocus(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/LabFragment.java b/app/src/main/java/gr/aueb/se/labadministration/fragments/LabFragment.java new file mode 100644 index 0000000..0d7f6b1 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/fragments/LabFragment.java @@ -0,0 +1,157 @@ +package gr.aueb.se.labadministration.fragments; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ExpandableListView; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.google.android.material.floatingactionbutton.FloatingActionButton; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.activities.NewConfigurationActivity; +import gr.aueb.se.labadministration.activities.NewTerminalActivity; +import gr.aueb.se.labadministration.dao.LaboratoryDAO; +import gr.aueb.se.labadministration.domain.lab.Laboratory; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.domain.schedule.DaySchedule; +import gr.aueb.se.labadministration.memorydao.LaboratoryDAOMemory; +import gr.aueb.se.labadministration.services.LabService; +import gr.aueb.se.labadministration.utilities.ExpandableListAdapter; + +import static android.content.Context.MODE_PRIVATE; + +/** + * The fragment that presents lab info + */ +public class LabFragment extends Fragment { + + private ExpandableListView listViewComputers, listViewShedules; + private ExpandableListAdapter listAdapterComputers, listAdapterShedules; + private List listComputers, listShedules; + private HashMap> listHashMapComputers, listHashMapShedules; + private RadioGroup labsRadioGroup; + + private LabService service; + + /** + * Method that initiates connection with lab service + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + LabFragment.this.service = ((LabService.LabServiceBinder) iBinder).getService(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + LabFragment.this.service = null; + } + }; + + /** + * Default Android Methods + */ + @Override + public void onStart() { + super.onStart(); + getActivity().bindService(new Intent(getContext(), LabService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + listComputers = new ArrayList<>(); + listHashMapComputers = new HashMap<>(); + + listShedules= new ArrayList<>(); + listHashMapShedules = new HashMap<>(); + + labsRadioGroup = getView().findViewById(R.id.labsRadioGroup); + labsRadioGroup.setOnCheckedChangeListener( (group, checkedId) -> + { + RadioButton checkedRadioButton = group.findViewById(checkedId); + boolean isChecked = checkedRadioButton.isChecked(); + if (isChecked) + { + updateComputers(checkedRadioButton.getText().toString()); + updateShedule(checkedRadioButton.getText().toString()); + listAdapterComputers.notifyDataSetChanged(); + listAdapterShedules.notifyDataSetChanged(); + } + }); + + updateComputers("Lab1"); + updateShedule("Lab1"); + + // Computer List Configuration + listViewComputers = getView().findViewById(R.id.labListComputers); + listAdapterComputers = new ExpandableListAdapter(getContext(), listComputers, listHashMapComputers); + listViewComputers.setAdapter(listAdapterComputers); + + // Computer List Configuration + listViewShedules = getView().findViewById(R.id.labListShedules); + listAdapterShedules = new ExpandableListAdapter(getContext(), listShedules, listHashMapShedules); + listViewShedules.setAdapter(listAdapterShedules); + + labsRadioGroup.check(R.id.lab1RadioButton); + + SharedPreferences sharedPreferences = getContext().getSharedPreferences("user", MODE_PRIVATE); + boolean administrator = sharedPreferences.getBoolean("administrator", false); + + FloatingActionButton button = getView().findViewById(R.id.fab); + button.setVisibility(administrator ? View.VISIBLE : View.GONE); + button.setOnClickListener(click -> { + startActivity(new Intent(getContext(), NewTerminalActivity.class)); + }); + } + + + void updateComputers(String labName){ + + listComputers.clear(); + listHashMapComputers.clear(); + + LaboratoryDAO laboratoryDAO = new LaboratoryDAOMemory(); + Laboratory lab = laboratoryDAO.findByName(labName); + listComputers.add(lab.getName()); + List terminals = new ArrayList<>(); + for(Terminal t: lab.getTerminals()){ + terminals.add(t.getName()); + } + listHashMapComputers.put(lab.getName(), terminals); + } + + + void updateShedule(String labName){ + listShedules.clear(); + listHashMapShedules.clear(); + + LaboratoryDAO laboratoryDAO = new LaboratoryDAOMemory(); + Laboratory lab = laboratoryDAO.findByName(labName); + listShedules.add(lab.getName()); + ArrayList schedules = new ArrayList<>(); + for(DaySchedule s: lab.getSchedule()){ + schedules.add("Day: " + s.getDay()); + } + listHashMapShedules.put(lab.getName(), schedules); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_lab, container, false); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/fragments/TerminalFragment.java b/app/src/main/java/gr/aueb/se/labadministration/fragments/TerminalFragment.java new file mode 100644 index 0000000..739c35e --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/fragments/TerminalFragment.java @@ -0,0 +1,152 @@ +package gr.aueb.se.labadministration.fragments; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.os.IBinder; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.services.LabService; + +import static android.content.Context.MODE_PRIVATE; + +/** + * The fragment that presents a terminal + */ +public class TerminalFragment extends DialogFragment { + + private LabService labService; + private String terminalName; + private TextView terminalTitle, terminalStatus; + private Terminal terminal; + private ImageButton shutdown, restart, signout; + + /** + * Method that initiates connection with lab service + * Also hides information and capabilities in case of normal user login + */ + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + TerminalFragment.this.labService = ((LabService.LabServiceBinder) iBinder).getService(); + terminal = labService.findTerminal(terminalName); + + terminalTitle.setText(terminal.getName()); + terminalStatus.setText(terminal.getStatus().toString()); + + SharedPreferences sharedPreferences = getContext().getSharedPreferences("user", MODE_PRIVATE); + boolean administrator = sharedPreferences.getBoolean("administrator", false); + + if (!administrator) { + shutdown.setVisibility(View.GONE); + restart.setVisibility(View.GONE); + signout.setVisibility(View.GONE); + signout.setVisibility(View.GONE); + return; + } + + if(labService.isTerminalOffline(terminal) || labService.isTerminalInMaintenance(terminal)){ + shutdown.setVisibility(View.GONE); + restart.setVisibility(View.GONE); + signout.setVisibility(View.GONE); + } + + if(labService.isTerminalInUse(terminal)){ + signout.setVisibility(View.VISIBLE); + } + else signout.setVisibility(View.GONE); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + TerminalFragment.this.labService = null; + } + }; + + /** + * Default Android Methods + */ + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + + Bundle bundle = this.getArguments(); + terminalName = bundle.getString("terminal_name"); + + return inflater.inflate(R.layout.fragment_terminal, container, false); + } + + @Override + public void onStart() { + super.onStart(); + getActivity().bindService(new Intent(getContext(), LabService.class), serviceConnection, Context.BIND_AUTO_CREATE); + + terminalTitle = getView().findViewById(R.id.terminal_name); + terminalStatus = getView().findViewById(R.id.terminal_status); + shutdown = getView().findViewById(R.id.terminal_shut_off); + restart = getView().findViewById(R.id.terminal_reboot); + signout = getView().findViewById(R.id.terminal_sign_out); + + shutdown.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + labService.terminalAction(terminalName, Terminal.TerminalStatus.OFFLINE); + + refresh(); + } + }); + + restart.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + labService.terminalAction(terminalName, Terminal.TerminalStatus.IN_MAINTENANCE); + + labService.terminalAction(terminalName, Terminal.TerminalStatus.AVAILABLE); + + refresh(); + } + }); + + signout.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + labService.terminalAction(terminalName, Terminal.TerminalStatus.AVAILABLE); + + refresh(); + } + }); + } + + /** + * Method that refreshes the fragment when + * an action is performed on a terminal + */ + private void refresh(){ + FragmentTransaction manager = getFragmentManager().beginTransaction(); + manager.detach(this); + TerminalFragment terminalFragment = new TerminalFragment(); + Bundle bundle = new Bundle(); + bundle.putString("terminal_name", terminalName); + terminalFragment.setArguments(bundle); + manager.add(terminalFragment, "Terminal"); + manager.commit(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/interfaces/SignInFragment.java b/app/src/main/java/gr/aueb/se/labadministration/interfaces/SignInFragment.java deleted file mode 100644 index de7c69f..0000000 --- a/app/src/main/java/gr/aueb/se/labadministration/interfaces/SignInFragment.java +++ /dev/null @@ -1,16 +0,0 @@ -package gr.aueb.se.labadministration.interfaces; - -import gr.aueb.se.labadministration.presenter.SignInPresenter; -import gr.aueb.se.labadministration.utilities.RequestResult; - -public interface SignInFragment { - - boolean getSuccess(); - String getFail(); - String getReasonOfFailure(); - void performSignIn(String username, String password); - void show(); - void hide(); - - void setSignInPresenter(SignInPresenter presenter); -} diff --git a/app/src/main/java/gr/aueb/se/labadministration/memorydao/LaboratoryDAOMemory.java b/app/src/main/java/gr/aueb/se/labadministration/memorydao/LaboratoryDAOMemory.java index 610277e..4d60b93 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/memorydao/LaboratoryDAOMemory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/memorydao/LaboratoryDAOMemory.java @@ -2,23 +2,69 @@ import gr.aueb.se.labadministration.dao.LaboratoryDAO; import gr.aueb.se.labadministration.domain.lab.Laboratory; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.domain.schedule.DaySchedule; import java.util.ArrayList; +import java.util.Arrays; +/** + * The interface the communicates with memory for the laboratories + */ public class LaboratoryDAOMemory implements LaboratoryDAO { protected static ArrayList laboratories = new ArrayList(); + static { + laboratories.add(new Laboratory("Lab1", "Aueb", true)); + laboratories.add(new Laboratory("Lab2", "Aueb", false)); + laboratories.add(new Laboratory("Lab3", "Aueb at Troy", true)); + + laboratories.get(0).setTerminals(TerminalDAOMemory.terminals); + laboratories.get(1).setTerminals(new ArrayList<>(TerminalDAOMemory.terminals.subList(0,2))); + laboratories.get(2).setTerminals(new ArrayList<>(TerminalDAOMemory.terminals.subList(1,3))); + + laboratories.get(0).setSchedule(new ArrayList<>(Arrays.asList(new DaySchedule(1), new DaySchedule(2)))); + laboratories.get(1).setSchedule(new ArrayList<>(Arrays.asList(new DaySchedule(4), new DaySchedule(3)))); + laboratories.get(2).setSchedule(new ArrayList<>(Arrays.asList(new DaySchedule(1), new DaySchedule(5)))); + } + + /** + * The method that saves a lab to the memory + * @param laboratory + */ @Override public void save(Laboratory laboratory) { laboratories.add(laboratory); } + /** + * The method that removes a lab from the memory + * @param laboratory + */ @Override public void remove(Laboratory laboratory) { laboratories.remove(laboratory); } + /** + * The method that adds a terminal to the lab + * @param terminal + */ + @Override + public void addTerminal(Laboratory laboratory, Terminal terminal) { + for (Laboratory lab : laboratories){ + if(lab.getName().equals(laboratory.getName())) { + lab.addTerminal(terminal); + } + } + } + + /** + * The method that searches if a lab exists with that name + * @param name + * @return a lab or null + */ @Override public Laboratory findByName(String name) { for (Laboratory lab : laboratories){ @@ -27,6 +73,10 @@ public Laboratory findByName(String name) { return null; } + /** + * The method that returns all the labs + * @return + */ @Override public ArrayList listAll() { return laboratories; diff --git a/app/src/main/java/gr/aueb/se/labadministration/memorydao/SoftwarePackageDAOMemory.java b/app/src/main/java/gr/aueb/se/labadministration/memorydao/SoftwarePackageDAOMemory.java index 3e61964..9d78789 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/memorydao/SoftwarePackageDAOMemory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/memorydao/SoftwarePackageDAOMemory.java @@ -5,20 +5,42 @@ import java.util.ArrayList; +/** + * The interface the communicates with memory for the software packages + */ public class SoftwarePackageDAOMemory implements SoftwarePackageDAO { protected static ArrayList softwarePackages = new ArrayList(); + static{ + softwarePackages.add(new SoftwarePackage("soft1", "make -i https://...", "rm -r /*")); + softwarePackages.add(new SoftwarePackage("soft2", "make -i https://...", "rm -r /*")); + softwarePackages.add(new SoftwarePackage("soft3", "make -i https://...", "rm -r /*")); + } + + /** + * The method that saves a software package to the memory + * @param softwarePackage + */ @Override public void save(SoftwarePackage softwarePackage) { softwarePackages.add(softwarePackage); } + /** + * The method that removes a software package from the memory + * @param softwarePackage + */ @Override public void delete(SoftwarePackage softwarePackage) { softwarePackages.remove(softwarePackage); } + /** + * The method that searches if a software package exists with that name + * @param softPackageName + * @return software package or null + */ @Override public SoftwarePackage findByName(String softPackageName) { for(SoftwarePackage sp : softwarePackages){ @@ -27,6 +49,10 @@ public SoftwarePackage findByName(String softPackageName) { return null; } + /** + * The method that returns all the software packages + * @return + */ @Override public ArrayList listAll() { return softwarePackages; diff --git a/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalConfigurationDAOMemory.java b/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalConfigurationDAOMemory.java index fc17a93..780755a 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalConfigurationDAOMemory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalConfigurationDAOMemory.java @@ -1,34 +1,75 @@ package gr.aueb.se.labadministration.memorydao; +import gr.aueb.se.labadministration.domain.builder.TerminalConfigurationBuilder; import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; import gr.aueb.se.labadministration.dao.TerminalConfigurationDAO; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +/** + * The interface the communicates with memory for the terminal configurations + */ public class TerminalConfigurationDAOMemory implements TerminalConfigurationDAO { - protected static ArrayList configurations = new ArrayList(); + protected static HashMap configurations = new HashMap<>(); + static { + configurations.put("CSLAB1", new TerminalConfigurationBuilder() + .setName("CSLAB1") + .setOperatingSystem("Windows 10") + .setProcessor("i7") + .setstorageCapacity(2014) + .setTotalMemory(2048) + .createTerminalConfiguration()); + configurations.put("CSLAB2", new TerminalConfigurationBuilder() + .setName("CSLAB2") + .setOperatingSystem("Ubuntu 16.04 LTS") + .setProcessor("i5") + .setstorageCapacity(2014) + .setTotalMemory(1024) + .createTerminalConfiguration()); + } + + /** + * The method that saves a terminal configuration to the memory + * @param configuration + */ @Override public void save(TerminalConfiguration configuration) { - configurations.add(configuration); + configurations.put(configuration.getName(), configuration); } + /** + * The method that removes a terminal configuration from the memory + * @param configuration + */ @Override public void delete(TerminalConfiguration configuration) { - configurations.remove(configuration); + configurations.remove(configuration.getName()); } + /** + * The method that searches if a terminal configuration exists with that name + * @param configurationName + * @return terminal configuration or null + */ @Override public TerminalConfiguration findByName(String configurationName) { - for(TerminalConfiguration conf : configurations){ + for(TerminalConfiguration conf : configurations.values()){ if(conf.getName().equalsIgnoreCase(configurationName)) return conf; } return null; } + /** + * The method that returns all terminal configurations + * @return + */ @Override - public ArrayList listAll() { - return configurations; + public Collection listAll() { + return configurations.values(); } } diff --git a/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalDAOMemory.java b/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalDAOMemory.java index 9ce014e..28aafdc 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalDAOMemory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/memorydao/TerminalDAOMemory.java @@ -1,25 +1,97 @@ package gr.aueb.se.labadministration.memorydao; +import android.content.ServiceConnection; + import gr.aueb.se.labadministration.dao.TerminalDAO; +import gr.aueb.se.labadministration.domain.builder.TerminalBuilder; +import gr.aueb.se.labadministration.domain.lab.Session; import gr.aueb.se.labadministration.domain.lab.Terminal; import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Date; +/** + * The interface the communicates with memory for the terminals + */ public class TerminalDAOMemory implements TerminalDAO { - protected static ArrayList terminals = new ArrayList(); + protected static ArrayList terminals = new ArrayList<>(); + + static { + try { + Terminal term1 = new TerminalBuilder() + .setHostname("cslab1-22") + .setName("CSLAB1-22") + .setPositionX(0) + .setPositionY(0) + .setIpAddress(InetAddress.getByName("172.16.1.22")) + .setConfiguration(TerminalConfigurationDAOMemory.configurations.get("CSLAB1")) + .createTerminal(); + Terminal term2 = new TerminalBuilder() + .setHostname("cslab1-23") + .setName("CSLAB1-23") + .setPositionX(1) + .setPositionY(0) + .setIpAddress(InetAddress.getByName("172.16.1.23")) + .setConfiguration(TerminalConfigurationDAOMemory.configurations.get("CSLAB1")) + .createTerminal(); + Terminal term3 = new TerminalBuilder() + .setHostname("cslab2-32") + .setName("CSLAB2-32") + .setPositionX(0) + .setPositionY(0) + .setIpAddress(InetAddress.getByName("172.16.2.32")) + .setConfiguration(TerminalConfigurationDAOMemory.configurations.get("CSLAB2")) + .createTerminal(); + Terminal term4 = new TerminalBuilder() + .setHostname("cslab2-33") + .setName("CSLAB2-33") + .setPositionX(1) + .setPositionY(0) + .setIpAddress(InetAddress.getByName("172.16.2.33")) + .setConfiguration(TerminalConfigurationDAOMemory.configurations.get("CSLAB2")) + .createTerminal(); + term1.setStatus(Terminal.TerminalStatus.AVAILABLE); + term2.setStatus(Terminal.TerminalStatus.IN_MAINTENANCE); + term3.setStatus(Terminal.TerminalStatus.IN_USE); + term4.setStatus(Terminal.TerminalStatus.OFFLINE); + terminals.add(term1); + terminals.add(term2); + terminals.add(term3); + terminals.add(term4); + } catch (UnknownHostException ignored) {} + } + + static { + // Register session. + new Session(terminals.get(0), UserDAOMemory.users.get(0), Session.SessionStatus.STARTED, new Date(), null); + } + /** + * The method that saves a terminal to the memory + * @param terminal + */ @Override public void save(Terminal terminal) { terminals.add(terminal); } + /** + * The method that removes a terminal from the memory + * @param terminal + */ @Override public void delete(Terminal terminal) { terminals.remove(terminal); } + /** + * The method that searches if a terminal exists with that name + * @param terminalName + * @return terminal or null + */ @Override public Terminal findByName(String terminalName) { for(Terminal terminal : terminals){ @@ -28,6 +100,11 @@ public Terminal findByName(String terminalName) { return null; } + /** + * The method that searches if a terminal exists with that ip + * @param inetAddress + * @return terminal or null + */ @Override public Terminal findByIP(InetAddress inetAddress) { for(Terminal terminal : terminals){ @@ -36,6 +113,11 @@ public Terminal findByIP(InetAddress inetAddress) { return null; } + /** + * The method that saves changes to the terminal + * @param terminal + * @param status of the terminal that moment + */ @Override public void updateStatus(Terminal terminal, Terminal.TerminalStatus status){ for(Terminal t : terminals){ @@ -43,6 +125,10 @@ public void updateStatus(Terminal terminal, Terminal.TerminalStatus status){ } } + /** + * Returns all terminals + * @return + */ @Override public ArrayList listAll() { return terminals; diff --git a/app/src/main/java/gr/aueb/se/labadministration/memorydao/UserDAOMemory.java b/app/src/main/java/gr/aueb/se/labadministration/memorydao/UserDAOMemory.java index 1a0d5c6..c5e5ce5 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/memorydao/UserDAOMemory.java +++ b/app/src/main/java/gr/aueb/se/labadministration/memorydao/UserDAOMemory.java @@ -4,23 +4,46 @@ import gr.aueb.se.labadministration.domain.lab.Session; import gr.aueb.se.labadministration.domain.people.Administrator; import gr.aueb.se.labadministration.domain.people.User; +import gr.aueb.se.labadministration.utilities.Password; import java.util.ArrayList; +/** + * The interface the communicates with memory for the users + */ public class UserDAOMemory implements UserDAO { - protected static ArrayList users = new ArrayList(); + protected static ArrayList users = new ArrayList<>(); + static { + users.add(new User("d2111111", "5E884898DA2847151D0E56F8DC6292773603DD6AABBDD62A11EF721D1542D8", "student")); + users.add(new User("p3160026", "5E884898DA2847151D0E56F8DC6292773603DD6AABBDD62A11EF721D1542D8", "student")); + users.add(new User("teacher", "5E884898DA2847151D0E56F8DC6292773603DD6AABBDD62A11EF721D1542D8", "teacher")); + } + + /** + * The method that saves users to the memory + * @param user + */ @Override public void save(User user) { users.add(user); } + /** + * The method that removes users from the memory + * @param user + */ @Override public void delete(User user) { users.remove(user); } + /** + * The method that finds users by their username + * @param username + * @return user or null + */ @Override public User find(String username) { for(User user : users){ @@ -29,6 +52,20 @@ public User find(String username) { return null; } + /** + * The method that returns all users + * @return + */ + @Override + public ArrayList listUsers() { + return users; + } + + /** + * The method that returns the data from which terminals have been used by the user + * @param user + * @return user or null + */ @Override public ArrayList listAllSessions(User user) { for(User u : users){ @@ -37,6 +74,10 @@ public ArrayList listAllSessions(User user) { return null; } + /** + * The method that returns all the administrators + * @return all users that are admins + */ @Override public ArrayList listAllAdministrators(){ ArrayList administrators = new ArrayList<>(); @@ -45,4 +86,4 @@ public ArrayList listAllAdministrators(){ } return administrators; } -} +} \ No newline at end of file diff --git a/app/src/main/java/gr/aueb/se/labadministration/presenter/SignInPresenter.java b/app/src/main/java/gr/aueb/se/labadministration/presenter/SignInPresenter.java deleted file mode 100644 index a574375..0000000 --- a/app/src/main/java/gr/aueb/se/labadministration/presenter/SignInPresenter.java +++ /dev/null @@ -1,33 +0,0 @@ -package gr.aueb.se.labadministration.presenter; - -import java.security.NoSuchAlgorithmException; - -import gr.aueb.se.labadministration.interfaces.SignInFragment; -import gr.aueb.se.labadministration.services.SignIn; -import gr.aueb.se.labadministration.utilities.RequestResult; - -public class SignInPresenter { - - private SignInFragment signInFragment; - private SignIn signIn; - private RequestResult result = null; - - public SignInPresenter(SignInFragment signInFragment) { - this.signInFragment = signInFragment; - this.signIn = new SignIn(); - } - - public RequestResult performSignIn(String username, String password){ - try { - return signIn.signInRequest(username, password); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; - } - - public void start(){ - signInFragment.setSignInPresenter(this); - signInFragment.show(); - } -} diff --git a/app/src/main/java/gr/aueb/se/labadministration/services/ConfigurationService.java b/app/src/main/java/gr/aueb/se/labadministration/services/ConfigurationService.java new file mode 100644 index 0000000..c4435a3 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/services/ConfigurationService.java @@ -0,0 +1,83 @@ +package gr.aueb.se.labadministration.services; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import androidx.annotation.Nullable; + +import java.util.Collection; +import java.util.List; + +import gr.aueb.se.labadministration.dao.TerminalConfigurationDAO; +import gr.aueb.se.labadministration.domain.configurations.TerminalConfiguration; +import gr.aueb.se.labadministration.memorydao.TerminalConfigurationDAOMemory; + +/** + * The class that communicates with all the activities & fragments regarding terminal configurations + */ +public class ConfigurationService extends Service { + + /** + * Binder definition + */ + public class ConfigurationServiceBinder extends Binder { + public ConfigurationService getService(){ + return ConfigurationService.this; + } + } + + private TerminalConfigurationDAO terminalConfigurationDAO; + + /** + * DAO Memory initialization + */ + public ConfigurationService(){ + terminalConfigurationDAO = new TerminalConfigurationDAOMemory(); + } + + /** + * Method that saves the new configuration that is given from the UI + * @param configuration + */ + public void saveConfiguration(TerminalConfiguration configuration){ + getTerminalConfigurationDAO().save(configuration); + } + + /** + * Method that finds the configuration that is given from the UI + * @param configuration + */ + public TerminalConfiguration findConfig(TerminalConfiguration configuration){ + return getTerminalConfigurationDAO().findByName(configuration.getName()); + } + + /** + * Method that displays all the available configs to the UI + * @return list of configs + */ + public Collection listAllConfigs(){ + return getTerminalConfigurationDAO().listAll(); + } + + /** + * @return the DAO + */ + public TerminalConfigurationDAO getTerminalConfigurationDAO(){ + return terminalConfigurationDAO; + } + + /** + * Default Android Methods + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_NOT_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return new ConfigurationServiceBinder(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/services/HistoryService.java b/app/src/main/java/gr/aueb/se/labadministration/services/HistoryService.java new file mode 100644 index 0000000..b82aeed --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/services/HistoryService.java @@ -0,0 +1,91 @@ +package gr.aueb.se.labadministration.services; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import java.util.List; +import java.util.stream.Collectors; + +import gr.aueb.se.labadministration.dao.TerminalDAO; +import gr.aueb.se.labadministration.domain.lab.Session; +import gr.aueb.se.labadministration.memorydao.TerminalDAOMemory; + +/** + * The class that communicates with all the activities & fragments regarding history + */ +public class HistoryService extends Service { + + /** + * Binder definition + */ + public class HistoryServiceBinder extends Binder { + public HistoryService getService() { + return HistoryService.this; + } + } + + private TerminalDAO terminalDAO; + + /** + * DAO Memory initialization + */ + public HistoryService() { + terminalDAO = new TerminalDAOMemory(); + } + + /** + * @return the DAO + */ + public TerminalDAO getTerminalDAO() { + return terminalDAO; + } + + /** + * Method that returns all the sessions + * @return list of sessions + */ + public List allSessions() { + return getTerminalDAO().listAll().stream() + .flatMap(terminal -> terminal.getSessions().stream()) + .collect(Collectors.toList()); + } + + /** + * Method that returns all the sessions of specific user + * @param query + * @return list of sessions + */ + public List findSessionsByUser(String query) { + return getTerminalDAO().listAll().stream() + .flatMap(terminal -> terminal.getSessions().stream()) + .filter(session -> session.getUser().getUsername().startsWith(query)) + .collect(Collectors.toList()); + } + + /** + * Method that returns all the sessions of specific terminal + * @param query + * @return list of sessions + */ + public List findSessionsByComputer(String query) { + return getTerminalDAO().listAll().stream() + .flatMap(terminal -> terminal.getSessions().stream()) + .filter(session -> session.getTerminal().getName().startsWith(query)) + .collect(Collectors.toList()); + } + + /** + * Default Android Methods + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_NOT_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return new HistoryServiceBinder(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/services/LabService.java b/app/src/main/java/gr/aueb/se/labadministration/services/LabService.java new file mode 100644 index 0000000..20768a3 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/services/LabService.java @@ -0,0 +1,172 @@ +package gr.aueb.se.labadministration.services; + +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import java.util.ArrayList; +import java.util.List; + +import gr.aueb.se.labadministration.dao.LaboratoryDAO; +import gr.aueb.se.labadministration.dao.TerminalDAO; +import gr.aueb.se.labadministration.domain.lab.Laboratory; +import gr.aueb.se.labadministration.domain.lab.Session; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.domain.schedule.DaySchedule; +import gr.aueb.se.labadministration.memorydao.LaboratoryDAOMemory; +import gr.aueb.se.labadministration.memorydao.TerminalDAOMemory; + +/** + * The class that communicates with all the activities & fragments regarding labs + */ +public class LabService extends Service { + + /** + * Binder definition + */ + public class LabServiceBinder extends Binder { + public LabService getService() { + return LabService.this; + } + } + + private LaboratoryDAO laboratoryDAO; + private TerminalDAO terminalDAO; + + /** + * DAO Memory initialization + */ + public LabService() { + laboratoryDAO = new LaboratoryDAOMemory(); + terminalDAO = new TerminalDAOMemory(); + } + + /** + * @return the Laboratory DAO + */ + public LaboratoryDAO getLaboratoryDAO() { + return laboratoryDAO; + } + + /** + * @return the Terminal DAO + */ + public TerminalDAO getTerminalDAO(){ + return terminalDAO; + } + + /** + * Method that saves a terminal and registers it to the specified lab + * @param laboratory to register + * @param terminal to save + */ + public void saveTerminal(Laboratory laboratory, Terminal terminal) { + getLaboratoryDAO().addTerminal(laboratory, terminal); + getTerminalDAO().save(terminal); + } + + /** + * Method that finds a terminal based on it's name + * @param name pf terminal + * @return Terminal or null + */ + public Terminal findTerminal(String name){ + return getTerminalDAO().findByName(name); + } + + /** + * Method that returns every lab available + * @return list of Laboratories + */ + public List listLabs(){ + return getLaboratoryDAO().listAll(); + } + + /** + * Method that returns all the Terminals of a lab + * @param lab + * @return list of terminals + */ + public List listComputers(Laboratory lab){ + return getLaboratoryDAO().findByName(lab.getName()).getTerminals(); + } + + /** + * Method that returns the schedule + * @param lab + * @return + */ + public List listSchedule(Laboratory lab){ + return getLaboratoryDAO().findByName(lab.getName()).getSchedule(); + } + + /** + * Method that returns if a terminal is in use + * @param terminal + * @return boolean + */ + public boolean isTerminalInUse(Terminal terminal){ + return getTerminalDAO().findByName(terminal.getName()).getStatus()==Terminal.TerminalStatus.IN_USE; + } + + /** + * Method that returns if a terminal is offline + * @param terminal + * @return boolean + */ + public boolean isTerminalOffline(Terminal terminal){ + return getTerminalDAO().findByName(terminal.getName()).getStatus()==Terminal.TerminalStatus.OFFLINE; + } + + /** + * Method that returns if a terminal is in maintenance + * @param terminal + * @return boolean + */ + public boolean isTerminalInMaintenance(Terminal terminal){ + return getTerminalDAO().findByName(terminal.getName()).getStatus()==Terminal.TerminalStatus.IN_MAINTENANCE; + } + + /** + * Method that returns the status of a terminal + * @param terminal + * @return Terminal.TerminalStatus as a String + */ + public String getStatus(String terminal){ + Terminal.TerminalStatus status = getTerminalDAO().findByName(terminal).getStatus(); + if(status == Terminal.TerminalStatus.IN_USE){ + ArrayList sessions = getTerminalDAO().findByName(terminal).getSessions(); + return sessions.get(sessions.size() - 1).getUser().getUsername(); + } + return status.toString(); + } + + /** + * Method that performs an action that is registered through the UI + * @param terminal to perform action + * @param status action to perform + * @return boolean of success or failure + */ + public boolean terminalAction(String terminal, Terminal.TerminalStatus status){ + Terminal f_terminal = getTerminalDAO().findByName(terminal); + if (f_terminal != null){ + f_terminal.setStatus(status); + return true; + } + return false; + } + + /** + * Default Android Methods + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_NOT_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return new LabServiceBinder(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/services/SignIn.java b/app/src/main/java/gr/aueb/se/labadministration/services/SignIn.java deleted file mode 100644 index 737a027..0000000 --- a/app/src/main/java/gr/aueb/se/labadministration/services/SignIn.java +++ /dev/null @@ -1,22 +0,0 @@ -package gr.aueb.se.labadministration.services; - -import java.security.NoSuchAlgorithmException; - -import gr.aueb.se.labadministration.dao.UserDAO; -import gr.aueb.se.labadministration.memorydao.UserDAOMemory; -import gr.aueb.se.labadministration.domain.people.User; -import gr.aueb.se.labadministration.utilities.RequestResult; - -public class SignIn { - - public RequestResult signInRequest(String username, String password) throws NoSuchAlgorithmException { - UserDAO userDAO = new UserDAOMemory(); - - User user = userDAO.find(username); - if (user == null) return new RequestResult(false, "User not found"); - - return user.signIn(password); - } - - -} diff --git a/app/src/main/java/gr/aueb/se/labadministration/services/SignInService.java b/app/src/main/java/gr/aueb/se/labadministration/services/SignInService.java new file mode 100644 index 0000000..934d50a --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/services/SignInService.java @@ -0,0 +1,70 @@ +package gr.aueb.se.labadministration.services; + +import android.app.Service; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; + +import java.security.NoSuchAlgorithmException; + +import gr.aueb.se.labadministration.dao.UserDAO; +import gr.aueb.se.labadministration.domain.people.User; +import gr.aueb.se.labadministration.memorydao.UserDAOMemory; +import gr.aueb.se.labadministration.utilities.RequestResult; + +/** + * The class that communicates with all the activities & fragments regarding sign in operation + */ +public class SignInService extends Service { + + /** + * Binder definition + */ + public class SignInBinder extends Binder { + public SignInService getService() { + return SignInService.this; + } + } + + private UserDAO userDAO; + + /** + * DAO Memory initialization + */ + public SignInService() { + userDAO = new UserDAOMemory(); + } + + /** + * @return the DAO + */ + public UserDAO getUserDAO() { + return userDAO; + } + + /** + * Method that returns the result of a sign in request + * @param username of user + * @param password of user + * @return the result of sign in action + */ + public RequestResult signInRequest(String username, String password) { + User user = getUserDAO().find(username); + if (user == null) return new RequestResult(false, false, "User not found"); + return user.signIn(password); + } + + /** + * Default Android Methods + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return START_NOT_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + return new SignInBinder(); + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/utilities/ExpandableListAdapter.java b/app/src/main/java/gr/aueb/se/labadministration/utilities/ExpandableListAdapter.java new file mode 100644 index 0000000..f2fbe19 --- /dev/null +++ b/app/src/main/java/gr/aueb/se/labadministration/utilities/ExpandableListAdapter.java @@ -0,0 +1,128 @@ +package gr.aueb.se.labadministration.utilities; + +import android.content.Context; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseExpandableListAdapter; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +import java.util.HashMap; +import java.util.List; + +import gr.aueb.se.labadministration.R; +import gr.aueb.se.labadministration.domain.lab.Terminal; +import gr.aueb.se.labadministration.fragments.TerminalFragment; + +/** + * The class that extends BaseExpandableListAdapter for our own purpose + */ +public class ExpandableListAdapter extends BaseExpandableListAdapter { + + private Context context; + private List listDataHeader; // contains the main categories e.x. lab1, lab2, lab3 etc. + private HashMap> listHashMap; // connects each main category with her items e.x. String lab1, List computer_101, computer_102 etc. + + /** + * Constructor + * @param context of app + * @param listDataHeader + * @param listHashMap + */ + public ExpandableListAdapter(Context context, List listDataHeader, HashMap> listHashMap) { + this.context = context; + this.listDataHeader = listDataHeader; + this.listHashMap = listHashMap; + } + + /** + * Override Methods + */ + @Override + public int getGroupCount() { + return listDataHeader.size(); + } + + @Override + public int getChildrenCount(int i) { + return listHashMap.get(listDataHeader.get(i)).size(); + } + + @Override + public Object getGroup(int i) { + return listDataHeader.get(i); + } + + @Override + public Object getChild(int i, int i1) { + return listHashMap.get(listDataHeader.get(i)).get(i1); // i = Group Item, i1 = Children item + } + + @Override + public long getGroupId(int i) { + return i; + } + + @Override + public long getChildId(int i, int i1) { + return i1; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) { + String headerTitle = (String) getGroup(i); + if(view == null){ + LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.list_group, null); + } + TextView listHeader = view.findViewById(R.id.listHeader); + listHeader.setTypeface(null, Typeface.BOLD); + listHeader.setText(headerTitle); + return view; + } + + /** + * Method that provides popup information for a terminal + */ + @Override + public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) { + final String childText = (String)getChild(i, i1); + if(view == null){ + LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.list_item, null); + } + TextView listItem = view.findViewById(R.id.listItem); + listItem.setText(childText); + listItem.setOnClickListener(v -> { + if(!childText.contains("Day")){ + FragmentTransaction manager = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction(); + TerminalFragment terminalFragment = new TerminalFragment(); + Bundle bundle = new Bundle(); + bundle.putString("terminal_name", childText); + terminalFragment.setArguments(bundle); + manager.add(terminalFragment, "Terminal"); + manager.commit(); + } + }); + return view; + } + + @Override + public boolean isChildSelectable(int i, int i1) { + return true; + } +} diff --git a/app/src/main/java/gr/aueb/se/labadministration/utilities/Password.java b/app/src/main/java/gr/aueb/se/labadministration/utilities/Password.java index 2417a33..0052ca0 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/utilities/Password.java +++ b/app/src/main/java/gr/aueb/se/labadministration/utilities/Password.java @@ -3,11 +3,19 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +/** + * Helper class that hashes a plaintext password + */ public class Password { private Password() { } + /** + * Method that hashes a password + * @param password to hash + * @return hashed password + */ public static String hash(String password) { MessageDigest md = null; try { diff --git a/app/src/main/java/gr/aueb/se/labadministration/utilities/RequestResult.java b/app/src/main/java/gr/aueb/se/labadministration/utilities/RequestResult.java index 66e7bc0..c8803f2 100644 --- a/app/src/main/java/gr/aueb/se/labadministration/utilities/RequestResult.java +++ b/app/src/main/java/gr/aueb/se/labadministration/utilities/RequestResult.java @@ -1,19 +1,36 @@ package gr.aueb.se.labadministration.utilities; +/** + * The class that provides the sign in result + */ public class RequestResult { - private boolean success; + private boolean success, administrator; private String reasonOfFailure; - public RequestResult(boolean success, String reasonOfFailure) { + /** + * Constructor + * @param success of sign in + * @param administrator privileged user + * @param reasonOfFailure of sign in + */ + public RequestResult(boolean success, boolean administrator, String reasonOfFailure) { this.success = success; + this.administrator = administrator; this.reasonOfFailure = reasonOfFailure; } + /** + * Getters + */ public boolean isSuccessful() { return success; } + public boolean isAdministrator() { + return administrator; + } + public String getReasonOfFailure() { return reasonOfFailure; } diff --git a/app/src/main/res/drawable/app_icon.xml b/app/src/main/res/drawable/app_icon.xml new file mode 100644 index 0000000..ce59600 --- /dev/null +++ b/app/src/main/res/drawable/app_icon.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_add_black_24dp.xml b/app/src/main/res/drawable/ic_add_black_24dp.xml new file mode 100644 index 0000000..3e47a39 --- /dev/null +++ b/app/src/main/res/drawable/ic_add_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_add_to_photos_black_24dp.xml b/app/src/main/res/drawable/ic_add_to_photos_black_24dp.xml new file mode 100644 index 0000000..f704ffe --- /dev/null +++ b/app/src/main/res/drawable/ic_add_to_photos_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_assignment_black_24dp.xml b/app/src/main/res/drawable/ic_assignment_black_24dp.xml new file mode 100644 index 0000000..4a3eb4f --- /dev/null +++ b/app/src/main/res/drawable/ic_assignment_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_computer_black_24dp.xml b/app/src/main/res/drawable/ic_computer_black_24dp.xml new file mode 100644 index 0000000..4599f98 --- /dev/null +++ b/app/src/main/res/drawable/ic_computer_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index d5fccc5..2408e30 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,170 +1,74 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:viewportWidth="108" + xmlns:android="http://schemas.android.com/apk/res/android"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml new file mode 100644 index 0000000..affc7ba --- /dev/null +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/power_off.xml b/app/src/main/res/drawable/power_off.xml new file mode 100644 index 0000000..26272ab --- /dev/null +++ b/app/src/main/res/drawable/power_off.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/reboot.xml b/app/src/main/res/drawable/reboot.xml new file mode 100644 index 0000000..8229a9a --- /dev/null +++ b/app/src/main/res/drawable/reboot.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/sign_out.xml b/app/src/main/res/drawable/sign_out.xml new file mode 100644 index 0000000..beafea3 --- /dev/null +++ b/app/src/main/res/drawable/sign_out.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..bb8b32b --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_new_configuration.xml b/app/src/main/res/layout/activity_new_configuration.xml new file mode 100644 index 0000000..94bfeb3 --- /dev/null +++ b/app/src/main/res/layout/activity_new_configuration.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +