Reputation: 658
Let's say I want to create a generic type container in Java, using an interface like this:
public interface GenericDataContainer<T>
I want classes that'll implement this interface to have an underlying structure to hold data of type T
. However, I also want to keep track of who a piece of data was added by. In the GenericDataContainer
interface, a method to add an object to the container might have a declaration like this:
public void put(String added_by, T obj);
I am just getting started with generics, and also Java in general, so I'm not sure what the best way to go about this would be.
Let's say I have a structure, like a HashMap
that keeps track of what users I have, and let's say I identify users by their name
String
. How would I go about associating a T
object inside my container to the String
of the user who added it?
Would I wrap the object into a wrapper class that has two members:
T obj;
String added_by;
or is there a better way?
Let's say I also want to be able to allow certain users to access the object, not just the owner; could I just add an array of String
s to such wrapper object to keep track of users who were granted access?
This is what the whole interface specification is like (please don't critique it: I have no control over the specification)
public interface SecureDataContainer<T>{
public void createUser(String id, String passw);
// number of elements added by owner
public int getSize(String owner, String passw);
public boolean put(String owner, String passw, T data);
public T get(String owner, String passw, T data);
public T remove(String owner, String passw, T data);
public void copy(String owner, String passw, T data);
// enable another user to access the object
public void share(String owner, String passw, String other, T data);
public Iterator<T>getIterator(String owner, String passw);
}
Upvotes: 1
Views: 1708
Reputation: 1160
If a user can only ever add a single object to your collection, then a Map<String, T>
would suffice.
Then your put method is literally just the built in Map
put.
myMap.put(ownerString, dataOfTypeT)
If you want a single user to be able to add multiple data to your collection, then you want to create a Map<String,List<T>>
.
Then your put method needs to create the list first if it doesn't already exist, otherwise it's the same.
class MyContainer<T> {
private Map<String, List<T>> backingMap = new HashMap<>();
public void put(String userName, T data) {
if (!map.containsKey(userName)) {
map.put(userName, new ArrayList<>());
}
map.get(userName).add(data);
}
public List<T> getAllData(String userName) {
if (!map.get(userName)) {
// in my opinion it makes more sense to return empty list than null
return List.of()
}
// making a copy is a good idea so that the caller can't modify our list.
return List.copyOf(map.get(userName))
}
}
If you are okay with using a third party library, guava's ListMultimap provides similar behavior.
Upvotes: 0
Reputation: 38531
Let's say I have a structure, like a HashMap that keeps track of what users I have, and let's say I identify users by their name String. How would I go about associating a T object inside my container to the String of the user who added it?
What's wrong with :
import java.util.HashMap;
import java.util.Map;
interface GenericDataContainer<T> {
public void put(String added_by, T obj);
}
class HashMapBasedContainer<T> implements GenericDataContainer<T> {
//if this lives somewhere else, make sure it's accessible from here
Map<String, T> mapper = new HashMap<>();
@Override
public void put(String added_by, T obj) {
this.mapper.put(added_by, obj);
}
}
Let's say I also want to be able to allow certain users to access the object, not just the owner; could I just add an array of Strings to such wrapper object to keep track of users who were granted access?
You could implement the interface again in a version that does exactly that.
Upvotes: 0
Reputation: 140427
What you outlined makes sense, you could do something like:
public class OwnedData<T> {
private final OwnerId owner;
private final T data;
// constructor taking owner/data ... getters maybe
}
(Note: it makes more sense to have a distinct type that denotes Owners, you might have two different users named "Carl", so better prepare yourself to be not rely just on a String name to identify owners)
But yes, that would be one way to go about this. Of course, you then have to think to correctly implement equals()
and hashCode()
for that class, to ensure that objects can be clearly distinguished.
Yet, in the real world, things are of course much more complicated. Permission models are complicated. You have to think not only about users, but also about "roles". Or groups of users. Or some data being read-only, some data being read/writeable.
In other words: there are many different requirements that a permission system might have to fulfil. Therefore we can't tell you what is best for you, as nobody here knows your specific requirements!
Upvotes: 2