I am currently getting an array out of bounds exception while executing the line name.firstName = this.firstNames[rand.nextInt(NUM_NAMES)]; Normally I dont have issues finding the source of these exceptions however I have been stuck on this one for some time now. Any help is appreciated, class and stacktrace are pasted below:
public class NameGenerator {
private static final int NUM_NAMES = 200;
private static final File NAMES_FILE = new File("resources/info.dat");
/** a random number generator */
private Random rand;
/** the array of first names */
private String[] firstNames;
/** the array of last names */
private String[] lastNames;
/**
* Default Constructor
*/
public NameGen() {
super();
this.rand = new Random();
try {
readFile();
} catch (IOException exp) {
this.first = new String[] { "foo" };
this.last = new String[] { "bar" };
}
}
/**
* Read the names from the file
*/
private void readNFiles() throws IOException {
List<String> tempFirst = new ArrayList<String>();
List<String> tempLast = new ArrayList<String>();
Scanner scnr = new Scanner(NAMES_FILE);
while (scnr.hasNext()) {
tempFirst.add(scnr.next());
tempLast.add(scnr.next());
}
scnr.close();
int size = tempFirst.size();
this.first = new String[size];
tempFirst.toArray(this.firstNames);
this.last = new String[size];
tempLast.toArray(this.last);
}
/**
* #return a generated name
*/
public FullName generateName() {
FullName name = new FullName();
name.first = this.firstNames[rand.nextInt()];
name.last = this.lastNames[rand.nextInt()];
return name;
}
/**
* Class describing a full name
*/
public static final class FullName {
/** the first name */
public String firstName;
/** the last name */
public String lastName;
}
}
Based on...
try {
readNamesFiles();
} catch (IOException exp) {
this.firstNames = new String[] { "John" };
this.lastNames = new String[] { "Doe" };
}
There is no guarantee that your arrays will contain NUM_NAMES elements (you should be logging the exception at the very least).
So using something like name.firstName = this.firstNames[rand.nextInt(NUM_NAMES)]; has the potional to cause some serious issues, as you've discovered.
Instead, you should work with reality instead of assumptions, using something more like...
name.firstName = this.firstNames[rand.nextInt(this.firstNames.length)];
Here is a summary of your problematic code:
List<String> tempFirstNames = new ArrayList<String>(NUM_NAMES);
int size = tempFirstNames.size();
this.firstNames = new String[size];
FullName name = new FullName();
name.firstName = this.firstNames[rand.nextInt(NUM_NAMES)];
You are using rand.nextInt(NUM_NAMES) as the array index into firstNames. This will generate a number between 0 and NUM_NAMES. The problem is that there is no guarantee that the array firstNames will have a size of NUM_NAMES. As the #AngryProgrammer pointed out, you can use this instead:
name.firstName = this.firstNames[rand.nextInt(firstNames.length)];
Related
I have data of tracks & tracklinks like folowing:
trackname - abc
links - www.abc.com
www.abc1.com
www.abc2.com
trackname - xyz
links - www.xyz.com
www.xyz1.com
www.xyz2.com
I want to make array with in array in Java. so final array would be:
trackdata = {
[0] {
[trackname] = 'abc',
[tracklinks] = {
[0] = "www.abc.com";
[1] = "www.abc1.com";
[2] = "www.abc2.com";
}
},
[1] {
[trackname] = 'xyz',
[tracklinks] = {
[0] = "www.xyz.com";
[1] = "www.xyz1.com";
[2] = "www.xyz2.com";
}
}
I have tried to make this using ArrayList, Map but not succeed.
Map<String,String> map = new HashMap<>();
map.put("trackname", "abc");
ArrayList<String> myLinks= new ArrayList<>();
myLinks.add("www.abc.com");
myLinks.add("www.abc1.com");
myLinks.add("www.abc2.com");
map.put("tracklinks", myLinks);
please help me here.
Consider using a multimap, a map whose values are list objects:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Starter {
public static void main(String[] args) {
Map<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> myLinks= new ArrayList<>();
myLinks.add("www.abc.com");
myLinks.add("www.abc1.com");
myLinks.add("www.abc2.com");
map.put("abc", myLinks);
System.out.println(map); // {abc=[www.abc.com, www.abc1.com, www.abc2.com]}
}
}
You should create a class and then access the properties like you want.
class TrackData {
private String trackme;
private List<String> trackLink;
public String getTrackme() {return trackme;}
public void setTrackme(String trackme) {this.trackme = trackme;}
public List<String> getTrackLink() {return trackLink;}
public void setTrackLink(List<String> trackLink) {this.trackLink = trackLink;}
}
To access it:
#Test
void arrayInArray_Test1() {
List<TrackData> trackData = new ArrayList<>();
trackData.add(new TrackData(){{
setTrackme("abc");
setTrackLink(new ArrayList<String>(){{
add("www.abc.com");
add("www.abc1.com");
add("www.abc2.com");
}});
}});
trackData.add(new TrackData(){{
setTrackme("xyz");
setTrackLink(new ArrayList<String>(){{
add("www.xyz.com");
add("www.xyz1.com");
add("www.xyz2.com");
}});
}});
System.out.println(trackData);
}
If you are using a newer Java version, you can create a record instead of a class.
You can achieve as follows
public class TrackTest {
public static void main(String[] args) {
List<Tracks> trackList = new ArrayList<>();
Tracks track1 = new Tracks("abc");
track1.getTrackLinks().add("www.abc.com");
track1.getTrackLinks().add("www.abc1.com");
track1.getTrackLinks().add("www.abc2.com");
Tracks track2 = new Tracks("xyz");
track2.getTrackLinks().add("www.xyz.com");
track2.getTrackLinks().add("www.xyz1.com");
track2.getTrackLinks().add("www.xyz2.com");
trackList.add(track1);
trackList.add(track2);
System.out.println(trackList);
}
static class Tracks{
private String trackName;
private List<String> trackLinks;
public Tracks(String trackName) {
this.trackName = trackName;
this.trackLinks = new ArrayList<>();
}
public Tracks(String trackName, List<String> trackLinks) {
this.trackName = trackName;
this.trackLinks = trackLinks;
}
public String getTrackName() {
return trackName;
}
public List<String> getTrackLinks() {
return trackLinks;
}
#Override
public String toString() {
return "Tracks [trackName=" + trackName + ", trackLinks=" + trackLinks + "]";
}
}
}
Let me know, if you want other approach.
how are u?
Why u dont do this.
Create class named URL, for example.
public class Url(){
//atributes
String domain;
String url;
//Contructor
public class URL(String domain, String url){
this.domain = domain;
this.url = url;
}
}
In ur main.class, u can create one Arraylist to saves ur instaces of URL.
public static void newURL(){
String domain, url;
Scanner keyboard = new Scanner(System.in);
//ask domain, i will use an example.
System.out.println("What is domain of URL?");
domain = keyboard.nextLine();
System.out.println("What is url?");
url = keyboard.nextLine;
//now, u have atributes of new url
URL url = new URL(domain,url);
}
What its ur objective? It's important question.
If is for simple control in a little program, u can do this
I have a problem with maing java reading a file for me. I have a .txt-file with all the danish islands but somehow it will not display in the console no matter how i try.
This is the class with the main method. From here it reads the file and splits the lines in order to put the data into an ArrayList.
public class DanishIslandFileReader {
private File inFile;
private List<DanishIsland> islandList;
public DanishIslandFileReader(String fName) {
inFile = new File(fName);
}
private void readFile() {
islandList = new ArrayList<DanishIsland>();
Scanner scan = null;
try {
scan = new Scanner(inFile);
} catch (FileNotFoundException fnfe) {
System.out.println(fnfe);
}
while (scan.hasNext()) {
String line = scan.nextLine();
String[] tokens = line.split(" ");
String name = tokens[0];
double circ = Double.parseDouble(tokens[1]);
double area = Double.parseDouble(tokens[2]);
int addr = Integer.parseInt(tokens[3]);
int adkm = Integer.parseInt(tokens[4]);
DanishIsland island = new DanishIsland(name, circ, area, addr, adkm);
System.out.println(island.toString());
islandList.add(island);
}
scan.close();
}
public List<?> getList() {
return islandList;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException {
System.out.println(new File(".").getAbsolutePath());
// DanishIslandFileReader fr = new DanishIslandFileReader("Islands punktum.txt");
DanishIslandFileReader fr = new DanishIslandFileReader("Islands komma.txt");
fr.readFile();
System.out.println("Result:\n" + fr.getList());
}
}
When the line has been split it goes through another class which turns the data into a String and puts it into another Arraylist which will be printed in the consol.
public class DanishIsland {
private String name;
private double circumference;
private double area;
private int addresses;
private int addrPerKm2;
public DanishIsland(String name, double circumference, double area,
int addresses, int addrPerKm2) {
super();
this.name = name;
this.circumference = circumference;
this.area = area;
this.addresses = addresses;
this.addrPerKm2 = addrPerKm2;
}
public String getName() {
return name;
}
public double getCircumference() {
return circumference;
}
public double getArea() {
return area;
}
public int getAddresses() {
return addresses;
}
public int getAddrPerKm2() {
return addrPerKm2;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append(name);
builder.append("\t");
builder.append(circumference);
builder.append("\t");
builder.append(area);
builder.append("\t");
builder.append(addresses);
builder.append("\t");
builder.append(addrPerKm2);
builder.append("\n");
return builder.toString();
}
}
I do not get any errors or exceptions and the program run till it thinks the list has been printed.
Problem is that the list is empty and I can't seem to make any sort of "sout" from the .txt-file. Whar am I doing wrong?
Lolland 298,388 1234,96 38919 32
Bornholm 108,047 588,025 27125 46
Falster 145,926 516,268 26654 52
Mors 139,254 361,745 12374 34
Have you tried debugging it?
I think it is not entering
while (scan.hasNext())
because scan.hasNext returns false.
This could be a file permission issue.
Also this may be related:
Why is hasNext() False, but hasNextLine() is True?
Im fairly new to java and ive been doing som searching for an answer to my problem but i just cant seem to get the output from the arraylist.
I get a red mark under Ordtildikt String arrayoutput = kontrollObjekt.Ordtildikt;saying it cannot be resolved or is not a field. The program is supposed to get userinput and create an arraylist from the input
Interface class
import javax.swing.JOptionPane;
public class Grensesnitt {
public static void main(String[] args) {
Grensesnitt Grensesnitt = new Grensesnitt();
Grensesnitt.meny();
}
Kontroll kontrollObjekt = new Kontroll();
private final String[] ALTERNATIVER = {"Registrere ord","Skriv dikt","Avslutt"};
private final int REG = 0;
private final int SKRIV = 1;
public void meny() {
boolean fortsett = true;
while(fortsett) {
int valg = JOptionPane.showOptionDialog(
null,
"Gjør et valg:",
"Prosjektmeny",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
ALTERNATIVER,
ALTERNATIVER[0]);
switch(valg) {
case REG: regNy();
break;
case SKRIV: regDikt();
break;
default: fortsett = false;
}
}
}
int i = 0;
public void regNy() {
while(i<=16)
{
String Ord = JOptionPane.showInputDialog("Skriv or til diktet: ");
kontrollObjekt.regNy(Ord);
//String Diktord = JOptionPane.showInputDialog("Skriv ord til diktet: ");
//kontrollObjekt.regNy(Diktord);
i = i + 1;
}
}
public void regDikt() {
String arrayoutput = kontrollObjekt.Ordtildikt;
JOptionPane.showMessageDialog(null, arrayoutput);
}
//JOptionPane.showMessageDialog(null, kontrollObjekt.Diktord);
}
Controll Class
import java.util.ArrayList;
public class Kontroll {
public ArrayList<String> Diktord = new ArrayList<String>();
public void regNy(String Ord) {
Diktord.add(Ord);
Diktord.add("\n");
}
public String Ordtildikt(String Ord) {
return Ord=Diktord.toString();
}
}
This is a method, not a variable.
kontrollObjekt.Ordtildikt;
You are trying to call this?
public String Ordtildikt(String Ord) {
return Ord=Diktord.toString();
}
1) Make it return Diktord.toString();
2) Get rid of String Ord unless you are going to use that parameter
3) Actually call the method, e.g. Put some parenthesis.
String arrayoutput = kontrollObjekt.Ordtildikt();
Also, I think this should be the correct regNy method unless you want to falsely report that the list is twice its size.
public void regNy(String Ord) {
Diktord.add(Ord + "\n");
}
So I have a test which is to test the addNewCustomer method which does so by reading in from a text file
#Test
public void testAddNewCustomer() {
System.out.println("addNewCustomer");
try {
File nFile = new File("ProductData.txt");
File file = new File("CustomerData.txt");
Scanner scan = new Scanner(file);
ElectronicsEquipmentSupplier ees = new ElectronicsEquipmentSupplier(1, 1, InputFileData.readProductDataFile(nFile));
ees.addNewCustomer(InputFileData.readCustomerData(scan));
CustomerDetailsList expResult = ees.getDetails();
CustomerDetailsList result = ees.getDetails();
assertEquals(expResult, result);
} catch (IllegalCustomerIDException | IOException | IllegalProductCodeException e) {
fail(e.getMessage());
}
}
The problem that I'm having is to what to have as the expected result? I tried putting a string with the values that I thought would be entered but it then said I can't compare type string with type CustomerDetailsList. Any ideas?
public class CustomerDetailsList {
private final ArrayList<CustomerDetails> customerCollection;
public CustomerDetailsList() {
customerCollection = new ArrayList<>();
}
public void addCustomer(CustomerDetails newCustomer) {
customerCollection.add(newCustomer);
}
public int numberOfCustomers() {
return customerCollection.size();
}
public void clearArray() {
this.customerCollection.clear();
}
/**
*
* #param givenID the ID of a customer
* #return the customer’s details if found, exception thrown otherwise.
* #throws supplierproject.CustomerNotFoundException
*/
public CustomerDetails findCustomer(String givenID) throws CustomerNotFoundException {
CustomerNotFoundException notFoundMessage
= new CustomerNotFoundException("Customer was not found");
int size = customerCollection.size();
int i = 0;
boolean customerFound = false;
while (!customerFound && i < size) {
customerFound = customerCollection.get(i).getCustomerID().equals(givenID);
i++;
}
if (customerFound) {
return customerCollection.get(i - 1);
} else {
throw notFoundMessage;
}
}
#Override
public String toString() {
StringBuilder customerDets = new StringBuilder();
for (int i = 0; i < numberOfCustomers(); i++) {
customerDets.append(customerCollection.get(i).toString()).append("\n");
}
return customerDets.toString();
}
}
The list itself
Generally, you should test if the new customer is in the list. However, the expResult and result from your test are just the same, because at that point the ees already contains the new customer. Therefore the assertion does not make sense.
However, you can test if the Customer List contains the customer with given email (or some unique property of that customer).
I have a library contains a bunch of static *lib files, I wish to access them from JNA (a Java library that allows one to dynamically call `dll's from JAVA Code), so is there a way to magically change static lib to dll?
Code was compiled using Visual studio (hope that is relevant), and I also have appropriate header files.
I do not have access to source code, also I would like to do it using only free (as in beer) tools.
I'm not aware of anyb tools that will do this automatically, but the process is to create a DLL project and add your libraries to the project. For each function in the header file:
int SomeLibFunc( int x, int y );
you would need to create and export your own function in the DLL;
int MyFunc( int x, int y ) {
return SomLibFunc( x, y );
}
The process is quite mechanical, and you may be able to knock up a script using something like perl to create the DLL source files.
Assuming you don't have access to the source, you can simply create a wrapper DLL that exports the functions you need and delegates to the static library.
I did as anon suggested, I did an automatic converter (someone suggested just putting _ddlspec(export) before declaration and compiling dll with this header would work -- well it didn't -- maybe i did something wrong -- I'm Plain Old Java Programmer ;)):
it basically parses header files and turns:
SADENTRY SadLoadedMidFiles( HMEM, USHORT usMaxMidFiles, VOID * );
to:
__declspec(dllexport) SADENTRY DLL_WRAPPER_SadLoadedMidFiles(HMEM param0,
USHORT usMaxMidFiles, VOID* param2){
return SadLoadedMidFiles(param0, usMaxMidFiles, param2);
}
Here is the code (most probably its Regexp abuse, but it works), gui part depends on MigLayout:
package cx.ath.jbzdak.diesIrae.util.wrappergen;
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Displays a window. In this window you have to specify two things:
* <p/>
* 1. Name of header file that you want to process.
* <p/>
* 2. Name of output files extension will be added automatically. We will override any existing files.
*
* <p/>
* Dependencies: MigLayout
* <p/>
* Actual wrapper generation is done inside WrapperGen class.
* <p/>
* KNOWN ISSUES:
* <p/>
* 1. Ignores preprocessor so may extract finction names that are inside <code>#if false</code>.
* <p/>
* 2. Ignores comments
* <p/>
* 3. May fail to parse werid parameter syntax. . .
*
* Created by IntelliJ IDEA.
* User: Jacek Bzdak
*/
public class WrapperGenerator {
public static final Charset charset = Charset.forName("UTF-8");
WrapperGen generator = new WrapperGen();
// GUI CODE:
File origHeader, targetHeader, targetCpp;
JTextField newHeaderFileName;
JFrame wrapperGeneratorFrame;
{
wrapperGeneratorFrame = new JFrame();
wrapperGeneratorFrame.setTitle("Zamknij mnie!"); //Wrapper generator
wrapperGeneratorFrame.setLayout( new MigLayout("wrap 2, fillx", "[fill,min!]"));
wrapperGeneratorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ActionListener buttonListener = new ActionListener() {
JFileChooser fileChooser = new JFileChooser();
{
fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
#Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().matches(".*\\.h(?:pp)?");
}
#Override
public String getDescription() {
return "Header files";
}
});
fileChooser.setCurrentDirectory(new File("C:\\Documents and Settings\\jb\\My Documents\\Visual Studio 2008\\Projects\\dll\\dll"));
}
public void actionPerformed(ActionEvent e) {
if(JFileChooser.APPROVE_OPTION == fileChooser.showOpenDialog(wrapperGeneratorFrame)){
origHeader = fileChooser.getSelectedFile();
}
}
};
wrapperGeneratorFrame.add(new JLabel("Original header file"));
JButton jButton = new JButton("Select header file");
jButton.addActionListener(buttonListener);
wrapperGeneratorFrame.add(jButton);
wrapperGeneratorFrame.add(new JLabel("Result files prefix"));
newHeaderFileName = new JTextField("dll_wrapper");
wrapperGeneratorFrame.add(newHeaderFileName);
ActionListener doListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
targetHeader = new File(origHeader.getParentFile(), newHeaderFileName.getText() + ".h");
targetCpp = new File(origHeader.getParentFile(), newHeaderFileName.getText() + ".cpp");
try {
targetHeader.createNewFile();
targetCpp.createNewFile();
generator.reader = new InputStreamReader(new FileInputStream(origHeader),charset);
generator.cppWriter = new OutputStreamWriter(new FileOutputStream(targetCpp), charset);
generator.heaerWriter = new OutputStreamWriter(new FileOutputStream(targetHeader), charset);
generator.parseReader();
} catch (IOException e1) {
e1.printStackTrace();
JOptionPane.showMessageDialog(wrapperGeneratorFrame, "ERROR:" + e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
return;
}
}
};
JButton go = new JButton("go");
go.addActionListener(doListener);
wrapperGeneratorFrame.add(go, "skip 1");
}
public static void main(String []args){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
WrapperGenerator wgen = new WrapperGenerator();
JFrame f = wgen.wrapperGeneratorFrame;
wgen.wrapperGeneratorFrame.pack();
Point p = getLocalGraphicsEnvironment().getCenterPoint();
wgen.wrapperGeneratorFrame.setLocation(p.x-f.getWidth()/2, p.y-f.getHeight()/2);
wgen.wrapperGeneratorFrame.setVisible(true);
}
});
}
}
/**
* Does the code parsing and generation
*/
class WrapperGen{
/**
* Method is basically syntax like this: <code>(anything apart from some special chars like #;) functionName(anything)</code>;
* Method declarations may span many lines.
*/
private static final Pattern METHOD_PATTERN =
//1 //2 //params
Pattern.compile("([^#;{}]*\\s+\\w[\\w0-9_]+)\\(([^\\)]*)\\);", Pattern.MULTILINE);
//1 - specifiers - including stuff like __dllspec(export)...
//2 - function name
//3 param list
/**
* Generated functions will have name prefixet with #RESULT_PREFIX
*/
private static final String RESULT_PREFIX = "DLL_WRAPPER_";
/**
* Specifiers of result will be prefixed with #RESULT_SPECIFIER
*/
private static final String RESULT_SPECIFIER = "__declspec(dllexport) ";
Reader reader;
Writer heaerWriter;
Writer cppWriter;
public void parseReader() throws IOException {
StringWriter writer = new StringWriter();
int read;
while((read = reader.read())!=-1){
writer.write(read);
}
reader.close();
heaerWriter.append("#pragma once\n\n\n");
heaerWriter.append("#include \"stdafx.h\"\n\n\n"); //Standard Visual C++ import file.
cppWriter.append("#include \"stdafx.h\"\n\n\n");
Matcher m = METHOD_PATTERN.matcher(writer.getBuffer());
while(m.find()){
System.out.println(m.group());
handleMatch(m);
}
cppWriter.close();
heaerWriter.close();
}
public void handleMatch(Matcher m) throws IOException {
Method meth = new Method(m);
outputHeader(meth);
outputCPP(meth);
}
private void outputDeclaration(Method m, Writer writer) throws IOException {
//writer.append(RESULT_SPECIFIER);
writer.append(m.specifiers);
writer.append(" ");
writer.append(RESULT_PREFIX);
writer.append(m.name);
writer.append("(");
for (int ii = 0; ii < m.params.size(); ii++) {
Parameter p = m.params.get(ii);
writer.append(p.specifiers);
writer.append(" ");
writer.append(p.name);
if(ii!=m.params.size()-1){
writer.append(", ");
}
}
writer.append(")");
}
public void outputHeader(Method m) throws IOException {
outputDeclaration(m, heaerWriter);
heaerWriter.append(";\n\n");
}
public void outputCPP(Method m) throws IOException {
cppWriter.append(RESULT_SPECIFIER);
outputDeclaration(m, cppWriter);
cppWriter.append("{\n\t");
if (!m.specifiers.contains("void") || m.specifiers.matches(".*void\\s*\\*.*")) {
cppWriter.append("return ");
}
cppWriter.append(m.name);
cppWriter.append("(");
for (int ii = 0; ii < m.params.size(); ii++) {
Parameter p = m.params.get(ii);
cppWriter.append(p.name);
if(ii!=m.params.size()-1){
cppWriter.append(", ");
}
}
cppWriter.append(");\n");
cppWriter.append("}\n\n");
}
}
class Method{
private static final Pattern NAME_REGEXP =
//1 //2
Pattern.compile("\\s*(.*)\\s+(\\w[\\w0-9]+)\\s*", Pattern.MULTILINE);
//1 - all specifiers - including __declspec(dllexport) and such ;)
//2 - function name
public final List<Parameter> params;
public final String name;
public final String specifiers;
public Method(Matcher m) {
params = Collections.unmodifiableList(Parameter.parseParamList(m.group(2)));
Matcher nameMather = NAME_REGEXP.matcher(m.group(1));
System.out.println("ALL: " + m.group());
System.out.println("G1: " + m.group(1));
if(!nameMather.matches()){
throw new IllegalArgumentException("for string " + m.group(1));
}
// nameMather.find();
specifiers = nameMather.group(1);
name = nameMather.group(2);
}
}
class Parameter{
static final Pattern PARAMETER_PATTERN =
//1 //2
Pattern.compile("\\s*(?:(.*)\\s+)?([\\w\\*&]+[\\w0-9]*[\\*&]?)\\s*");
//1 - Most probably parameter type and specifiers, but may also be empty - in which case name is empty, and specifiers are in 2
//2 - Most probably parameter type, sometimes prefixed with ** or &* ;), also
// 'char *' will be parsed as grup(1) == char, group(2) = *.
/**
* Used to check if group that represenrs parameter name is in fact param specifier like '*'.
*/
static final Pattern STAR_PATTERN =
Pattern.compile("\\s*([\\*&]?)+\\s*");
/**
* If
*/
static final Pattern NAME_PATTERN =
Pattern.compile("\\s*([\\*&]+)?(\\w[\\w0-9]*)\\s*");
public final String name;
public final String specifiers;
public Parameter(String param, int idx) {
System.out.println(param);
Matcher m = PARAMETER_PATTERN.matcher(param);
String name = null;
String specifiers = null;
if(!m.matches()){
throw new IllegalStateException(param);
}
name = m.group(2);
specifiers = m.group(1);
if(specifiers==null || specifiers.isEmpty()){ //Case that parameter has no name like 'int', or 'int**'
specifiers = name;
name = null;
}else if(STAR_PATTERN.matcher(name).matches()){ //Case that parameter has no name like 'int *'
specifiers += name;
name = null;
}else if(NAME_PATTERN.matcher(name).matches()){ //Checks if name contains part of type like '**ptrData', and extracts '**'
Matcher m2 = NAME_PATTERN.matcher(name);
m2.matches();
if(m2.group(1)!=null){
specifiers += m2.group(1);
name = m2.group(2);
}
}
if(name==null){
name = "param" + idx;
}
this.specifiers = specifiers;
this.name = name;
}
public static List<Parameter> parseParamList(String paramList){
List<Parameter> result = new ArrayList<Parameter>();
String[] params = paramList.split(",");
int idx = 0;
for(String param : params){
Parameter p = new Parameter(param, idx++);
result.add(p);
}
if(result.size()==1){
Parameter p = result.get(0);
if(p.specifiers.matches("\\s*void\\s*")){
return Collections.emptyList();
}
}
return result;
}
}