Design pattern for flexible interface - java

Suppose I have an interface API and classes FacebookAPI and FlickrAPI that implements this interface,
public interface API {
Photo getPhoto(int id);
Album getAlbum(int id);
}
package api;
import domainObjects.Album;
import domainObjects.Photo;
public class FacebookAPI implements API{
#Override
public Photo getPhoto(int id) {
// TODO Auto-generated method stub
return null;
}
#Override
public Album getAlbum(int id) {
// TODO Auto-generated method stub
return null;
}
}
import domainObjects.Album;
import domainObjects.Photo;
public class FlickrAPI implements API{
#Override
public Photo getPhoto(int id) {
// TODO Auto-generated method stub
return null;
}
#Override
public Album getAlbum(int id) {
// TODO Auto-generated method stub
return null;
}
}
The issue is that I only know that at minimum both APIs(facebook and flickr) requires the photoId. Now suppose that to get a photo FacebookAPI requires AccessToken in addition to Id while FlickAPI requires APIKey + UserId in addition to photoId.
What Design Pattern can i use to solve this issue?

Create a Credentials abstract class to be extended by concrete APi implementation and get that in method contracts.
public Album getAlbum(int id, Credentials c) {
and similarily
public FlickrCredentials extends Credentials {
String APIKey
String UserId
}
That is only feasible if the authentication method is similar with changing parameters (like URL parameters). The abstract class should specify the contract of the method actually using the values, something like:
public String buildToken();
that could be implemented for instance as:
#Override
public String buildToken() {
return "APIKey="+getAPIKey()+"&UserId="+getUserId();
}

Not sure which language you're using (objective c?) but if done it in C# then you'd want to use generics:
public interface API<TIdentifier> {
Photo getPhoto(TIdentifier id);
Album getAlbum(TIdentifier id);
}
Then your classes would look like this:
public class FlickrAPI implements API<FlickrIdentifier>
{
#Override
public Photo getPhoto(FlickrIdentifier id) {
// TODO Auto-generated method stub
return null;
}
#Override
public Album getAlbum(FlickrIdentifier id) {
// TODO Auto-generated method stub
return null;
}
}
Then you'd also need the FlickrIdentifier class:
public class FlickrIdentifier
{
public string ApiKey { get; set; }
public string UserId { get; set; }
}

Why cant you do something like this
public class FlickrAPI implements API{
private String key;
private UserId id;
public FlickrAPI(String key, UserId id){
this.key = key;
this.id = id;
//rest of initialzation
}
}
Similarly for the FacebookAPI class

Related

Is it possible to make a specific method working only with a specific constructor?

I have a class called User.java
public class User {
public User(Context context) {
}
public User() {
}
public void getUserId(){
}
public void getUserName(){
}
}
If I create an object of user class then I can reach to all methods such as getUserId and getUserName
User user_1 = new User(this);
user_1.getUserId();
user_1.getUserName();
User user_2 = new User();
user_2.getUserId();
user_2.getUserName();
The main question is can I get getUserName only if I called a constructor that has one parameter? But if I call a constructor that does not have a parameter then I can't get getUserName. Is it possible in Java?
There are multiple ways to achieve (roughly) what you want.
The easy, but possibly annoying way is to throw an Exception whenever a "forbidden" method is called:
public String getUserName(){
if (someRequiredContext == null) {
throw new IllegalStateException("method not allowed!");
}
// do stuff
}
This "works", but doesn't help the user avoid calling those methods, since there's no easy way for them to know if they can call getuserName on a given User object.
The more involved version would be to have two classes (for example User and UserWithContext), but then you can't instantiate them the right way. But you could use factory methods instead of constructors:
public abstract class User {
User() { ... };
public static User createUser() {
return new BasicUser();
};
public static UserWithContext createUser(Context context) {
return new UserWithContext(context);
}
public String getId() { ... }
}
class BasicUser extends User { // this class need not be public!
}
public class UserWithContext extends User {
UserWithContext(Context context) { ... }
public String getuserName() { ... };
}
This way the type will inform the users of your API which methods are allowed with a given User object.
No, it is not possible. But you could use interfaces to say for instance LimitedUser and FullUser
public interface LimitedUser {
int userId();
}
public interface FullUser extends LimitedUser {
String getUsername();
}
Then use factory methods on for instance the User implementation
public class User implements FullUser {
private final int id;
private final String username;
private User(int id, String username) {
this.id = id;
this.username = username;
}
public static LimitedUser createLimitedUser(int id) {
return new User(id, null);
}
public static FullUser createFullUser(int id, String username) {
return new User(id, username);
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
}

Java EE: Interface with a method that returns an instance of a helper class. Bad idea?

I have an interface that defines a method that returns an instance of a helper class and I was wondering if there's a better way of going about what I'm trying to do.
For example, say I have a Tag class:
public class Tag {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
You can assign Tags to other objects.
The assignment is represented by TagAssign:
public abstract class TagAssign {
private Tag tag;
public Tag getTag() {
return tag;
}
public void setTag(Tag tag) {
this.tag = tag;
}
}
A new type of assignment will extend TagAssign and define what the Tag's being assigned to.
For example, a Tag assigned to a User would look like the following:
public class UserTag extends TagAssign {
private long id;
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
An object that can have a tag assigned to it will implement the TagAssignable interface:
public interface TagAssignable {
public TagAssignableHelper getTagAssignableHelper();
}
TagAssignable defines a method that returns an instance of TagAssignableHelper.
At the moment, TagAssignableHelper just defines a method that assigns the Tag to the TagAssignable, returning a TagAssign.
public interface TagAssignableHelper<A extends TagAssignable, T extends TagAssign> {
public T assignTag(A assignable, Tag tag);
}
Here's what a User class that implements TagAssignable would look like:
public class User implements TagAssignable {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
#Override
public UserTagAssignableHelper getTagAssignableHelper() {
return new UserTagAssignableHelper();
}
}
And UserTagAssignableHelper looks like:
public class UserTagAssignableHelper implements TagAssignableHelper<User, UserTag> {
#Override
public UserTag assignTag(User assignable, Tag tag) {
UserTag userTag = new UserTag();
userTag.setUser(assignable);
userTag.setTag(tag);
return userTag;
}
}
The code in use:
public class Main {
public static void main(String[] args) {
List<TagAssignable> assignables = new ArrayList<>();
assignables.add(new User());
Tag tag = new Tag();
List<TagAssign> assignments = new ArrayList<>();
for (TagAssignable assignable : assignables) {
TagAssign assignment = assignable.getTagAssignableHelper().assignTag(assignable, tag);
assignments.add(assignment);
}
}
}
I basically want each type of TagAssignable to define how it's used inside the framework. When a developer marks a class as TagAssignable, they have to define how the TagAssign class is created, because at some point in the framework it's going to try and do just that.
I'm trying to avoid doing something like this:
if(assignable instanceof User) {
User user = (User) assignable;
UserTag userTag = new UserTag();
userTag.setTag(tag);
userTag.setUser(user);
return userTag;
}
// followed by more ifs for each type of TagAssignable
I'm open to all feedback and suggestions.
I think introducing the TagAssign class hierarchy complicates your design. What I would try to achieve is to change the TagAssignable interface to only have Set<Tag> getTags(), add(Tag tag) and remove(Tag tag) tags. If you want to achieve immutability of objects with tags, you could change the interface to have with(Tag tag) and without(Tag tag) methods that return mutated instances. This would remove the need for separate assignment classes and their corresponding helpers.

Send List of Custom model between Intents

I've found lots of answers on SO but none working for me.
I have a List<MyModel> myList that I want to pass and retrieve through Intents.MyModel implements Parcelable and its implementation.I am using intent.putExtra("my_key",(Parcelable) myList);At runtime it throws the exception
java.util.ArrayList cannot be cast to android.os.Parcelable
And if I use putParcelableArrayListExtra then it says wrong second argument type.Any explaination or other way would be helpfulEDIT: My Model class is :
public class Filter {
private String categoryId;
public List<PrimaryFilterData> getPrimaryFilterDataList() {
return primaryFilterDataList;
}
public void setPrimaryFilterDataList(List<PrimaryFilterData> primaryFilterDataList) {
this.primaryFilterDataList = primaryFilterDataList;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getCategoryId() {
return categoryId;
}
public void setCategoryId(String categoryId) {
this.categoryId = categoryId;
}
private String categoryName;
private List<PrimaryFilterData> primaryFilterDataList;
public static class PrimaryFilterData implements Parcelable
{
private String filterId;
protected PrimaryFilterData(Parcel in) {
filterId = in.readString();
filterName = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(filterId);
dest.writeString(filterName);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<PrimaryFilterData> CREATOR = new Creator<PrimaryFilterData>() {
#Override
public PrimaryFilterData createFromParcel(Parcel in) {
return new PrimaryFilterData(in);
}
#Override
public PrimaryFilterData[] newArray(int size) {
return new PrimaryFilterData[size];
}
};
public String getFilterName() {
return filterName;
}
public void setFilterName(String filterName) {
this.filterName = filterName;
}
public String getFilterId() {
return filterId;
}
public void setFilterId(String filterId) {
this.filterId = filterId;
}
public List<SecondaryFilterData> getSecondaryFilterDataList() {
return secondaryFilterDataList;
}
public void setSecondaryFilterDataList(List<SecondaryFilterData> secondaryFilterDataList) {
this.secondaryFilterDataList = secondaryFilterDataList;
}
private String filterName;
private List<SecondaryFilterData> secondaryFilterDataList;
}
public static class SecondaryFilterData implements Parcelable {
private String secFilterName;
private String secFilterId;
private boolean isChecked=false;
public SecondaryFilterData(){}
protected SecondaryFilterData(Parcel in) {
secFilterName = in.readString();
secFilterId = in.readString();
isChecked = in.readByte() != 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(secFilterName);
dest.writeString(secFilterId);
dest.writeByte((byte) (isChecked ? 1 : 0));
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SecondaryFilterData> CREATOR = new Creator<SecondaryFilterData>() {
#Override
public SecondaryFilterData createFromParcel(Parcel in) {
return new SecondaryFilterData(in);
}
#Override
public SecondaryFilterData[] newArray(int size) {
return new SecondaryFilterData[size];
}
};
public boolean isChecked() {
return isChecked;
}
public void setIsChecked(boolean isChecked) {
this.isChecked = isChecked;
}
public String getSecFilterName() {
return secFilterName;
}
public void setSecFilterName(String secFilterName) {
this.secFilterName = secFilterName;
}
public String getSecFilterId() {
return secFilterId;
}
public void setSecFilterId(String secFilterId) {
this.secFilterId = secFilterId;
}
}
}
Now I wish to send list of Primary data from one activity to other
You can achieve this with a Bundle.
// Important - use array list not regular list.
// MyModel must implement Parcelable
ArrayList<MyModel> myList;
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("my_key", myList);
intent.putExtras(bundle);
If your list must be of type List you can convert it at the last minute.
bundle.putParcelableArrayList("my_key", new ArrayList<MyModel>(myList));
Then in the receiving activity.
List<MyModel> myList = getIntent().getParcelableArrayListExtra("my_key");
if your MyModel class contains data memeber of only primary or String type then
Implement java.io.Serializable interface in your MyModel class.
Use Intent.putExtra(String name, Serializable value) method to send the list of model with Intent.
Intent.getSerializableExtra(String name) to retrieve list back;
You can pass your java object as a Parcelable object in the bundle. But before that you need your model java class to implement Parcelable interface and override the necessary methods.
Once you have implemented the Parcelable interface you can easily pass your model class(java class) object as Parcelable to the bundle. Small snippet below:
yourBundle.putParcelable(YOUR_OBJ_KEY,yourModelObject);
Here, yourModelObject is the object of your model class that contains all the getters and setters method that you can use.
The point i am trying to make is that you pass your entire java object to the next activity rather than the list. By doing this you will get all the information that you require in your next activity inside this java object.
I think the problem is that your List does indeed not implement Parcelable. Its content does. Try to pass an array, not a List, of Parcelables:
intent.putExtra("my_key", myList.toArray());
Edit: I just saw that it is also possible to send lists but they have to be of type ArrayList. If you don't want to convert your List to an array, try to declare your List as ArrayList<MyModel> myList where MyModel must implement Parcelable.
Phew!
After long hours of work; I come to following conculsion (I'll update answer if I find some better reason).
Parceble/Serializablwe is passing value of list as reference; that's why when I was trying to access that list from other activity; it was returning null.
Currently ; I have maintained a global list(singleton using application class) and updating / retreiving it.

Not printing required result

When trying to test with SOAP UI..I coudn't get correct output for :
public String registerUserByuser(String user)
public String getAllUsers(String userNames)
User.java
package com.ws.entity;
public class User implements java.io.Serializable{
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
private String userName;
private int userId;
}
===============================================================================
RegistrationService.java
package com.ws.Service;
import com.ws.entity.User;
public interface RegistrationService {
String registerUserByuser (String user);
User getuserNameById(int Id );
String getAllUsers (String userNames);
}
===============================================================================
RegistrationServiceImpl.java
package com.ws.test;
import javax.jws.WebMethod;
import javax.jws.WebService;
import com.ws.Service.RegistrationService;
import com.ws.entity.User;
#WebService(name = "UserWS", serviceName="RegService", portName = "CustomerPort", targetNamespace = "http://www.reg.com")
public class RegistrationServiceImpl implements RegistrationService {
#WebMethod
#Override
public String registerUserByuser(String user) {
// TODO Auto-generated method stub
User u = new User();
u.setUserId(555);
u.setUserName("Keith");
return user;
}
#WebMethod
#Override
public User getuserNameById(int Id) {
// TODO Auto-generated method stub
User a = new User();
a.setUserId(888);
a.setUserName("Seth");
return a;
}
#WebMethod
#Override
public String getAllUsers(String userNames) {
return userNames;
// TODO Auto-generated method stub
}
}
Requirement is to develop Bottom Up WebServices:
UserRegistration - Interface
method 1 - registerUser that takes user as input and sends String as output
method 2- getUser that takes id as input and returns back user object
method 3 - getAllusers that returns list of users back to user
Am I writing code in incorrect way?
Your code seems more a mockup than an actual implementation. You are hardcoding the user you return in the getuserNameById method and you also have the mistake pointed out by Invexity in the getAllUsers method.
You need some form of persistence. For prototyping, you could just add a List attribute to your class, to store the users you create. Something like:
private List<User> users = new ArrayList<User>();
and in the registerUserByUser method do something like:
this.users.add(user);
Finally, in the getAllUsers method, you could just:
return this.users;
However, if this is some sort of mockup or test, it would be alright I guess. But if you are building production code, you need to read some more about webservices, persistence and security (given the fact that your domain is about users). This code is definitely not suitable for production for many reasons (hardcoding, lack of actual persistence, security of data, to name a few).

How to use enums to create generic API for Search and Filter of POJOs in Java?

Lets say you have a particular enum called Field:
public enum Field {
ALBUM,
DESCRIPTION
}
And another enum called:
public enum Operator {
CONTAINS,
EQUALS,
LESS_THAN,
GREATER_THAN
}
And you have a corresponding Java interface called Music
public interface Music {
String getAlbum();
String getDescription();
}
Which the implementation looks liks this:
public class MusicImpl implements Music {
#Override
public String getYear() {
return Field.Year.toString();
}
#Override
public String getDescription() {
return Field.DESCRIPTION.toString();
}
#Override
public Object getField(Field field) {
Object myObject = field.getClass();
return myObject;
}
}
How would you use this API to implement the following two methods?
public class MyApp {
#Override
public List<Music> searchMusic(String query) {
// What to put in this?
}
#Override
public List<Music> filterMusic(Field field, Operator op, String query) {
// What to put in?
}
}

Categories