diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 60ea6ff5c..c7c9d9b5c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ - - + + @@ -17,11 +17,12 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> - + + - - + @@ -44,10 +45,9 @@ - - + \ No newline at end of file diff --git a/app/src/main/java/ch/epfl/sdp/appart/MainActivity.java b/app/src/main/java/ch/epfl/sdp/appart/MainActivity.java index 834c56cc5..eaf371eb8 100644 --- a/app/src/main/java/ch/epfl/sdp/appart/MainActivity.java +++ b/app/src/main/java/ch/epfl/sdp/appart/MainActivity.java @@ -3,9 +3,10 @@ import android.content.Intent; import android.os.Bundle; -import android.util.Log; import androidx.appcompat.app.AppCompatActivity; +import ch.epfl.sdp.appart.databus.Activity1; + /** * The main UI class. */ @@ -17,7 +18,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Bundle extras = this.getIntent().getExtras(); - Intent intent = new Intent(this, LoginActivity.class); + Intent intent = new Intent(this, Activity1.class); if(extras != null && extras.containsKey("email") && extras.containsKey("password")){ intent.putExtra("email", extras.getString("email")); intent.putExtra("password", extras.getString("password")); diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/Activity1.java b/app/src/main/java/ch/epfl/sdp/appart/databus/Activity1.java new file mode 100644 index 000000000..38c17d700 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/Activity1.java @@ -0,0 +1,73 @@ +package ch.epfl.sdp.appart.databus; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.lifecycle.MutableLiveData; + +import ch.epfl.sdp.appart.R; +import ch.epfl.sdp.appart.hilt.databus.annotations.IntegerDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.StringDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.UriListDataBus; +import dagger.hilt.android.AndroidEntryPoint; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.widget.Button; + +import java.util.Arrays; +import java.util.List; + +import javax.inject.Inject; + +@AndroidEntryPoint +public class Activity1 extends AppCompatActivity { + + @IntegerDataBus + @Inject + DataBus integerBus; + + @StringDataBus + @Inject + DataBus stringBus; + + @UriListDataBus + @Inject + DataBus> uriListBus; + + @UriListDataBus + @Inject + PrivateDataBus> uriPrivateDataBus; + + private PrivateDataBusToken token = + PrivateDataBusTokenFactory.makeToken(Activity1.class, Activity2.class); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_1); + Button gotoActivity2Button = findViewById(R.id.goto_activity_2_button); + + /** + * Solution 1 : basic bus + */ + integerBus.setData(1234); + stringBus.setData("coucou !"); + uriListBus.setData(Arrays.asList(Uri.parse("abc"), Uri.parse("1234"), Uri.parse("cool"))); + + /** + * Solution 2 : private bus + */ + uriPrivateDataBus.setData(token, Arrays.asList(Uri.parse("so"), Uri.parse("private"))); + + gotoActivity2Button.setOnClickListener(v -> { + Intent intent = new Intent(this, Activity2.class); + startActivity(intent); + }); + + } + + @Override + protected void onResume() { + super.onResume(); + } +} \ No newline at end of file diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/Activity2.java b/app/src/main/java/ch/epfl/sdp/appart/databus/Activity2.java new file mode 100644 index 000000000..ef5a67d21 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/Activity2.java @@ -0,0 +1,66 @@ +package ch.epfl.sdp.appart.databus; + +import androidx.appcompat.app.AppCompatActivity; + +import android.net.Uri; +import android.os.Bundle; + +import java.util.List; + +import javax.inject.Inject; + +import ch.epfl.sdp.appart.R; +import ch.epfl.sdp.appart.hilt.databus.annotations.IntegerDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.StringDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.UriListDataBus; +import dagger.hilt.android.AndroidEntryPoint; + +@AndroidEntryPoint +public class Activity2 extends AppCompatActivity { + + /** + * Bellow we declare the bus we want to use + */ + @IntegerDataBus + @Inject + DataBus integerBus; + + @StringDataBus + @Inject + DataBus stringBus; + + @UriListDataBus + @Inject + DataBus> uriListBus; + + /** + * Solution 2 : private databus + */ + + @UriListDataBus + @Inject + PrivateDataBus> uriPrivateDataBus; + + private PrivateDataBusToken token = + PrivateDataBusTokenFactory.makeToken(Activity1.class, Activity2.class); + + private Integer a; + private String b; + private List c; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_2); + + /** + * Solution 1 and 2 get data + */ + a = integerBus.getData(); + b = stringBus.getData(); + c = uriListBus.getData(); + + c = uriPrivateDataBus.getData(token); + + } +} \ No newline at end of file diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/DataBus.java b/app/src/main/java/ch/epfl/sdp/appart/databus/DataBus.java new file mode 100644 index 000000000..ac1a1fd0d --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/DataBus.java @@ -0,0 +1,37 @@ +package ch.epfl.sdp.appart.databus; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Solution 1 + * Class that allows activities to talk to each other with a bus. All classes that + * utilise this class defined for some type T will utilize the same class. + * @param The type of the data that will be exchangeable over the bus. + * This class is only meant to be used via hilt injection and should never be instantiated. + */ +@Singleton +public class DataBus { + + T data; + + @Inject + public DataBus() {} + + /** + * Set the data contained in the bus. + * @param data data T to be set. + */ + public void setData(T data) { + this.data = data; + } + + /** + * Get the data contained in the bus. + * @return T data + */ + public T getData() { + return data; + } + +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/ExclusiveDataBus.java b/app/src/main/java/ch/epfl/sdp/appart/databus/ExclusiveDataBus.java new file mode 100644 index 000000000..373db9810 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/ExclusiveDataBus.java @@ -0,0 +1,80 @@ +package ch.epfl.sdp.appart.databus; + +/** + * Solution 2 + * This class allows for two classes to exchange data by allowing exactly two classes to + * talk with each other. + * @param the type of parameters + */ +public class ExclusiveDataBus { + + private T data; + private Class firstTalker; + private Class secondTalker; + + /** + * Set the owner ship of the bus for one of the talker + * @param newTalker + */ + public void bind(Class newTalker) { + if (firstTalker == null) { + firstTalker = newTalker; + return; + } + + if (secondTalker == null) { + secondTalker = newTalker; + return; + } + + throw new IllegalStateException("bus already owned by " + firstTalker.getCanonicalName() + + " and " + secondTalker.getCanonicalName() + " but requested by " + newTalker.getCanonicalName()); + } + + public void release(Class talker) { + + if (firstTalker.getCanonicalName().equals(talker.getCanonicalName())) { + firstTalker = null; + return; + } + + if (secondTalker.getCanonicalName().equals(talker.getCanonicalName())) { + secondTalker = null; + return; + } + + throw new IllegalStateException("bus owned by " + firstTalker.getCanonicalName() + + " and " + secondTalker.getCanonicalName() + " but trying to be released by " + + talker.getCanonicalName()); + + } + + public void setData(Class talker, T data) { + if (!firstTalker.getCanonicalName().equals(talker.getCanonicalName()) && + !secondTalker.getCanonicalName().equals(talker.getCanonicalName())) { + throw new IllegalStateException("bus already owned by " + firstTalker.getCanonicalName() + + " and " + secondTalker.getCanonicalName() + " but accessed by " + talker.getCanonicalName()); + } + + if (firstTalker == null || secondTalker == null) { + throw new IllegalStateException("Two talkers must be registered"); + } + + this.data = data; + } + + public T getData(Class talker) { + if (!firstTalker.getCanonicalName().equals(talker.getCanonicalName()) && + !secondTalker.getCanonicalName().equals(talker.getCanonicalName())) { + throw new IllegalStateException("bus already owned by " + firstTalker.getCanonicalName() + + " and " + secondTalker.getCanonicalName() + " but read by " + talker.getCanonicalName()); + } + + if (firstTalker == null || secondTalker == null) { + throw new IllegalStateException("Two talkers must be registered"); + } + + return data; + } + +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBus.java b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBus.java new file mode 100644 index 000000000..3afd87f3c --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBus.java @@ -0,0 +1,44 @@ +package ch.epfl.sdp.appart.databus; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.HashMap; + +import javax.inject.Inject; + +/** + * This class allows activities to talk with the use of tokens. + * A token equals a channel and enforce that to see a value you need to have the right token + * See the token factory to see how it is synthesized. + * @param + */ +public class PrivateDataBus { + + private HashMap entries = new HashMap<>(); + + @Inject + public PrivateDataBus() {} + + /** + * Set the data contained in the bus. + * @param data data T to be set. + */ + public void setData(@NonNull PrivateDataBusToken token, @Nullable T data) { + if (token == null) { + throw new IllegalArgumentException("token cannot be null"); + } + entries.put(token, data); + } + + /** + * Get the data contained in the bus. + * @return T data + */ + public T getData(@NonNull PrivateDataBusToken token) { + if (token == null) { + throw new IllegalArgumentException("token cannot be null"); + } + return entries.getOrDefault(token, null); + } +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusToken.java b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusToken.java new file mode 100644 index 000000000..3d7e88e2f --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusToken.java @@ -0,0 +1,26 @@ +package ch.epfl.sdp.appart.databus; + +public class PrivateDataBusToken { + private final int token; + public PrivateDataBusToken(int token) { this.token = token; } + protected int getToken() { return token; } + + @Override + public int hashCode() { + return token; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (other == null) { + return false; + } else if (getClass() != other.getClass()) { + return false; + } else { + PrivateDataBusToken t = (PrivateDataBusToken) other; + return t.getToken() == getToken(); + } + } +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusTokenFactory.java b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusTokenFactory.java new file mode 100644 index 000000000..3e47f164d --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/databus/PrivateDataBusTokenFactory.java @@ -0,0 +1,10 @@ +package ch.epfl.sdp.appart.databus; + +import java.util.HashMap; + +public class PrivateDataBusTokenFactory { + public static PrivateDataBusToken makeToken(Class first, Class second) { + int hash = (first.getCanonicalName() + second.getCanonicalName()).hashCode(); + return new PrivateDataBusToken(hash); + } +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/ActivityBusModule.java b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/ActivityBusModule.java new file mode 100644 index 000000000..d69a7cefa --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/ActivityBusModule.java @@ -0,0 +1,46 @@ +package ch.epfl.sdp.appart.hilt.databus; + +import android.content.Context; +import android.net.Uri; + + +import java.util.List; + +import javax.inject.Singleton; + +import ch.epfl.sdp.appart.databus.DataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.IntegerDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.StringDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.UriListDataBus; +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.android.qualifiers.ApplicationContext; +import dagger.hilt.components.SingletonComponent; + +@Module +@InstallIn(SingletonComponent.class) +public abstract class ActivityBusModule { + + @IntegerDataBus + @Singleton + @Provides + public static DataBus provideDataTransferService(@ApplicationContext Context context) { + return new DataBus<>(); + } + + @StringDataBus + @Singleton + @Provides + public static DataBus provideOtherDataTransferService(@ApplicationContext Context context) { + return new DataBus<>(); + } + + @UriListDataBus + @Singleton + @Provides + public static DataBus> provideUriList(@ApplicationContext Context context) { + return new DataBus<>(); + } + +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/PrivateDataBusModule.java b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/PrivateDataBusModule.java new file mode 100644 index 000000000..7e1986e22 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/PrivateDataBusModule.java @@ -0,0 +1,46 @@ +package ch.epfl.sdp.appart.hilt.databus; + +import android.content.Context; +import android.net.Uri; + +import java.util.List; + +import javax.inject.Singleton; + +import ch.epfl.sdp.appart.databus.DataBus; +import ch.epfl.sdp.appart.databus.PrivateDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.IntegerDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.StringDataBus; +import ch.epfl.sdp.appart.hilt.databus.annotations.UriListDataBus; +import dagger.Module; +import dagger.Provides; +import dagger.hilt.InstallIn; +import dagger.hilt.android.qualifiers.ApplicationContext; +import dagger.hilt.components.SingletonComponent; + +@Module +@InstallIn(SingletonComponent.class) +public class PrivateDataBusModule { + + @IntegerDataBus + @Singleton + @Provides + public static PrivateDataBus provideIntegerDataBus(@ApplicationContext Context context) { + return new PrivateDataBus<>(); + } + + @StringDataBus + @Singleton + @Provides + public static PrivateDataBus provideStringDataBus(@ApplicationContext Context context) { + return new PrivateDataBus<>(); + } + + @UriListDataBus + @Singleton + @Provides + public static PrivateDataBus> provideUriListDataBus(@ApplicationContext Context context) { + return new PrivateDataBus<>(); + } + +} diff --git a/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/IntegerDataBus.java b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/IntegerDataBus.java new file mode 100644 index 000000000..2784ef809 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/IntegerDataBus.java @@ -0,0 +1,12 @@ +package ch.epfl.sdp.appart.hilt.databus.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface IntegerDataBus {} + + diff --git a/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/StringDataBus.java b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/StringDataBus.java new file mode 100644 index 000000000..2f9361739 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/StringDataBus.java @@ -0,0 +1,10 @@ +package ch.epfl.sdp.appart.hilt.databus.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface StringDataBus {} \ No newline at end of file diff --git a/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/UriListDataBus.java b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/UriListDataBus.java new file mode 100644 index 000000000..50e125f42 --- /dev/null +++ b/app/src/main/java/ch/epfl/sdp/appart/hilt/databus/annotations/UriListDataBus.java @@ -0,0 +1,10 @@ +package ch.epfl.sdp.appart.hilt.databus.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface UriListDataBus {} diff --git a/app/src/main/res/layout/activity_1.xml b/app/src/main/res/layout/activity_1.xml new file mode 100644 index 000000000..c3a025119 --- /dev/null +++ b/app/src/main/res/layout/activity_1.xml @@ -0,0 +1,30 @@ + + + + + +