I am currently taking each column based on query and modifying variables based on the current position of the cursor. I was wondering if it would be possible to cut down the size of the code by doing something like this where a different function call would be made based on the column within the cursor that is currently being referenced:
do {
Ticket ticket = new Ticket();
for(int i = 0; i < cursor.getColumnCount(); i++)
{
if (cursor.getString(0) != null) {
/*Where the array contains a list of function calls*/
ticket.arrayList(i);
}
}while(cursor.moveToNext());
Below is the code I currently have. From what I know there isn't anything in Java that works like this, but I'm trying to cut down on the number of lines here as I will eventually have close to one hundred columns that will be pulled into the cursor.
public List<Ticket> getTickets(Context context, SQLiteDatabase db)
{
List<Ticket> ticketInfo = new ArrayList<>();
String selectQuery = "SELECT * FROM " + TABLE_TICKET;
Cursor cursor = null;
try {
cursor = db.rawQuery(selectQuery, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
do {
Ticket ticket = new Ticket();
//Set the ticket number
if (cursor.getString(0) != null) {
ticket.setTicketNr(Integer.parseInt(cursor.getString(0)));
}
//Set the ticket id
if (cursor.getString(1) != null) {
ticket.setTicketId(Integer.parseInt(cursor.getString(1)));
}
//
if (cursor.getString(2) != null) {
ticket.setServiceName(cursor.getString(2));
}
//
if (cursor.getString(3) != null) {
ticket.setServiceHouseNr(Integer.parseInt(cursor.getString(3)));
}
//
if (cursor.getString(4) != null) {
ticket.setServiceDirectional(cursor.getString(4));
}
//
if (cursor.getString(5) != null) {
ticket.setServiceStreetName(cursor.getString(5));
}
//
if (cursor.getString(6) != null) {
ticket.setServiceCommunityName(cursor.getString(6));
}
//
if (cursor.getString(7) != null) {
ticket.setServiceState(cursor.getString(7));
}
//
if (cursor.getString(8) != null) {
ticket.setServiceZip1(Integer.parseInt(cursor.getString(8)));
}
//
if (cursor.getString(9) != null) {
ticket.setServiceZip2(Integer.parseInt(cursor.getString(9)));
}
//
if (cursor.getString(10) != null) {
ticket.setTroubleReported(cursor.getString(10));
}
// Adding exercise to list
if (ticket != null) {
ticketInfo.add(ticket);
}
} while (cursor.moveToNext());
} else {
//No results from query
Toast.makeText(context.getApplicationContext(), "No tickets found", Toast.LENGTH_LONG).show();
}
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
}
}
catch(SQLiteException exception)//If exception is found
{
Log.d(TAG, "Error", exception);
//Display exception
Toast.makeText(context.getApplicationContext(), exception.toString(), Toast.LENGTH_LONG).show();
}
return ticketInfo;
}
Thank you for any insights into this.
I think this would do it. Just advance the cursor and pass it into the Ticket constructor. You may want to add some error checking.
public class Ticket {
private static class Field {
int intValue;
String stringValue;
final Class type;
Field(Class fieldType){
type = fieldType;
}
void set(String value){
if(type.equals(String.class)){
stringValue = value;
}
else {
intValue = Integer.parseInt(value);
}
}
}
private List<Field> fields = new ArrayList<>();
private Field addField(Field field){
fields.add(field);
return field;
}
// This solution relies on adding fields in the order they'll be retrieved in the cursor.
// Other options are possible such as a map by column index.
private Field ticketNumber = addField(new Field(Integer.class));
private Field serviceName = addField(new Field(String.class));
public Ticket(Cursor cursor){
for(int i=0; i < fields.size(); i++){
Field f = fields.get(i);
f.set(cursor.getString(i));
}
}
}
public int getTicketNumber(){
return ticketNumber.intValue;
}
// Don't know if you need setters
public void setTicketNumber(int value){
ticketNumber.intValue = value;
}
// etc for remaining fields
I would also consider using an ORM to make this stuff easier, rather than dealing with cursors.
Related
Following this demo: https://github.com/googlesamples/android-media-controller
I have this
if (playbackState == null) {
Log.e(TAG, "Failed to update media info, null PlaybackState.");
return null;
}
Map<String, String> mediaInfos = new HashMap<>();
mediaInfos.put(getString(R.string.info_state_string),
playbackStateToName(playbackState.getState()));
MediaMetadataCompat mediaMetadata = mController.getMetadata();
if (mediaMetadata != null) {
addMediaInfo(
mediaInfos,
getString(R.string.info_title_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
addMediaInfo(
mediaInfos,
getString(R.string.info_artist_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
addMediaInfo(
mediaInfos,
getString(R.string.info_album_string),
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM));
binding.controlsPage.mediaTitle.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
binding.controlsPage.mediaArtist.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
binding.controlsPage.mediaAlbum.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ALBUM));
final Bitmap art = mediaMetadata.getBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART);
if (art != null) {
binding.controlsPage.mediaArt.setImageBitmap(art);
} else {
binding.controlsPage.mediaArt.setImageResource(R.drawable.ic_album_black_24dp);
}
// Prefer user rating, but fall back to global rating if available.
RatingCompat rating =
mediaMetadata.getRating(MediaMetadataCompat.METADATA_KEY_USER_RATING);
if (rating == null) {
rating = mediaMetadata.getRating(MediaMetadataCompat.METADATA_KEY_RATING);
}
mRatingUiHelper.setRating(rating);
} else {
binding.controlsPage.mediaArtist.setText(R.string.media_info_default);
binding.controlsPage.mediaArt.setImageResource(R.drawable.ic_album_black_24dp);
mRatingUiHelper.setRating(null);
}
final long actions = playbackState.getActions();
`
I'm interested in getting the current pitch and changing it to the one I want.
I can see this api here https://developer.android.com/reference/androidx/media3/session/MediaController#setPlaybackParameters(androidx.media3.common.PlaybackParameters) does what I want, but it's only for the MediaController, not for the MediaControllerCompat.
I tried doing mController.getMediaController()
https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaControllerCompat#getMediaController() with no changes at all.
Any ideas?
I have a requirement where I need to make few Java calls and retrieve necessary values. These are all strings. I need to write this to a console with comma separated values. Like below:
3,Till,,Till,Weiss,,
3,ugilad,,ugilad,ugilad,,
3,admintest,,admin,test,abc#sample.com,
Expected should be:
userid,firstname,lastname,email
3,Till,,Till,Weiss,,
3,ugilad,,ugilad,ugilad,,
3,admintest,,admin,test,abc#sample.com,
Now I need to add columns to these values. Say: userId, firstName, lastName like this. How can I achieve this dynamically using Java code? Here is the code that I wrote:
if (usersList.totalCount != 0 && usersList.totalCount >= 1) {
System.out.println("usersList.totalCount ----->"
+ usersList.totalCount);
for (KalturaUser user : usersList.objects) {
if (user != null) {
if (user.id != null) {
String userRole = getUserRole(user.id);
String cnum = getUserUniqueId(user.email);
// if (userRole != null) {
// if (userRole.equals("adminRole")
// || userRole
// .equals("privateOnlyRole")) {
// sb1.append(action);
if (user.id != null) {
sb.append(user.id);
} else {
sb.append(",");
}
String action = "1";
if (cnum != null) {
if (userRole == null) {
action = "3";
}
} else {
action = "3";
}
if (action != null) {
sb1.append(action);
}
if (cnum != null) {
sb1.append(",").append(cnum);
} else {
sb1.append(",").append(user.id);
sb1.append(",");
}
if (user.firstName != null) {
sb.append(",").append(user.firstName);
sb1.append(",").append(user.firstName);
} else {
sb.append(",");
sb1.append(",");
}
if (user.lastName != null) {
sb.append(",").append(user.lastName);
sb1.append(",").append(user.lastName);
} else {
sb.append(",");
sb1.append(",");
}
if (userRole != null) {
sb.append(",").append(userRole);
// sb1.append(",").append(userRole);
} else {
sb.append(",");
// action = "3";
// sb1.append(action);
}
// sb1.append("1");
if (user.email != null) {
sb.append(",").append(user.email);
sb1.append(",").append(user.email);
} else {
sb.append(",");
sb1.append(",");
}
if (userRole != null) {
sb1.append(",").append(userRole);
} else {
sb1.append(",");
}
// sb1.append("1");
if (user.partnerData != null) {
if (user.partnerData.startsWith("pw")
&& user.partnerData.length() == 43) {
sb.append(",");
}
if (user.partnerData.length() > 43) {
String partnerData = user.partnerData
.substring(44);
sb.append(",").append(partnerData);
}
if (!user.partnerData.startsWith("pw")) {
sb.append(",").append(user.partnerData);
}
}
sb.append(System.getProperty("line.separator"));
sb1.append(System.getProperty("line.separator"));
}
}
}
}
// System.out.println(sb);
System.out.println(sb1);
As per your code you are appending everything to a string buffer(sb) and printing it at once. So in between the loop you could create a string header and assign value based on condition. And outside the loop first print header and then print the buffer. That would be the simplest soultion. However if the amount of data is buge it would be better to use a file. Write everything to a file, construct the header and then after the loop print the header and then print the file. A sample with dummy logic and classes
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
class UserList {
public int totalCount;
public List<KalturaUser> objects;
public UserList(List<KalturaUser> objects) {
this.objects = objects;
this.totalCount = (objects != null) ? objects.size() : 0;
}
}
class KalturaUser {
public String id;
public String email;
public String firstName;
public String lastName;
public String partnerData;
public KalturaUser(String id, String email, String firstName,
String lastName, String partnerData) {
this.id = id;
this.email = email;
this.firstName = firstName;
this.lastName = lastName;
this.partnerData = partnerData;
}
}
public class DynamicHeader {
private static final String NEW_LINE = System.getProperty("line.separator");
public static void main(String[] args) throws Exception {
UserList usersList = init();
RandomAccessFile csv = new RandomAccessFile("temp.csv","rw");
csv.setLength(0); //Clears the file
String header = "";
if (usersList.totalCount >= 1) {
for (KalturaUser user : usersList.objects) {
if (user != null && user.id != null) {
List<String> row = new ArrayList<String>();
String userRole = getUserRole(user.id);
String cnum = getUserUniqueId(user.email);
row.add(getNullSafeValue(user.id));
String action = "1";
if (cnum == null || userRole == null) {
action = "3";
}
row.add(action);
if (cnum != null) {
row.add(cnum);
header = "uniqueid,firstname,lastname,email";
} else {
row.add(user.id);
header = "userid,firstname,lastname,email";
}
row.add(getNullSafeValue(user.firstName));
row.add(getNullSafeValue(user.lastName));
row.add(getNullSafeValue(userRole));
row.add(getNullSafeValue(user.email));
if (user.partnerData != null) {
if (user.partnerData.startsWith("pw")) {
if (user.partnerData.length() == 43) {
row.add("");
} else if (user.partnerData.length() > 43) {
row.add(user.partnerData.substring(44));
}
} else {
row.add(user.partnerData);
}
}
csv.write(row.toString().replace("[", "").replace("]", "").replace(", ", ",").getBytes());
csv.write(NEW_LINE.getBytes());
}
}
}
csv.seek(0);
System.out.println(header);
String data;
while((data = csv.readLine()) != null){
System.out.println(data);
}
csv.close();
}
private static UserList init() {
List<KalturaUser> userObjs = new ArrayList<KalturaUser>();
userObjs.add(new KalturaUser("1", null, "Till", "Till", "Weiss"));
userObjs.add(new KalturaUser("2", null, "ugilad", "ugilad", "ugilad"));
userObjs.add(new KalturaUser("3", "abc#sample.com", "admin", "test", "admintest"));
return new UserList(userObjs);
}
private static String getNullSafeValue(String str) {
return (str != null) ? str : "";
}
private static String getUserUniqueId(String email) {
return (email != null) ? email.substring(0, email.indexOf("#")) : null; //Replace with proper logic
}
private static String getUserRole(String id) {
return ("2".equals(id)) ? "Role 2" : null; //Replace with proper logic
}
}
Apart from this you could do some clean ups in your code like below. Also insteaded of constructing string you could just add it to a list. The toString of list gives you a comma separated value.
(usersList.totalCount != 0 && usersList.totalCount >= 1)
could be reduced to (usersList.totalCount > 0)
if (user != null) {
if (user.id != null) {}
}
If you dont have to do anything specific when (user != null) then, this could be combined to
if (user != null && user.id != null) {}
And
if (cnum != null) {
if (userRole == null) {
action = "3";
}
} else {
action = "3";
}
This could be reduced to
if (cnum == null || userRole == null) {
action = "3";
}
I have implemented two member functions in the same class:
private static void getRequiredTag(Context context) throws IOException
{
//repeated begin
for (Record record : context.getContext().readCacheTable("subscribe")) {
String traceId = record.get("trace_id").toString();
if (traceSet.contains(traceId) == false)
continue;
String tagId = record.get("tag_id").toString();
try {
Integer.parseInt(tagId);
} catch (NumberFormatException e) {
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
//repeated end
tagSet.add(tagId);
}
}
private static void addTagToTraceId(Context context) throws IOException
{
//repeated begin
for (Record record : context.getContext().readCacheTable("subscribe")) {
String traceId = record.get("trace_id").toString();
if (traceSet.contains(traceId) == false)
continue;
String tagId = record.get("tag_id").toString();
try {
Integer.parseInt(tagId);
} catch (NumberFormatException e) {
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
//repeated end
Vector<String> ret = traceListMap.get(tagId);
if (ret == null) {
ret = new Vector<String>();
}
ret.add(traceId);
traceListMap.put(tagId, ret);
}
}
I will call that two member functions in another two member functions(so I can't merge them into one function):
private static void A()
{
getRequiredTag()
}
private static void B()
{
getRequiredTag()
addTagToTraceId()
}
tagSet is java.util.Set and traceListMap is java.util.Map.
I know DRY principle and I really want to eliminate the repeat code, so I come to this code:
private static void getTraceIdAndTagIdFromRecord(Record record, String traceId, String tagId) throws IOException
{
traceId = record.get("trace_id").toString();
tagId = record.get("tag_id").toString();
}
private static boolean checkTagIdIsNumber(String tagId)
{
try {
Integer.parseInt(tagId);
} catch (NumberFormatException e) {
return false;
}
return true;
}
private static void getRequiredTag(Context context) throws IOException
{
String traceId = null, tagId = null;
for (Record record : context.getContext().readCacheTable("subscribe")) {
getTraceIdAndTagIdFromRecord(record, traceId, tagId);
if (traceSet.contains(traceId) == false)
continue;
if (!checkTagIdIsNumber(tagId))
{
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
tagSet.add(tagId);
}
}
private static void addTagToTraceId(Context context) throws IOException
{
String traceId = null, tagId = null;
for (Record record : context.getContext().readCacheTable("subscribe")) {
getTraceIdAndTagIdFromRecord(record, traceId, tagId);
if (traceSet.contains(traceId) == false)
continue;
if (!checkTagIdIsNumber(tagId))
{
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
Vector<String> ret = traceListMap.get(tagId);
if (ret == null) {
ret = new Vector<String>();
}
ret.add(traceId);
traceListMap.put(tagId, ret);
}
}
It seems I got an new repeat... I have no idea to eliminate repeat in that case, could anybody give me some advice?
update 2015-5-13 21:15:12:
Some guys gives a boolean argument to eliminate repeat, but I know
Robert C. Martin's Clean Code Tip #12: Eliminate Boolean Arguments.(you can google it for more details).
Could you gives some comment about that?
The parts that changes requires the values of String tagId and String traceId so we will start by extracting an interface that takes those parameters:
public static class PerformingInterface {
void accept(String tagId, String traceId);
}
Then extract the common parts into this method:
private static void doSomething(Context context, PerformingInterface perform) throws IOException
{
String traceId = null, tagId = null;
for (Record record : context.getContext().readCacheTable("subscribe")) {
getTraceIdAndTagIdFromRecord(record, traceId, tagId);
if (traceSet.contains(traceId) == false)
continue;
if (!checkTagIdIsNumber(tagId))
{
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
perform.accept(tagId, traceId);
}
}
Then call this method in two different ways:
private static void getRequiredTag(Context context) throws IOException {
doSomething(context, new PerformingInterface() {
#Override public void accept(String tagId, String traceId) {
tagSet.add(tagId);
}
});
}
private static void addTagToTraceId(Context context) throws IOException {
doSomething(context, new PerformingInterface() {
#Override public void accept(String tagId, String traceId) {
Vector<String> ret = traceListMap.get(tagId);
if (ret == null) {
ret = new Vector<String>();
}
ret.add(traceId);
traceListMap.put(tagId, ret);
}
});
}
Note that I am using lambdas here, which is a Java 8 feature (BiConsumer is also a functional interface defined in Java 8), but it is entirely possible to accomplish the same thing in Java 7 and less, it just requires some more verbose code.
Some other issues with your code:
Way too many things is static
The Vector class is old, it is more recommended to use ArrayList (if you need synchronization, wrap it in Collections.synchronizedList)
Always use braces, even for one-liners
You could use a stream (haven't tested):
private static Stream<Record> validRecords(Context context) throws IOException {
return context.getContext().readCacheTable("subscribe").stream()
.filter(r -> {
if (!traceSet.contains(traceId(r))) {
return false;
}
try {
Integer.parseInt(tagId(r));
return true;
} catch (NumberFormatException e) {
context.getCounter("Error", "tag_id not a number").increment(1);
return false;
}
});
}
private static String traceId(Record record) {
return record.get("trace_id").toString();
}
private static String tagId(Record record) {
return record.get("tag_id").toString();
}
Then could do just:
private static void getRequiredTag(Context context) throws IOException {
validRecords(context).map(r -> tagId(r)).forEach(tagSet::add);
}
private static void addTagToTraceId(Context context) throws IOException {
validRecords(context).forEach(r -> {
String tagId = tagId(r);
Vector<String> ret = traceListMap.get(tagId);
if (ret == null) {
ret = new Vector<String>();
}
ret.add(traceId(r));
traceListMap.put(tagId, ret);
});
}
tagId seems to be always null in your second attempt.
Nevertheless, one approach would be to extract the code that collects tagIds (this seems to be the same in both methods) into its own method. Then, in each of the two methods just iterate over the collection of returned tagIds and do different operations on them.
for (String tagId : getTagIds(context)) {
// do method specific logic
}
EDIT
Now I noticed that you also use traceId in the second method. The principle remains the same, just collect Records in a separate method and iterate over them in the two methods (by taking tagId and traceId from records).
Solution with lambdas is the most elegant one, but without them it involves creation of separate interface and two anonymous classes which is too verbose for this use case (honestly, here I would rather go with a boolean argument than with a strategy without lambdas).
Try this approach
private static void imYourNewMethod(Context context,Boolean isAddTag){
String traceId = null, tagId = null;
for (Record record : context.getContext().readCacheTable("subscribe")) {
getTraceIdAndTagIdFromRecord(record, traceId, tagId);
if (traceSet.contains(traceId) == false)
continue;
if (!checkTagIdIsNumber(tagId))
{
context.getCounter("Error", "tag_id not a number").increment(1);
continue;
}
if(isAddTag){
Vector<String> ret = traceListMap.get(tagId);
if (ret == null) {
ret = new Vector<String>();
}
ret.add(traceId);
traceListMap.put(tagId, ret);
}else{
tagSet.add(tagId);
}
}
call this method and pass one more parameter boolean true if you want to add otherwise false to get it.
I have dug into the Android sources and found that under the hood, each time an Audio route event occurs, an AudioRoutesInfo object is based to the internal updateAudioRoutes method in MediaRouter:
void updateAudioRoutes(AudioRoutesInfo newRoutes) {
if (newRoutes.mMainType != mCurAudioRoutesInfo.mMainType) {
mCurAudioRoutesInfo.mMainType = newRoutes.mMainType;
int name;
if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADPHONES) != 0
|| (newRoutes.mMainType&AudioRoutesInfo.MAIN_HEADSET) != 0) {
name = com.android.internal.R.string.default_audio_route_name_headphones;
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
} else if ((newRoutes.mMainType&AudioRoutesInfo.MAIN_HDMI) != 0) {
name = com.android.internal.R.string.default_media_route_name_hdmi;
} else {
name = com.android.internal.R.string.default_audio_route_name;
}
sStatic.mDefaultAudioVideo.mNameResId = name;
dispatchRouteChanged(sStatic.mDefaultAudioVideo);
}
final int mainType = mCurAudioRoutesInfo.mMainType;
boolean a2dpEnabled;
try {
a2dpEnabled = mAudioService.isBluetoothA2dpOn();
} catch (RemoteException e) {
Log.e(TAG, "Error querying Bluetooth A2DP state", e);
a2dpEnabled = false;
}
if (!TextUtils.equals(newRoutes.mBluetoothName, mCurAudioRoutesInfo.mBluetoothName)) {
mCurAudioRoutesInfo.mBluetoothName = newRoutes.mBluetoothName;
if (mCurAudioRoutesInfo.mBluetoothName != null) {
if (sStatic.mBluetoothA2dpRoute == null) {
final RouteInfo info = new RouteInfo(sStatic.mSystemCategory);
info.mName = mCurAudioRoutesInfo.mBluetoothName;
info.mDescription = sStatic.mResources.getText(
com.android.internal.R.string.bluetooth_a2dp_audio_route_name);
info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO;
sStatic.mBluetoothA2dpRoute = info;
addRouteStatic(sStatic.mBluetoothA2dpRoute);
} else {
sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.mBluetoothName;
dispatchRouteChanged(sStatic.mBluetoothA2dpRoute);
}
} else if (sStatic.mBluetoothA2dpRoute != null) {
removeRouteStatic(sStatic.mBluetoothA2dpRoute);
sStatic.mBluetoothA2dpRoute = null;
}
}
if (mBluetoothA2dpRoute != null) {
if (mainType != AudioRoutesInfo.MAIN_SPEAKER &&
mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false);
} else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) &&
a2dpEnabled) {
selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false);
}
}
}
Unfortunately, the only thing I have found that is exposed about the device type in the MediaRouter callbacks, is the internal string resource name of the device (e.g. Phone or Headphones). However, you can see that under the hood, this AudioRoutesInfo object has references to whether the device was a headphone, HDMI etc.
Has anyone found a solution to get at this information? The best way I have found is to use the internal resource names, which is pretty ugly. God, if they would just provide the AudioRoutesInfo object all this information could be accessed without having to rely on a resource hack.
In another class im using the setRating to change the ratings of these songs, however I'm not sure what I need to do to this code to be able to change the rating permanently. Thanks in advance.
import java.util.*;
public class LibraryData {
static String playCount() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
static int setRating(int stars) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
private static class Item {
Item(String n, String a, int r) {
name = n;
artist = a;
rating = r;
}
// instance variables
private String name;
private String artist;
private int rating;
private int playCount;
public String toString() {
return name + " - " + artist;
}
}
// with a Map you use put to insert a key, value pair
// and get(key) to retrieve the value associated with a key
// You don't need to understand how this works!
private static Map<String, Item> library = new TreeMap<String, Item>();
static {
// if you want to have extra library items, put them in here
// use the same style - keys should be 2 digit Strings
library.put("01", new Item("How much is that doggy in the window", "Zee-J", 3));
library.put("02", new Item("Exotic", "Maradonna", 5));
library.put("03", new Item("I'm dreaming of a white Christmas", "Ludwig van Beethoven", 2));
library.put("04", new Item("Pastoral Symphony", "Cayley Minnow", 1));
library.put("05", new Item("Anarchy in the UK", "The Kings Singers", 0));
}
public static String listAll() {
String output = "";
Iterator iterator = library.keySet().iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
Item item = library.get(key);
output += key + " " + item.name + " - " + item.artist + "\n";
}
return output;
}
public static String getName(String key) {
Item item = library.get(key);
if (item == null) {
return null; // null means no such item
} else {
return item.name;
}
}
public static String getArtist(String key) {
Item item = library.get(key);
if (item == null) {
return null; // null means no such item
} else {
return item.artist;
}
}
public static int getRating(String key) {
Item item = library.get(key);
if (item == null) {
return -1; // negative quantity means no such item
} else {
return item.rating;
}
}
public static void setRating(String key, int rating) {
Item item = library.get(key);
if (item != null) {
item.rating = rating;
}
}
public static int getPlayCount(String key) {
Item item = library.get(key);
if (item == null) {
return -1; // negative quantity means no such item
} else {
return item.playCount;
}
}
public static void incrementPlayCount(String key) {
Item item = library.get(key);
if (item != null) {
item.playCount += 1;
}
}
public static void close() {
// Does nothing for this static version.
// Write a statement to close the database when you are using one
}
}
Inside Item, you should write this method:
public static void setRating(int rating0) {
rating = rating0;
}
You should also change your instance variables into static variables by calling them "public static" instead of just "public."