views:

182

answers:

6

In my system I have a single class with a load of (20?) final booleans defining the permissions this user type has.

What is a better way to do this?

I'm sure there's lots of examples about this but I don't know the keywords.

+8  A: 

Make a class Permission, and give each User a collection of them. If a permission is in the user's permissions collection, then the user has the permission, otherwise not.

tdammers
He explicitly asked for final booleans.
Tim Büthe
@Tim: He explicitly asked for a better way than final booleans.
sepp2k
No, he is asking for better approach than final booleans
arjan
Oh, I see my bad.
Tim Büthe
A particularly nice way to do this would be to make the `Permission` class an enum (which it probably is, conceptually, unless the application is doing something unusual with dynamically-created roles). Then you get extremely clear code by calling something like `EnumSet.contains(Permission.ADMIN)`.
Andrzej Doyle
@Andrzej Doyle When You have 20 roles You need to check write 20 times EnumSet.Contains(Permission.ADMIN) The code stop to be extremely clean. The role based on Enum are for long way way very limited option.
Vash
I'm not sure exactly what you mean by "check write 20 times"; but see Vitalii Federenko's answer which illustrates the kind of thing I had in mind. You only need to define the `contains` call once, you have the ability to easily do things like `containsAll` if the situation dictates, and permissions are conceptually enums anyway.
Andrzej Doyle
Vash
A: 

If you don't know the keywords and syntax, you might want to read a book about Java or do some tutorials online. However, a class could look like this:

public class User {

private final boolean admin, superuser, guest;

public User(boolean admin, boolean superuser, boolean guest) {
    this.admin = admin;
    this.superuser = superuser;
    this.guest = guest;
}

public boolean isAdmin() {
    return admin;
}

public boolean isSuperuser() {
    return superuser;
}

public boolean isGuest() {
    return guest;
}

// and so on
}
Tim Büthe
+9  A: 

You can take advantage of enums, e.g.:

public enum Permission {
    READ, WRITE;
}

public class User {

    private final EnumSet<Permission> permissions;

    public User(Permission... permissions) {
       this.permissions = EnumSet.copyOf(Arrays.asList(permissions));
    }

    public boolean hasPermission(Permission permission) {
        return permissions.contains(permission);
    }

    //...
}

User user = new User(Permission.READ, Permission.WRITE);
Vitalii Fedorenko
btw: this code wold not compile because you create a final field without initialization
Vash
+1, this is what I meant in my comment to tdammers' answer. @Vash - this is completely fine, the field is initialised in the constructor.
Andrzej Doyle
That something new (for me), but really works ;-).
Vash
+2  A: 

Complete example of what @tdammers proposed:

class enum Permission {
    WRITE, READ, EXECUTE, GROUP, OWNER
}

public class User {
    protected Set<Permission> permissions;

    public User() {
        permissions = new EnumSet<Permission>();
    }

    public boolean hasPermission(Permission p) {
        return permissions.contains(p);
    }

    public void addPermisssion(Permission p) {
        permissions.add(p);
    }

    public void removePermisssion(Permission p) {
        permissions.remove(p);
    }
}

//usage
User u = new User();
u.addPermission(Permission.READ);
System.out.writeln(u.hasPermission(Permission.WRITE));
u.removePermission(Permission.READ);
Max
+2  A: 

You can use the mask for this

public interface IPersmisions {

 public static final int NONE = 1 << 0;
 public static final int LEVEL1 = 1 << 1;
 public static final int LEVEL2 = 1 << 2;
 public static final int LEVEL3 = 1 << 3;
 public static final int LEVEL4 = 1 << 4;
 public static final int LEVEL5 = 1 << 5;
 public static final int LEVEL6 = 1 << 6;
 public static final int LEVEL7 = 1 << 7;
 public static final int LEVEL8 = 1 << 8;
 public static final int LEVEL9 = 1 << 9;
}

in used You add

int permisions = IPersmisions.NONE;

    public boolean checkPermission(int permission) {
        return (permissions & permission) != 0;
    }

    public void addPermission(int permission) {
            permissions = (permissions | permission);
    }

    public void removePermission(int permission) {
        permissions = (permissions & ~permission);
    }

Than You can set a easily set a group for users

public interface IPermisionGroup extends IPermisions {

  public static final int LEVEL1_2_3 = LEVEL1 | LEVEL2 | LEVEL3; 
  public static final int LEVEL4_5_6 = LEVEL4 | LEVEL5 | LEVEL6; 
  public static final int LEVEL7_8_9 = LEVEL7 | LEVEL8 | LEVEL9; 

}

And in the code you can use is like this

   user.addPermision(IPermisions.LEVEL1);

or

   user.addPermision(IPermisions.LEVEL1 | IPermision.LEVEL2);

or

user.addPermision(IPermisionGroup.LEVEL1_2_3);
Vash
Rolling your own bitmask in 2010 in .NET. You have got to be kidding me.
epochwolf
@eopchwolf: And what is wrong about it ? btw not in .NET but in Java.
Vash
A: 

Polymorphism, not conditionals.

class User {
    final Print print;
    User(Print print) {
        this.print = print;
    }
}

interface Print {
    void print();
}

class CanPrint implements Print {
    public void print() { do whatever it takes to print a user }
}

class CannotPrint implements Print {
    public void print() { throw null; }
}
Ricky Clarkson