User creating multiple objects from one class during runtime -Java - java

So I have been looking around and reading up a lot of forums and the java documentation but I can't seem to get a solid solution for what I am trying to do.
Essentially I have a Module class as shown below:
/**
* MODULE CLASS
* This class will be the base for every Module inputed into the system
* #author George
*/
public class Module {
// -=VARIABLE DECLARATIONS=-
private String moduleName; /* String variable to store the name of the module */
private String moduleLeader; /* String variable to store the name of the module leader */
// -=GETTERS=-
public String getModuleName() {return this.moduleName;} /* Will return the name of the module */
public String getModuleLeader() {return this.moduleLeader;} /* Will return the name of the module leader */
// -=SETTERS=-
public void setModuleLeader(String l) {this.moduleLeader = l;} /* Sets the name of the module leader to the inputed name */
public void setModuleName(String n) {this.moduleName = n;} //THIS NEEDS TO BE ADDED TO DESIGN DIAGRAMS
// -=CONSTRUCTOR=-
/**
* Constructor to make a new object for the module
* #param n (NAME) - String input to set the name of the module
* #param l (LEADER) - String input to set the name of the module leader
*/
public Module(String n, String l) {
this.moduleName = n;
this.moduleLeader = l;
}
}
On my GUI, each module is represented as its own button which upon clicking will take you to the module's page using CardLayout. I also have a button where the user can add a module, this is where my issue comes into place. Obviously a Module object would be defined as:
Module newModule = new Module("name", "leader");
But how would this allow more than one object to be created. The name of the module would come from user input so there is no way I can put the name of the object in the source code and from what I have read you cannot set the object name using a variable.
Lets say for example, during runtime, the user would want to create two modules. One with the name of "Java" and one with the name of "Python". How would I go about doing this? Obviously the first object would be created just fine using the initialization above, but the name of the object would be stuck as newModule. But then it would not be able to create the second object as it cannot have two objects with the same name. I have spent some time trying to understand HashMaps to see if that could be of any use to me but quite frankly I find it quite confusing and again, I can't tell if that is the correct solution.
I hope I have worded this correctly and you can understand my problem. Any help with this would be greatly appreciated.
Thanks in advance.

Related

JAutodoc: getter comment template is merged with default comment behavior

I am trying to configure JAutodoc such that getter comments are generated containing only the #returns tag, like so:
/**
* #returns The non-null {#linkplain Foo foo} of this {#link IBar}.
*/
public Foo getFoo();
I have configured my getter template to produce this:
However, something must be wrong with my general JAutodoc settings, because what I get instead is a hybrid of my template and a comment parsed from the method name:
/**
* Get foo.
* #returns The non-null {#linkplain Foo foo} of this {#link IBar}.
*/
public Foo getFoo();
These are my settings:
I have removed the 'get' replacement from the replacements list, as well as unchecked the 'etter from field comment' setting as advised in this discussion, but it has not made a noticeable difference. I have also attempted to uncheck the 'Create comment from element name' setting, despite my example getter being part of an interface (in which case there is no element to get the comment from), but JAutodoc doesn't seem to care about that.
I have also tried restarting Eclipse after making each of these changes, in case that mattered. So far, nothing is working. It almost appears as if the comment behavior of getters is hard-coded. Can someone please shed some light on this?
TL;DR
JAutodoc, in its current form, can not do what you want it to do. This is because you are asking for incomplete Javadocs.
Details
(This was fun, and I hope you appreciate the effort :-)
This is a case where you are asking JAutodoc to create incomplete Javadocs. i.e. you are asking for no documentation in the Javadoc. (I personally find the repetitiveness on simple getter annoying too BTW).
The steps that JAutodoc are going through internally is:
Applying your template, so the comment looks exactly as you want - for a moment in time.
This is the bit of code that applies the template. Using your example, the member parameter below is your getFoo method and, as there is no existing comment in your code when you first apply the auto-comment, so the jdi parameter is empty (jdi.isEmpty() == true).
When the template is applied, text looks exactly as you want it too. text gets parsed just as any Javadoc comment would and returned.
From net.sf.jautodoc.source.JavadocCreator:
public JavadocInfo applyTemplate(final IMember member, final JavadocInfo jdi) throws Exception {
final JavadocInfo templateJdi = new JavadocInfo();
final String text = JAutodocPlugin.getContext().getTemplateManager().applyTemplate(member,
config.getProperties());
if (text != null && text.length() > 0) {
templateJdi.parseJavadoc(text);
}
return jdi.isEmpty() ? templateJdi : jdi.merge(templateJdi);
}
Now the JavadocInfo that was returned from applyTemplate is passed to createJavadoc. In createJavadoc the code checks if there is a comment (excluding the #params, #return, etc). As there is not any, it tries to insert some automatically from the information available. Simplistically, it just un-camel-cases the name of the method and makes that the comment.
From net.sf.jautodoc.source.JavadocCreator
public String createJavadoc(final IMethod method, final String indent, final String lineSeparator,
final JavadocInfo jdi) throws JavaModelException {
final List<String> text = jdi.getComment();
if (text.isEmpty()) {
if (config.isCreateDummyComment()) {
if (method.isConstructor()) {
text.add(Constants.JDOC_CONSTRUCTOR);
}
else if (method.isMainMethod()) {
text.add(Constants.JDOC_MAIN);
}
else {
String comment = CommentManager.createComment(config, method.getElementName(),
CommentManager.METHOD, true, true, CommentManager.FIRST_TO_UPPER);
text.add(comment + Constants.DOT);
}
}
else {
text.add("");
}
}
else {
checkForDot(text);
}
Now the code that calls the above two methods is this:
From net.sf.jautodoc.source.SourceManipulator.addJavadoc(IMember):
if (config.isCreateDummyComment()) {
jdi = javadocCreator.applyTemplate(member, jdi);
}
newJavadoc = javadocCreator.createJavadoc((IMethod) member, indent, lineDelimiter, jdi);
As you can see from these code snippets, both applying your template and creating the comment part (that you don't want!) is controlled by the same if statement config.isCreateDummyComment(). That if statement connects to the Create comment from element name option.
Examples
This issue is not happening because the method is a getter, but applies everywhere. Assume you have this bit of code:
/**
* #param myFirstParam this is important and I documented it
*/
public int doThisAndThat(int myFirstParam, int anotherParamHere) {
return 0;
}
And you apply JAutodoc to it (with Complete existing Javadoc) then you get:
With Create comment from element name unset:
/**
*
*
* #param myFirstParam this is important and I documented it
* #param anotherParamHere
* #return
*/
public int doThisAndThat(int myFirstParam, int anotherParamHere) {
return 0;
}
With Create comment from element name set:
/**
* Do this and that.
*
* #param myFirstParam this is important and I documented it
* #param anotherParamHere the another param here
* #return the int
*/
public int doThisAndThat(int myFirstParam, int anotherParamHere) {
return 0;
}
Getting the source
I couldn't find the source on any of the usual suspects (github, etc), but it is available for download here: http://sourceforge.net/projects/jautodoc/files/jautodoc/1.13.0/
So you could, if you desired, edit the source and rebuild your plug-ins. Or file a feature request with the dev.
In Conclusion
JAutodoc, in its current form, can not do what you ask it to do. However, this is essentially by design, because if you say you want to Create comment from element name automatically (internally called Create Dummy Comment) then you want fully complete Javadoc to be created for you.
Finally, keep in mind if there is no comment, then nothing appears in the method summary table and your generated Javadocs simply look incomplete.

Jena custom datatype

For a GeoSPARQL test project I want to have a custom datatype set in Jena. Howerver when I try this through the example provided at the Jena website, it still doesn't work. I get the following result:
_:b0 <http://www.opengis.net/ont/geosparql#asWKT> "POINT (52.83525867111958 6.870789811954563)^^http://www.opengis.net/ont/sf#wktLiteral "^^<java:com.hp.hpl.jena.rdf.model.impl.LiteralImpl> .
And of course I don't want the java:com.hp.hpl.jena.rdf.model.impl.LiteralImpl but http://www.opengis.net/ont/sf#wktLiteral because I wan to work with GeoSPARQL. On this page they have example data that works perfectly with my triple store and spatial index. But the above data doesn't work at all with spatial indexing.
So, my question is, I do I define a custom datatype in my RDF in Jena?
The syntax is
"POINT (52.83525867111958 6.870789811954563)"^^<http://www.opengis.net/ont/sf#wktLiteral>
I just found the answer to my question after a lot of trial and error. To add a custom RDFDatatype to my RDF model I first had to create my own class which extends BaseDatetype and which I called WktLiteral, looking like this:
public class WktLiteral extends BaseDatatype {
public static final String TypeURI = "http://www.opengis.net/ont/sf#wktLiteral";
public static final String CRS84 = "<http://www.opengis.net/def/crs/OGC/1.3/CRS84>";
public static final RDFDatatype wktLiteralType = new WktLiteral();
private WktLiteral() {
super(WktLiteral.TypeURI);
}
/**
* Convert a value of this datatype out
* to lexical form.
*/
public String unparse(Object value) {
return value.toString();
}
/**
* Parse a lexical form of this datatype to a value
*/
public Object parse(String lexicalForm) {
return new TypedValue(String.format("%s %s", WktLiteral.CRS84, lexicalForm), this.getURI());
}
/**
* Compares two instances of values of the given datatype.
* This does not allow rationals to be compared to other number
* formats, Lang tag is not significant.
*
* #param value1 First value to compare
* #param value2 Second value to compare
* #return Value to determine whether both are equal.
*/
public boolean isEqual(LiteralLabel value1, LiteralLabel value2) {
return value1.getDatatype() == value2.getDatatype()
&& value1.getValue().equals(value2.getValue());
}
Where it was quite important to return a TypedLiteral in the parse() method. After which I had to do the following to add something to my RDF model:
TypeMapper.getInstance().registerDatatype(WktLiteral.wktLiteralType);
item.addLiteral(GeoSPARQL.asWKT, ResourceFactory.createTypedLiteral(geom, WktLiteral.wktLiteralType));
Where GeoSPARQL.asWKT is the predicate in the GeoSPARQL vocabulary that I generated through schemagen. geom is the geometry object as well known text and WktLiteral.wktLiteralType is an instance of the above class.
In conclusion the result was the following (notation 3):
_:b0 <http://www.w3.org/2003/01/geo/wgs84_pos#lat_long> "POINT (51.61821756986111 5.542408362751153)" .
thus exactly what I wanted... Thanks for all the input.

ArrayList of ArrayList in Java

I'm new to Java, coming from a C/C++ background. I'm trying to write a music player app for Android and I am working on a library scanning function. I want to have a hierarchical database of the format Artist -> Album -> Song where Artist has a name and a group of Albums, an Album has a name, year, and group of Songs, and a Song has a title, track number, and file location.
I created three classes to store this information:
public class libraryElementArtist
{
public String name;
public ArrayList<libraryElementAlbum> albums;
}
public class libraryElementAlbum
{
public String name;
public String year;
public ArrayList<libraryElementSong> songs;
}
public class libraryElementSong
{
public String name;
public int num;
public String filename;
}
The idea to fill them is simple - scan through each file and add its artist first, then album, then song. Each time it checks to make sure the artist/album does not already exist before creating a new one.
Essentially, I start off creating an ArrayList to store the artist information like this:
ArrayList<libraryElementArtist> libraryData = new ArrayList<libraryElementArtist>();
Then, to add an artist to the database:
libraryElementArtist newEntry = new libraryElementArtist();
newEntry.name = song_artist;
libraryData.add(newEntry);
And then to add an album:
libraryElementAlbum newEntry = new libraryElementAlbum();
newEntry.name = song_album;
libraryData.get(artistIndex).albums.add(newEntry);
where artistIndex is the index of the album's artist in the top-level artist array.
When I run this on the device and step through it in the debugger, the libraryElementArtist items are inserted into the libraryData array and their names are correctly filled in. However, the albums field is listed as null and trying to add albums does not fill in any data.
Sorry if this is a noob question, like I said I'm new to Java and I've searched and can't find what I'm looking for. Also, this is the way I'd do such a task in C++, not sure if it's the correct Java way.
I think is a Inheritance funda, So make your classes hierarchy as like (use of inheritance), So you have to make only one class which has all the derived propertied of its parent class, and make a ArrayList of that class only, So you don't have to make nested ArrayList. (If I am not wrong or if then please explain). :-)
Or generally make only one class which has all the properties, As you described above and use some getter,setter methods for that and using that class make your ArrayList.
create a custom class with getters and setters then create an arraylist as that datatype (your custom class)
List<customClass> foo = ArrayList<customClass>
same as the comment above but more info
All of the constructors should create (not just declare) the ArrayLists. Else they will be null. You can start them at a small size to save space. E.g
songs = new ArrayList(3);

Dynamically naming an instance of a class?

Just a really quick question about something small. The following is part of a programming assignment for my programming 2 class. It focuses on inheritance and multiple classes. I've answered the question but want to consolidate the classes into a main function and actually build something rather than just submitting the bare minimum.
My question is the section of code below. The user runs the program, is presented with a dialog asking him as to what he's like to add (a CD or a Movie, they're both separate classes).
What I would like though, is for the user to actually name the specific instance of the class while the program is running. So, the user will click Movie for example, be prompt to enter a name and then next line to use the constructor in the movie class to create a new instance class with the name the user entered? Is this possible? I tried using a simple string x = JOptionpane and then naming the class x also, but it didn't work. I'm thinking there might be some method that will refer to the string? like contents.x maybe?
thanks in advance!
import javax.swing.JOptionPane;
public class Main
{
public static void main (String args [])
{
Object[] options = {"Movie",
"CD",
"Cancel"};
int n = JOptionPane.showOptionDialog(null, "Would you like to add an item?","Product",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[2]);
switch(n)
{
case 0:
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
}
}
}
If it's not too far beyond your class' content, you could use a Map<String, Media>1 to store instances identified by a runtime-specified string.
Map<String, Media> instances = new HashMap<>();
// snip...
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
instances.put("some user-provided string", moviett);
1Assuming that Movie and CD both extend/implement Media.
Java doesn't work this way, and in fact variable names are much less important than you think and almost don't exist in compiled code. Instead how about using Strings to set a field of the Movie class, perhaps a String field called "name". If you want to retrieve a class instance based on a String, consider using a Map such as a HashMap.

how do I pass information from one class to another

I am creating a program which allows the user to input details of customers. When they have saved each customers record there is the choice to add additional information. I am having trouble getting the the name of the saved file in my append class. I need the filename so I can then save the additional information to the same file already created for the customer. How do I pass the file name from one file to another.
File FName = fileChooser.getSelectedFile();
String name = FName.getName();
public String getname() { return name; }
This code is in my customer class how do I get this information in my append class??
Possibly something like this:
Customer customer = new Customer();
// do some stuff with your customer object, including initiating the File and saving its name to a String field called name
Append append = new Append();
append.foo(customer.getName()); // passes the name of the file to the foo method of class Append
This assumes that you'll only want the name of the file in that one method (though you could save it to a field as part of method foo()). You'd need to implement a method foo(String name) in class Append.
Another option would be to pass it as a constructor of Append:
Append append = new Append(customer.getName());
append.foo();
For this, you'd need to implement a constructor Append(String name) in class Append.
There are a couple of ways to do this depending on what exactly it is you are trying to do.
Give the Append class a member variable of the Customer class
Have the Append class constructor take a parameter that would refer to a Customer, such as a String of name or a Customer object as this is Java
Your question is not entirely clear to me, but here's a problems you might run into based on your description:
What is getName() supposed to return, the name of the file, or the name of the person? If it's supposed to return the file name, then use getFileName() instead - it's clearer!
I don't really understand why you'd need an Append class. Personally, I'd handle appending additional info inside the Customer class. I'd do it so that every time a value is added or changed, the info is saved back into the file like:
class Customer {
public void setForename(String forename) {
this.forename = forename;
save();
}
public void setSurname(String surname) {
this.surname = surname;
save();
}
public void save() {
// clear file
// add new content
String fileContents = "forename="+forname+"&surname="+surname;
// save to file
}
Maybe I'm not understanding your needs correctly though...
In addition to DeadPassive's answer of associating the additional information with the Customer object:
The saving of the Customer data does not belong in the Customer Class. The logic of persisting the data belongs in a seperate layer than the code that deals with manipulating the problem domain. A controller or service class seems like a more appropriate place to put the persistance logic.

Categories

Resources