In my main activity I have two lists:
private List<Feed> feedItems;
private ArrayList<Object> adItems() {
ArrayList<Object> adItems = new ArrayList<>();
adItems.add("image");
adItems.add("image");
adItems.add("image");
return adItems;
}
The first list represents my feedItems, which are taken from my network model. The second list is simply a list of static images. I'm trying to set up native advertisements but I'm taking it a step back and simply supplying my feed with images to prove that overriding my RecyclerAdapter to produce multiple views works.
feedRecyclerAdapter = new FeedRecyclerAdapter(this, feedItems, new ImageLoader(new FeedItemFileCache(this)), adItems());
Here I pass my adItems() list of objects in the my FeedRecyclerAdapter as the last paramater, and in the adapter class itself I call it in the constructor:
public FeedRecyclerAdapter(Context context, List<Feed> feedItems, ImageLoader feedItemImageLoader, List<Object> adItems) {
this.context = context;
this.feedItems = feedItems;
this.feedItemImageLoader = feedItemImageLoader;
feedItems.addAll(adItems);
}
This last line feedItems.addAll(adItems); is where I get the following error message:
Error:(43, 18) error: no suitable method found for addAll(List<Object>)
method Collection.addAll(Collection<? extends Feed>) is not applicable
(argument mismatch; List<Object> cannot be converted to Collection<? extends Feed>)
method List.addAll(Collection<? extends Feed>) is not applicable
(argument mismatch; List<Object> cannot be converted to Collection<? extends Feed>)
My Feed object looks like this:
public class Feed {
public static final String CLASS_NAME = "Feed";
public static final String MARKET_CLASS_NAME = "MarketFeed";
private String objectId;
private String createdAt;
/**
* Can be a ParsePointer but we are using a relational include query to get the whole object
*/
private Design designId;
// Not part of the model, calculated at run time.
private String timestampText;
private boolean isInPersonalGallery;
private boolean isLiked;
private List<Comment> comments;
// Related to Market Feed Items
private DisplayedSide displayedSide = DisplayedSide.FRONT;
public enum DisplayedSide {
FRONT,
BACK
}
public String getObjectId() {
return objectId;
}
public Design getDesign() {
return designId;
}
public Date getCreatedAt() {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
Date date = null;
try {
date = dateFormat.parse(createdAt);
} catch (ParseException e) {
e.printStackTrace();
Log.d("Feed", "Couldn't parse createdAt date when requested " + createdAt);
}
return date;
}
public String getTimestampText() {
return timestampText;
}
public void setTimestampText(String timestampText) {
this.timestampText = timestampText;
}
public boolean isInPersonalGallery() {
return isInPersonalGallery;
}
public void setInPersonalGallery(boolean inPersonalGallery) {
isInPersonalGallery = inPersonalGallery;
}
public boolean isLiked() {
return isLiked;
}
public void setLiked(boolean liked) {
isLiked = liked;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
public DisplayedSide getDisplayedSide() {
return displayedSide;
}
public void setDisplayedSide(DisplayedSide displayedSide) {
this.displayedSide = displayedSide;
}
}
In summary, I'm trying to sprinkle some images, or adItems, between the main objects in my Collection, feedItems. Why can't I simply attach them to my main list? And what can I do instead?
you are set in wrong array
feedItems.addAll(adItems);//you are set adItems in wrong arraylist (feedItems is a feetItem array list not a adItem list)
public FeedRecyclerAdapter(Context context, List<Feed> feedItems, ImageLoader feedItemImageLoader, List<Object> adItems) {
this.context = context;
this.feedItems = feedItems;
this.feedItemImageLoader = feedItemImageLoader;
feedItems.addAll(adItems);
}`
In the onCreate method of my main activity I set adItems to be a Feed list, then passed it to my RecyclerAdapter constructor:
List<Feed> adItems = new ArrayList<>();
feedRecyclerAdapter = new FeedRecyclerAdapter(this, feedItems, new ImageLoader(new FeedItemFileCache(this)), adItems);
In my RecyclerAdapter class I added all adItems to the feedItems list so that I could operate over a single list:
public FeedRecyclerAdapter(Context context, List<Feed> feedItems, ImageLoader feedItemImageLoader, List<Feed> adItems) {
this.context = context;
this.feedItems = feedItems;
this.feedItemImageLoader = feedItemImageLoader;
feedItems.addAll(adItems);
}
Related
Context
I've been attempting to display data from Firestore in a FirestoreRecyclerAdapter, however this data is basically nested Maps, so a direct approach using the Query function is not ideal. Here is an image of my data structure:
Notice that ServiceOrder, client and vehicle are all Maps. In my Java code, ServiceOrder is made up of a Client and Vehicle objects.
So, if I were to use .setQuery(query, ServiceOrder.class), it would attempt to Map all of the data into ServiceOrder objects. But since my document is structured the way it is, that is not possible.
Issue
I suppose this could be fixed by mapping all documents into an object of a new class, similar to what is done here: https://medium.com/firebase-tips-tricks/how-to-map-an-array-of-objects-from-cloud-firestore-to-a-list-of-objects-122e579eae10.
Even though I can see how it could be done using a normal RecyclerView and using a custom adapter, could the same solution be used in FirestoreRecyclerAdapter? Because I did try to create something akin to the solution in the link, but couldn't get it to work.
My code
Here is where I'm setting up the RecyclerView and Querying the data from Firestore:
private void setupRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.recyclerViewOs);
Query query = osRef.orderBy("ServiceOrder",
Query.Direction.ASCENDING); //This is the issue.
//How could I map the documents here?
FirestoreRecyclerOptions<ServiceOrder> options =
new FirestoreRecyclerOptions.Builder<ServiceOrder>()
.setQuery(query, ServiceOrder.class)
.build();
listAdapter = new FirestoreAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(listAdapter);
}
My FirestoreRecyclerAdapter, where I'm binding my Views. The onBindViewHolder returns NPE for every View. This is the problem with the nested Maps described early.
public class FirestoreAdapter extends FirestoreRecyclerAdapter<ServiceOrder, FirestoreAdapter.ViewHolder> {
#Override
protected void onBindViewHolder(#NonNull ViewHolder holder, int position, #NonNull ServiceOrder model) {
holder.osIdItem.setText(String.valueOf(model.getId()));
holder.osClientItem.setText(model.getPaymentForm());
holder.osDateItem.setText(model.getPaymentForm());
holder.osValueItem.setText(String.valueOf(model.getTotalValue()));
}
And finally, my ServiceOrder class. Getters/Setters were removed to increase readability.
public class ServiceOrder {
public Client client;
public Vehicle vehicle;
private String service;
private String observation;
private String paymentForm;
private String date;
private double totalValue;
private int id;
public ServiceOrder() {
}
private ServiceOrder(ServiceOrderBuilder serviceOrderBuilder){
this.client = serviceOrderBuilder.client;
this.vehicle = serviceOrderBuilder.vehicle;
this.service = serviceOrderBuilder.service;
this.paymentForm = serviceOrderBuilder.paymentForm;
this.observation = serviceOrderBuilder.observation;
this.totalValue = serviceOrderBuilder.value;
this.date = serviceOrderBuilder.date;
}
public static class ServiceOrderBuilder {
private Vehicle vehicle;
private Client client;
private final String service;
private final String paymentForm;
private final int id;
private final double value;
private final String date;
private String observation;
public ServiceOrderBuilder(Client client, Vehicle vehicle,
String service, String paymentForm,
int id, double value, String date) {
this.client = client;
this.vehicle = vehicle;
this.service = service;
this.paymentForm = paymentForm;
this.id = id;
this.value = value;
this.date = date;
}
public ServiceOrder.ServiceOrderBuilder observation(String observation) {
this.observation = observation;
return this;
}
public ServiceOrder build() {
ServiceOrder serviceOrder = new ServiceOrder(this);
return serviceOrder;
}
}
}
My attempt
As suggested in another post, I attempted to create a new ServiceOrderDocument in order to map all documents into an object of this class. The class:
public class ServiceOrderDocument {
ServiceOrder serviceOrder;
public ServiceOrderDocument() {}
public ServiceOrderDocument(ServiceOrder serviceOrder) {
this.serviceOrder = serviceOrder;
}
#PropertyName("ServiceOrder")
public ServiceOrder getServiceOrder() {
return serviceOrder;
}
}
Ànd pass this into the Adapter found in the private void setupRecyclerView(). However, the Adapter expects a QuerySnapshot, so I feel like I'm stuck here.
Reproducing the issue
If you'd like to try it out yourself, the best way would be to have three Classes, with one of them having objects from the other two. A example would be a Sale class having objects from Salesman and Product.
Proceed to write a Sale object into your Firestore database, and see how it creates a nested document. Then, try to display that Sale in a RecyclerView using FirestoreRecyclerAdapter. Your onBindViewHolder should have a Sale model that would get the data from it's getters.
Edit
So using a List to get the content seems to work at a first glance, by using Cast I could pass it as a adapter for the FirestoreRecyclerAdapter, however, it does not work for the startListening() methods. Here's what I did:
private void setupRecyclerView() {
docRef.get().addOnCompleteListener(task -> {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
services = document.toObject(ServiceOrderDocument.class).services;
RecyclerView recyclerView = findViewById(R.id.recyclerViewOs);
Query query = osRef.orderBy("ServiceOrder",
Query.Direction.ASCENDING);
FirestoreRecyclerOptions<ServiceOrder> options =
new FirestoreRecyclerOptions.Builder<ServiceOrder>()
.setQuery(query, ServiceOrder.class)
.build();
// listAdapter = new FirestoreAdapter(options);
services = (List<ServiceOrder>) new FirestoreAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter((RecyclerView.Adapter) services);
}
}
});
}
However, the following issue is created:
#Override
protected void onStart() {
super.onStart();
listAdapter.startListening();//NPE Error
services.startListening();//Can't use method
}
For those looking for an answer, read Alex Mamo comments and his post at:
https://medium.com/firebase-tips-tricks/how-to-map-an-array-of-objects-from-cloud-firestore-to-a-list-of-objects-122e579eae10.
For my solution, I did need a ServiceDocument class to help me map my documents so I could use it in my Adapter. This is what the class looks like:
public class ServiceDocument {
public ServiceOrder serviceOrder;
public ServiceDocument() {
}
#PropertyName("serviceOrder")
public ServiceOrder getServiceOrder() {
return serviceOrder;
}
}
Then, in your Activity or wherever you are managing your Recyler/Adapter, you would need something like this
Query query = osRef.orderBy("serviceOrder",
Query.Direction.ASCENDING);
FirestoreRecyclerOptions<ServiceDocument> options =
new FirestoreRecyclerOptions.Builder<ServiceDocument>()
.setQuery(query, ServiceDocument.class)
.build();
listAdapter = new FirestoreAdapter(options);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setAdapter(listAdapter);
Last but not least, make sure your Adapter class has been adapted for your new class.
public class FirestoreAdapter extends FirestoreRecyclerAdapter<ServiceDocument, FirestoreAdapter.ViewHolder> {
public FirestoreAdapter(#NonNull FirestoreRecyclerOptions<ServiceDocument> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull ViewHolder holder, int position, #NonNull ServiceDocument model) {
holder.osIdItem.setText(String.valueOf(model.getServiceOrder().getId()));
holder.osClientItem.setText(model.getServiceOrder().getClient().getName());
holder.osDateItem.setText(model.getServiceOrder().getDate());
holder.osValueItem.setText(String.valueOf(model.getServiceOrder().getTotalValue()));
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View view = layoutInflater.inflate(R.layout.layout_os_item, parent, false);
return new FirestoreAdapter.ViewHolder(view);
}
I am using MVVM structure and my query in Dao looks like:
#Query("SELECT * FROM Sorted WHERE date LIKE :date AND categoryChart = :category")
LiveData<List<Sorted>> getSortedDiagramData(String date, String category);
In Repository I need to execute this method in AsyncTask, but I don't understand how to do it.
What I've tried:
public LiveData<List<Sorted>> getSortedDiagramData(String date, String category){
String[] array = new String[2];
array[0] = date;
array[1] = category;
return new GetSortedDiagramDataAsyncTask(sortedDao).execute(array);
}
And then:
private static class GetSortedDiagramDataAsyncTask extends AsyncTask<String[], Void, LiveData<List<Sorted>>> {
private SortedDao sortedDao;
private GetSortedDiagramDataAsyncTask(SortedDao sortedDao){
this.sortedDao = sortedDao;
}
#Override
protected LiveData<List<Sorted>> doInBackground(String[] ... strings) {
String date1 = String.valueOf(strings[0]);
String category1 = String.valueOf(strings[1]);
LiveData<List<Sorted>> list = sortedDao.getSortedDiagramData(date1, category1);
return list;
}
}
But when I pass "array" to execute() there is an error "Incompatible types".
Could you please suggest how I can solve this problem? Thanks for any help.
You can pass it in the constructor:
private String date, category;
private SortedDao sortedDao;
public GetSortedDiagramDataAsyncTask(SortedDao sortedDao, String date, String category) {
this.date = date;
this.category = category;
this.sortedDao = sortedDao;
}
#Override
protected LiveData<List<Sorted>> doInBackground(String[]... strings) {
LiveData<List<Sorted>> list = sortedDao.getSortedDiagramData(date, category);
return list;
}
Call it as:
new GetSortedDiagramDataAsyncTask(sortedDao, "date", "category").execute();
Another way would be to use this:
GetSortedDiagramDataAsyncTask(sortedDao).execute(date,category);
I have two activities, one to create an Assessment object, and another to list the Assessment objects in Firebase, however I've encountered an issue: the POJO is able to serialize to JSON just fine, however the FirebaseRecyclerAdapter doesn't seem to be able to return the JSON data to the object type.
Here is my object file:
#IgnoreExtraProperties
public class Assessment {
private String company;
private String industry;
private String location;
private String product;
private String ownerId;
private String ownerName;
private boolean isDraft;
private boolean isQuickWalk;
private Map<String, Category> categories;
public Assessment() {
// Default constructor required for calls to DataSnapshot.getValue()
}
public Assessment(String companyName, String industryName, String locationName,
String productName, String ownerId, String ownerName, boolean isDraft, boolean isQuickWalk, Map<String, Category> categories) {
this.company = companyName;
this.industry = industryName;
this.location = locationName;
this.product = productName;
this.ownerId = ownerId;
this.ownerName = ownerName;
this.isDraft = isDraft;
this.isQuickWalk = isQuickWalk;
this.categories = categories;
}
public String getCompanyName() {
return company;
}
public String getIndustryName() {
return industry;
}
public String getLocationName() {
return location;
}
public String getProductName() {
return product;
}
public String getOwnerName() {
return ownerName;
}
public boolean getIsDraft() {
return isDraft;
}
public boolean getIsQuickWalk() {
return isQuickWalk;
}
Based on this, I use this code to write to Firebase and it all works fine:
String key = mDatabaseRef.child(FIREBASE_ASSESSMENTS).push().getKey();
Assessment assessment = new Assessment(editCompanyText, editLocationText,
editIndustryText, editProductText, uid,
currentUser.getEmail(), isDraft, isQuickWalk, null);
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put("/" + FIREBASE_ASSESSMENTS + "/" + key,
assessment);
mDatabaseRef.updateChildren(childUpdates);
However, when I try to read from the database I believe this is where the problem lies:
FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder> adapter;
mRecyclerView = (RecyclerView) findViewById(R.id.draft_recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
Query query = mEvalRef;
FirebaseRecyclerOptions<Assessment> options = new FirebaseRecyclerOptions.Builder<Assessment>()
.setQuery(query, Assessment.class)
.build();
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(options) {
#Override
protected void onBindViewHolder(ViewDraftsViewHolder holder, int position, Assessment model) {
if(model.getIsDraft()) {
holder.companyName.setText(model.getCompanyName());
holder.industryName.setText(model.getIndustryName());
holder.locationName.setText(model.getLocationName());
holder.productName.setText(model.getProductName());
holder.ownerName.setText(model.getOwnerName());
if(model.getIsQuickWalk()) {
holder.isQuickWalk.setText("Quick Walkthrough");
} else {
holder.isQuickWalk.setText("Full Questionnaire");
}
}
}
#Override
public ViewDraftsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.completed_and_drafts_list_item, parent, false);
return new ViewDraftsViewHolder(view);
}
};
mRecyclerView.setAdapter(adapter);
private static class ViewDraftsViewHolder extends RecyclerView.ViewHolder {
TextView companyName;
TextView industryName;
TextView locationName;
TextView productName;
TextView ownerName;
TextView isQuickWalk;
public ViewDraftsViewHolder(View itemView) {
super(itemView);
companyName = (TextView) itemView.findViewById(R.id.companyView);
industryName = (TextView) itemView.findViewById(R.id.industryView);
locationName = (TextView) itemView.findViewById(R.id.locationView);
productName = (TextView) itemView.findViewById(R.id.productView);
ownerName = (TextView) itemView.findViewById(R.id.ownerName);
isQuickWalk = (TextView) itemView.findViewById(R.id.isQuickWalkView);
}
}
I'm not exactly sure where I'm going wrong that the FirebaseRecyclerAdapter is unable to convert the data back to an Assessment Object. Did i not set the object up correctly? Did I not set the RecyclerAdapter up correctly? This is how the data looks in Firebase
"-KzB39l1KH6MyEsgr6Ke" : {
"companyName" : "testing ",
"industryName" : "at",
"isDraft" : true,
"isQuickWalk" : true,
"locationName" : "five fifteen",
"ownerName" : "test#email.com",
"productName" : "please ignore"
},
any help you can give me would be excellent, I have been struggling with wrapping my head around this for a few days. Thanks!!
At this line:
Query query = mEvalRef;
I assume mEvalRef is a database reference, can you show it because its not clear how you query the data from the database.
just add (mEvalRef), in order to find the problem.
Edit
in your (Assessment) class , I noticed that there is no setter methods for the variable, add setter for each variable in the class and see if this helps.
EDIT 2
in your code where you try to read the values.
remove this
FirebaseRecyclerOptions<Assessment> options = new FirebaseRecyclerOptions.Builder<Assessment>()
.setQuery(query, Assessment.class)
.build();
and in this line or part of the adapter initialization:
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(options)
remove the (options) parameter and change the above line of code to this:
adapter = new FirebaseRecyclerAdapter<Assessment, ViewDraftsViewHolder>(Assessment.class, R.layout.completed_and_drafts_list_item, ViewDraftsViewHolder.class, query )
next remove this code:
#Override
public ViewDraftsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.completed_and_drafts_list_item, parent, false);
return new ViewDraftsViewHolder(view);
}
and finally change the (private) to (public) in this:
private static class ViewDraftsViewHolder extends RecyclerView.ViewHolder {
and don't forget to keep the setters for variables in assessment class and make the variables public as I told you.
EDIT 3
now forget about EDIT 2 and retype your code the way you originally did it and just do this after you configured everything:
in the method where you initialize the adapter, add before this:
mRecyclerView.setAdapter(adapter);
this:
adapter.startListening();
I'm receiving these errors when I tried to populate a list view with firebase adapter using firebase UI
com.google.firebase.database.DatabaseException: Failed to convert
value of type java.util.HashMap to String
com.google.firebase.database.DatabaseException: Class
java.util.HashMap has generic type parameters, please use
GenericTypeIndicator instead
Here Is the code
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
DatabaseReference a = ref.child("info");
final FirebaseListAdapter<String> adapter =
new FirebaseListAdapter<String>(this,String.class,android.R.layout.simple_list_item_1,a) {
#Override
protected void populateView(View v, String model, int position) {
TextView text = (TextView) findViewById(android.R.id.text1);
text.setText(model);
}
here is an example of json data
"info" : {
"KSTUJILdwPN305Fs7ujhga4knlG3" : {
"File Info" : {
"-JFRkA855rfOU7GtcK4" : {
"Name" : "John",
"Adress" : "Test Adress",
"Favourite_food" : "Bread",
},
info node does not refer to your data model. It may contain children nodes. So to reach the model, you should use a reference like this.
DatabaseReference a = ref.child("info").child(info_id).child("File Info").child(file_id);
and you should have a FileInfo model instead of String model to use in
populateView(View v, FileInfo model, int position):
and model
public class FileInfo {
private String Name;
private String Adress;
private String Favourite_food;
public FileInfo() {
}
public FileInfo(String Name, String Adress, String Favourite_food) {
this.Name = Name;
this.Adress = Adress;
this.Favourite_food = Favourite_food;
}
public String getName() {
return Name;
}
public void setName(String Name) {
this.Name = Name;
}
public String getAdress() {
return Adress;
}
public void setAdress(String Adress) {
this.Adress = Adress;
}
public String getFavourite_food() {
return Favourite_food;
}
public void setFavourite_food(String Favourite_food) {
this.Favourite_food = Favourite_food;
}
}
final FirebaseListAdapter<String> adapter = new FirebaseListAdapter<String>(this,String.class,android.R.layout.simple_list_item_1,a)
public FirebaseListAdapter(Activity activity,
java.lang.Class<T> modelClass,
int modelLayout,
com.firebase.client.Firebase ref)
modelClass - Firebase will marshall the data at a location into an instance of a class that you provide
replace the constructor's 2nd parameter (String.class) with a POJO with the fields from info (name, address, favouriteFood)
FirebaseListAdapter
Edit:
You should also use getters in the populateView method
I've run into some funky behavior with generics and I was wondering if someone could shed some light as to why this is happening. To start, I have a class Foo which has a field id. The hashCode method on Foo just returns the id. In another class I create a Map<Foo, Double> bar = new HashMap<Foo, Double().
Then, at a later part of the code the strangeness starts, and I am able to do the following (simplified here):
Long baz = new Long(1);
bar.get(baz);
So, my question is, Why doesn't the compiler and catch this and report it as an error?
EDIT: I made one mistake in my initial question in that get is the method that works, not put. I have posted the full code below.
Map<WebPage, Double> scoresForPhrase = new HashMap<WebPage, Double>();
// Now that we have a list of matching docs, we can calculate the
// Score of each word in the phrase for each document
for (String term: phrase.getWords()) {
TreeSet<Posting> wordPostings = wordMap.get(term);
for(Long doc: matchingDocs) {
if (docDenomScores.get(doc) == null) {
docDenomScores.put(doc, getDocTotal(doc));
}
// The set is of postings, which are compared by docId, so
// we need a temporary one to enable searching
Posting temp = new Posting(doc, new ArrayList<Integer>());
Posting wordPosting = wordPostings.ceiling(temp);
WebPage page = (WebPage) mWebpageDb
.getPageIdToWebPageTable().get(doc);
score = getTermScore(wordPosting, page,
wordPostings.size());
score = score * queryTermWeights.get(term);
Double curScore = scoresForPhrase.get(doc);
}
}
As for the Foo class, it is:
public class WebPage implements Serializable {
private static final long serialVersionUID = -4907557806357281837L;
private String mUrl;
private int mMaxTf;
private long mPageId;
private long mLastTimeUpdated;
private List<Long> mParentIds;
private long mContentLength;
private String mTitle;
private List<Long> mChildren;
private List<String> mAllUrls;
public WebPage(String url, long pageId, long lastTimeUpdated,
List<Long> parentIds, long contentLength, String title, List<Long> children,
List<String> allUrls) {
super();
this.mUrl = url;
this.mPageId = pageId;
this.mLastTimeUpdated = lastTimeUpdated;
this.mParentIds = parentIds;
this.mContentLength = contentLength;
this.mTitle = title;
this.mChildren = children;
this.mAllUrls = allUrls;
this.mMaxTf = 0;
}
public void setUrl(String mUrl) {
this.mUrl = mUrl;
}
public void setPageId(int mPageId) {
this.mPageId = mPageId;
}
public void setLastTimeUpdated(long mLastTimeUpdated) {
this.mLastTimeUpdated = mLastTimeUpdated;
}
public void setParentIds(List<Long> mParentId) {
this.mParentIds = mParentId;
}
public void setContentLength(long mContentLength) {
this.mContentLength = mContentLength;
}
public void setChildren(List<Long> mChildren) {
this.mChildren = mChildren;
}
public void setAllUrls(List<String> allUrls) {
this.mAllUrls = allUrls;
}
public void setMaxTf(int newTf) {
this.mMaxTf = newTf;
}
public String getUrl() {
return mUrl;
}
public long getPageId() {
return mPageId;
}
public long getLastTimeUpdated() {
return mLastTimeUpdated;
}
public List<Long> getParentIds() {
return mParentIds;
}
public long getContentLength() {
return mContentLength;
}
public List<Long> getChildren() {
return mChildren;
}
public String getTitle() {
return mTitle;
}
public List<String> getAllUrls() {
return mAllUrls;
}
public int getMaxTf() {
return mMaxTf;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof WebPage)) {
return false;
} else {
return ((WebPage)o).mPageId == mPageId;
}
}
#Override
public int hashCode() {
return (int)mPageId;
}
public String toString() {
return mUrl;
}
}
So two things. First, remember that due to type-erasure there is no runtime checking of generic types. The Map<Foo, Double> simply becomes Map<Object, Object>.
Second, with regards to a compiler warning or error, you should get a warning or error if bar is declared of type Map<Foo, Double>. But if it is declared as Map, no warning or error. My guess is that bar is defined as Map bar.
UPDATE
The reason there is no error on get is that by definition get takes an Object not the generic type. It is one of the odd things about the interface.
Map.get
Your Map<Foo, Double> might have been casted to Map:
Map<Foo, Double> barOriginal = new HashMap<Foo, Double();
// ...
Map bar = barOriginal;
// ...
Long baz = new Long(1);
bar.put(baz, new Double(1));