I'm trying to load a file using LibGDX's internal file loader via:
"Gdx.files.internal();"
however I get the error:
"GdxRuntimeException: File not Found: data\characters\collisons\misaka\running_aabb.json (Internal)"
This is my code where I am loading the data:
private BodyEditorLoader standingAABB;
private BodyEditorLoader movingAABB;
private BodyEditorLoader currentAABB;
public Player(String name, int x, int y, int width, int height) {
//...
standingAABB = new BodyEditorLoader(Gdx.files.internal("data/characters/collisions/" + name + "/standing_aabb.json"));
movingAABB = new BodyEditorLoader(Gdx.files.internal("data/characters/collisons/" + name + "/running_aabb.json"));
currentAABB = standingAABB;
//...
}
As the error is stating that it cannot load "running_aabb.json" I am assuming that it is able to load "standing_aabb.json".
This is what my assets folder looks like:
As you can see, the file exists where it should be but it cannot be found. I have already tried refreshing the project as well as cleaning the project and reopening Eclipse.
Anyone know what might be causing this error?
BodyEditorLoader.java contents (This isn't mine so I'm not sure which parts are related):
package aurelienribon.bodyeditor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.JsonValue;
/**
* Loads the collision fixtures defined with the Physics Body Editor
* application. You only need to give it a body and the corresponding fixture
* name, and it will attach these fixtures to your body.
*
* #author Aurelien Ribon | http://www.aurelienribon.com
*/
public class BodyEditorLoader {
// Model
private final Model model;
// Reusable stuff
private final List<Vector2> vectorPool = new ArrayList<Vector2>();
private final PolygonShape polygonShape = new PolygonShape();
private final CircleShape circleShape = new CircleShape();
private final Vector2 vec = new Vector2();
// -------------------------------------------------------------------------
// Ctors
// -------------------------------------------------------------------------
public BodyEditorLoader(FileHandle file) {
if (file == null) throw new NullPointerException("file is null");
model = readJson(file.readString());
}
public BodyEditorLoader(String str) {
if (str == null) throw new NullPointerException("str is null");
model = readJson(str);
}
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
/**
* Creates and applies the fixtures defined in the editor. The name
* parameter is used to retrieve the right fixture from the loaded file.
* <br/><br/>
*
* The body reference point (the red cross in the tool) is by default
* located at the bottom left corner of the image. This reference point
* will be put right over the BodyDef position point. Therefore, you should
* place this reference point carefully to let you place your body in your
* world easily with its BodyDef.position point. Note that to draw an image
* at the position of your body, you will need to know this reference point
* (see {#link #getOrigin(java.lang.String, float)}.
* <br/><br/>
*
* Also, saved shapes are normalized. As shown in the tool, the width of
* the image is considered to be always 1 meter. Thus, you need to provide
* a scale factor so the polygons get resized according to your needs (not
* every body is 1 meter large in your game, I guess).
*
* #param body The Box2d body you want to attach the fixture to.
* #param name The name of the fixture you want to load.
* #param fd The fixture parameters to apply to the created body fixture.
* #param scale The desired scale of the body. The default width is 1.
*/
public void attachFixture(Body body, String name, FixtureDef fd, float scale) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
//Changed mul() call to scl()
Vector2 origin = vec.set(rbModel.origin).scl(scale);
for (int i=0, n=rbModel.polygons.size(); i<n; i++) {
PolygonModel polygon = rbModel.polygons.get(i);
Vector2[] vertices = polygon.buffer;
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
//Changed mul() call to scl()
vertices[ii] = newVec().set(polygon.vertices.get(ii)).scl(scale);
vertices[ii].sub(origin);
}
polygonShape.set(vertices);
fd.shape = polygonShape;
body.createFixture(fd);
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
free(vertices[ii]);
}
}
for (int i=0, n=rbModel.circles.size(); i<n; i++) {
CircleModel circle = rbModel.circles.get(i);
//Changed mul() call to scl()
Vector2 center = newVec().set(circle.center).scl(scale);
float radius = circle.radius * scale;
circleShape.setPosition(center);
circleShape.setRadius(radius);
fd.shape = circleShape;
body.createFixture(fd);
free(center);
}
}
/**
* Gets the image path attached to the given name.
*/
public String getImagePath(String name) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
return rbModel.imagePath;
}
/**
* Gets the origin point attached to the given name. Since the point is
* normalized in [0,1] coordinates, it needs to be scaled to your body
* size. Warning: this method returns the same Vector2 object each time, so
* copy it if you need it for later use.
*/
public Vector2 getOrigin(String name, float scale) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
//Changed mul() call to scl()
return vec.set(rbModel.origin).scl(scale);
}
/**
* <b>For advanced users only.</b> Lets you access the internal model of
* this loader and modify it. Be aware that any modification is permanent
* and that you should really know what you are doing.
*/
public Model getInternalModel() {
return model;
}
// -------------------------------------------------------------------------
// Json Models
// -------------------------------------------------------------------------
public static class Model {
public final Map<String, RigidBodyModel> rigidBodies = new HashMap<String, RigidBodyModel>();
}
public static class RigidBodyModel {
public String name;
public String imagePath;
public final Vector2 origin = new Vector2();
public final List<PolygonModel> polygons = new ArrayList<PolygonModel>();
public final List<CircleModel> circles = new ArrayList<CircleModel>();
}
public static class PolygonModel {
public final List<Vector2> vertices = new ArrayList<Vector2>();
private Vector2[] buffer; // used to avoid allocation in attachFixture()
}
public static class CircleModel {
public final Vector2 center = new Vector2();
public float radius;
}
// -------------------------------------------------------------------------
// Json reading process
// -------------------------------------------------------------------------
private Model readJson(String str) {
Model m = new Model();
JsonValue map = new JsonReader().parse(str);
JsonValue bodyElem = map.getChild("rigidBodies");
for (; bodyElem != null; bodyElem = bodyElem.next()) {
RigidBodyModel rbModel = readRigidBody(bodyElem);
m.rigidBodies.put(rbModel.name, rbModel);
}
return m;
}
private RigidBodyModel readRigidBody(JsonValue bodyElem) {
RigidBodyModel rbModel = new RigidBodyModel();
rbModel.name = bodyElem.getString("name");
rbModel.imagePath = bodyElem.getString("imagePath");
JsonValue originElem = bodyElem.get("origin");
rbModel.origin.x = originElem.getFloat("x");
rbModel.origin.y = originElem.getFloat("y");
// polygons
JsonValue polygonsElem = bodyElem.getChild("polygons");
for (; polygonsElem != null ;polygonsElem = polygonsElem.next()){
PolygonModel polygon = new PolygonModel();
rbModel.polygons.add(polygon);
JsonValue vertexElem = polygonsElem.child();
for (; vertexElem != null; vertexElem = vertexElem.next()) {
float x = vertexElem.getFloat("x");
float y = vertexElem.getFloat("y");
polygon.vertices.add(new Vector2(x, y));
}
polygon.buffer = new Vector2[polygon.vertices.size()];
}
// circles
JsonValue circleElem = bodyElem.getChild("circles");
for (; circleElem != null; circleElem = circleElem.next()) {
CircleModel circle = new CircleModel();
rbModel.circles.add(circle);
circle.center.x = circleElem.getFloat("cx");
circle.center.y = circleElem.getFloat("cy");
circle.radius = circleElem.getFloat("r");
}
return rbModel;
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private Vector2 newVec() {
return vectorPool.isEmpty() ? new Vector2() : vectorPool.remove(0);
}
private void free(Vector2 v) {
vectorPool.add(v);
}
}
You have misprint in second path: collisons. It should be collisions.
Related
So, I started using Physics Body Editor as an extension to libgdx. I also use Android Studio to compile my code, so I can run an app on a real device.
But, unfortunately, as I create a new loader, like this:
BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal("tnkA.json"));
logcat gives me the following error:
java.lang.NoSuchMethodError: No virtual method parse(Ljava/lang/String;)Ljava/lang/Object;
Clearly, something wrong with the Physics Body Editor.
Is there any way to fix this? Thanks!
There is the full error:
02-12 13:39:15.406 2372-2387/com.tynibattles04.game.android E/AndroidRuntime﹕ FATAL EXCEPTION: GLThread 172
Process: com.tynibattles04.game.android, PID: 2372
java.lang.NoSuchMethodError: No virtual method parse(Ljava/lang/String;)Ljava/lang/Object;
in class Lcom/badlogic/gdx/utils/JsonReader;
or its super classes (declaration of 'com.badlogic.gdx.utils.JsonReader' appears
in /data/app/com.tynibattles04.game.android-1/base.apk)
at aurelienribon.bodyeditor.BodyEditorLoader.readJson(BodyEditorLoader.java:179)
at aurelienribon.bodyeditor.BodyEditorLoader.<init>(BodyEditorLoader.java:41)
at com.tynibattles04.game.TinyBattles.createBottle(TinyBattles.java:127)
at com.tynibattles04.game.TinyBattles.create(TinyBattles.java:74)
at com.badlogic.gdx.backends.android.AndroidGraphics.onSurfaceChanged(AndroidGraphics.java:241)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1511)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
look this maybe this can help with anything :
https://code.google.com/p/box2d-editor/issues/detail?id=25
https://gist.github.com/zudov/5566204
package aurelienribon.bodyeditor;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.JsonValue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Loads the collision fixtures defined with the Physics Body Editor
* application. You only need to give it a body and the corresponding fixture
* name, and it will attach these fixtures to your body.
*
* #author Aurelien Ribon | http://www.aurelienribon.com
*/
public class BodyEditorLoader {
// Model
private final Model model;
// Reusable stuff
private final List<Vector2> vectorPool = new ArrayList<Vector2>();
private final PolygonShape polygonShape = new PolygonShape();
private final CircleShape circleShape = new CircleShape();
private final Vector2 vec = new Vector2();
// -------------------------------------------------------------------------
// Ctors
// -------------------------------------------------------------------------
public BodyEditorLoader(FileHandle file) {
if (file == null) throw new NullPointerException("file is null");
model = readJson(file.readString());
}
public BodyEditorLoader(String str) {
if (str == null) throw new NullPointerException("str is null");
model = readJson(str);
}
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
/**
* Creates and applies the fixtures defined in the editor. The name
* parameter is used to retrieve the right fixture from the loaded file.
* <br/><br/>
*
* The body reference point (the red cross in the tool) is by default
* located at the bottom left corner of the image. This reference point
* will be put right over the BodyDef position point. Therefore, you should
* place this reference point carefully to let you place your body in your
* world easily with its BodyDef.position point. Note that to draw an image
* at the position of your body, you will need to know this reference point
* (see {#link #getOrigin(java.lang.String, float)}.
* <br/><br/>
*
* Also, saved shapes are normalized. As shown in the tool, the width of
* the image is considered to be always 1 meter. Thus, you need to provide
* a scale factor so the polygons get resized according to your needs (not
* every body is 1 meter large in your game, I guess).
*
* #param body The Box2d body you want to attach the fixture to.
* #param name The name of the fixture you want to load.
* #param fd The fixture parameters to apply to the created body fixture.
* #param scale The desired scale of the body. The default width is 1.
*/
public void attachFixture(Body body, String name, FixtureDef fd, float scale) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
Vector2 origin = vec.set(rbModel.origin).mul(scale);
for (int i=0, n=rbModel.polygons.size(); i<n; i++) {
PolygonModel polygon = rbModel.polygons.get(i);
Vector2[] vertices = polygon.buffer;
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
vertices[ii] = newVec().set(polygon.vertices.get(ii)).mul(scale);
vertices[ii].sub(origin);
}
polygonShape.set(vertices);
fd.shape = polygonShape;
body.createFixture(fd);
for (int ii=0, nn=vertices.length; ii<nn; ii++) {
free(vertices[ii]);
}
}
for (int i=0, n=rbModel.circles.size(); i<n; i++) {
CircleModel circle = rbModel.circles.get(i);
Vector2 center = newVec().set(circle.center).mul(scale);
float radius = circle.radius * scale;
circleShape.setPosition(center);
circleShape.setRadius(radius);
fd.shape = circleShape;
body.createFixture(fd);
free(center);
}
}
/**
* Gets the image path attached to the given name.
*/
public String getImagePath(String name) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null) throw new RuntimeException("Name '" + name + "' was not found.");
return rbModel.imagePath;
}
/**
* Gets the origin point attached to the given name. Since the point is
* normalized in [0,1] coordinates, it needs to be scaled to your body
* size. Warning: this method returns the same Vector2 object each time, so
* copy it if you need it for later use.
*/
public Vector2 getOrigin(String name, float scale) {
RigidBodyModel rbModel = model.rigidBodies.get(name);
if (rbModel == null)
throw new RuntimeException("Name '" + name + "' was not found.");
return vec.set(rbModel.origin).scl(scale);
}
/**
* <b>For advanced users only.</b> Lets you access the internal model of
* this loader and modify it. Be aware that any modification is permanent
* and that you should really know what you are doing.
*/
public Model getInternalModel() {
return model;
}
// -------------------------------------------------------------------------
// Json Models
// -------------------------------------------------------------------------
public static class Model {
public final Map<String, RigidBodyModel> rigidBodies = new HashMap<String, RigidBodyModel>();
}
public static class RigidBodyModel {
public String name;
public String imagePath;
public final Vector2 origin = new Vector2();
public final List<PolygonModel> polygons = new ArrayList<PolygonModel>();
public final List<CircleModel> circles = new ArrayList<CircleModel>();
}
public static class PolygonModel {
public final List<Vector2> vertices = new ArrayList<Vector2>();
private Vector2[] buffer; // used to avoid allocation in attachFixture()
}
public static class CircleModel {
public final Vector2 center = new Vector2();
public float radius;
}
// -------------------------------------------------------------------------
// Json reading process
// -------------------------------------------------------------------------
private Model readJson(String str) {
Model m = new Model();
JsonValue map = new JsonReader().parse(str);
JsonValue bodyElem = map.getChild("rigidBodies");
for (; bodyElem != null; bodyElem = bodyElem.next()) {
RigidBodyModel rbModel = readRigidBody(bodyElem);
m.rigidBodies.put(rbModel.name, rbModel);
}
return m;
}
private RigidBodyModel readRigidBody(JsonValue bodyElem) {
RigidBodyModel rbModel = new RigidBodyModel();
rbModel.name = bodyElem.getString("name");
rbModel.imagePath = bodyElem.getString("imagePath");
JsonValue originElem = bodyElem.get("origin");
rbModel.origin.x = originElem.getFloat("x");
rbModel.origin.y = originElem.getFloat("y");
// polygons
JsonValue polygonsElem = bodyElem.getChild("polygons");
for (; polygonsElem != null ;polygonsElem = polygonsElem.next()){
PolygonModel polygon = new PolygonModel();
rbModel.polygons.add(polygon);
JsonValue vertexElem = polygonsElem.child();
for (; vertexElem != null; vertexElem = vertexElem.next()) {
float x = vertexElem.getFloat("x");
float y = vertexElem.getFloat("y");
polygon.vertices.add(new Vector2(x, y));
}
polygon.buffer = new Vector2[polygon.vertices.size()];
}
// circles
JsonValue circleElem = bodyElem.getChild("circles");
for (; circleElem != null; circleElem = circleElem.next()) {
CircleModel circle = new CircleModel();
rbModel.circles.add(circle);
circle.center.x = circleElem.getFloat("cx");
circle.center.y = circleElem.getFloat("cy");
circle.radius = circleElem.getFloat("r");
}
return rbModel;
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private Vector2 newVec() {
return vectorPool.isEmpty() ? new Vector2() : vectorPool.remove(0);
}
private void free(Vector2 v) {
vectorPool.add(v);
}
}
This code is on GitHub, but it was once the reporsitorio deleted because the user account change, I'll post it here so they do not depend account Git.(also with some changes to the code).
I am trying to implement Dijkstra Algorithm that reads a DOT file (.txt) and should give back a map and first of all i have to extract Data from a textfile to an ArrayList, so I made two classes one for the Verticles, and the other Class for the Edges.
the text file looks like this :
Digraph {
A -> B [label="10,90"];
A -> C [label="8,80"];
C -> B [label="1,50"];
B -> D [label="7,60"];
C -> D [label="6,80"];
D -> E [label="4,90"];
E -> F [label="2,130"];
D -> F [label="5,130"];
F -> G [label="5,120"];
G -> H [label="5,100"];
A [label="A,5"];
B [label="B,4"];
C [label="C,3"];
D [label="D,2"];
E [label="E,1"];
F [label="F,6"];
G [label="G,7"];
H [label="H,8"];
}
for example in line 1 I should extract the Source which is "A" and the Destination which is "B" and the speedLimit which is 10 and the distance which is 90 this is concerning the edges. and from line 11 I should extract the name and time for example in the line 11 the name should be "A" and the time should be 5.
here is my simple first two classes :
VerticlesRep Class :
package lab;
public class VerticesRep {
private String name;
private int time;
public VerticesRep(String name, int time) {
this.name = name;
this.time = time;
}
public String getName() {
return name;
}
public int getTime() {
return time;
}
public void setName(String name) {
this.name = name;
}
public void setTime(int time) {
this.time = time;
}
}
and here is my EdgesRep Class :
package lab;
public class EdgesRep {
private String Source;
private String Destination;
private int speedLimit;
private int distance;
public EdgesRep(String Source, String Destination, int speedLimit, int distance) {
this.setSource(Source);
this.setDestination(Destination);
this.setSpeedLimit(speedLimit);
this.setDistance(distance);
}
public String getSource() {
return Source;
}
public void setSource(String source) {
Source = source;
}
public String getDestination() {
return Destination;
}
public void setDestination(String destination) {
Destination = destination;
}
public int getSpeedLimit() {
return speedLimit;
}
public void setSpeedLimit(int speedLimit) {
this.speedLimit = speedLimit;
}
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
}
and this is the Navigation Class :
package lab;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
/**
* The class Navigation finds the shortest (and/or) path between points on a map
* using the Dijkstra algorithm
*/
public class Navigation {
/**
* Return codes: -1 if the source is not on the map -2 if the destination is
* not on the map -3 if both source and destination points are not on the
* map -4 if no path can be found between source and destination
*/
public static final int SOURCE_NOT_FOUND = -1;
public static final int DESTINATION_NOT_FOUND = -2;
public static final int SOURCE_DESTINATION_NOT_FOUND = -3;
public static final int NO_PATH = -4;
// added variables
private String filename = null; // filename initialization
/**
* The constructor takes a filename as input, it reads that file and fill
* the nodes and edges Lists with corresponding node and edge objects
*
* #param filename
* name of the file containing the input map
*/
public Navigation(String filename) {
ArrayList<VerticesRep> Vertex = new ArrayList<VerticesRep>();
ArrayList<EdgesRep> Edges = new ArrayList<EdgesRep>();
this.filename = filename;
try {
FileReader fr = new FileReader(filename);
BufferedReader in = new BufferedReader(fr);
String line = null;
while ((line = in.readLine()) != null) {
// here i must fill the ArrayLists with the Information
// I need from the text file.
}
in.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I tried to find out what I actually should use to fill the ArrayList from the text file but the .split won't actually work in my case.
Thank You.
Use regular expressions.
First import:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Then write something like this:
String line = null;
Pattern patternEdge = Pattern.compile("\\s*([A-Z])\\s*->\\s*([A-Z])\\s*\\[label=\"(\\d+),(\\d+)\"\\];");
Pattern patternVertex = Pattern.compile("\\s*([A-Z])\\s*\\[label=\"([A-Z]),(\\d+)\"\\];");
Matcher m = null;
while ((line = in.readLine()) != null) {
m = patternEdge.matcher(line);
if (m.find()) {
String source = m.group(1);
String destination = m.group(2);
int speedLimit = Integer.parseInt(m.group(3));
int distance = Integer.parseInt(m.group(4));
Edges.add(new EdgesRep(source, destination, speedLimit, distance));
}
else {
m = patternVertex.matcher(line);
if (m.find()) {
String name = m.group(2);
int time = Integer.parseInt(m.group(3));
Vertex.add(new VerticesRep(name, time));
}
else
System.err.println("Expression is incorrect. No matches");
}
}
//for debugging
for(EdgesRep e : Edges)
System.out.println(e.getSource() + " " + e.getDestination() + " " + e.getSpeedLimit() + " " + e.getDistance());
//for debugging
for(VerticesRep v : Vertex)
System.out.println(v.getName() + " " + v.getTime());
Because the first line doesn't really mean anything you may want to just skip it...
On this code block I assumed it starts with A -> B [label="10,90"];
Hope it helped :)
I have created an sql database with a table containing information about Airplanes, I want to be able to take this information and insert it into an ArrayList of type Aircraft(object) although the different info in the sql table are different primitive types........can this be done?`package uk.ac.qub.sqldbflights;
This is the Aircraft object with all the attributes which are the
public class Aircraft {
/**
* private String containing the airline name of the aircraft
* -Can't be blank
*/
private int aircraft_number;
/**
* private String containing the flight number belonging to the aircraft
* -Can't be blank
*/
private String airline_company;
/**
* private String containing the aircrafts city of origin
* -Can't be blank
*/
private String departure_airport;
/**
* private int which holds the aircrafts fuel level
* -Must be over 0 and less than 100
*/
private float passenger_number;
/**
* private int containing the number of passengers aboard the aircraft
* -Must be over 0 and less than 300
*/
private float fuel_percentage;
/**
* private Boolean indicting wether the aircraft is in the landing queue or not
*/
private int flight_time_remaining;
/**
* private Boolean indicating wether the aircraft is landed or not
*/
private boolean in_queue;
private boolean is_landed;
public Aircraft() {
}
/**
* Song creation
* #param name -not null
* #param artist -not null
* #param album -not null
* #param genre- not null and one of Pop, Dance, Rock
* #throws IllegalArgumentException
*/
public Aircraft(int aircraft_number, String airline_company, String departure_airport, int passenger_number, float fuel_percentage, int flight_time_remaining, boolean in_queue, boolean is_landed)
throws IllegalArgumentException {
try {
// set name
this.setAircraft_number(aircraft_number);
this.setAirline_company(airline_company);
this.setDeparture_airport(departure_airport);
this.setPassenger_number(passenger_number);
this.setFuel_percentage(fuel_percentage);
this.setFlight_time_remaining(flight_time_remaining);
this.setIn_queue(in_queue);
this.setIs_landed(is_landed);
} catch (IllegalArgumentException ex) {
System.out.println("Unable to create song due to arguments passed");
throw ex;
}}
public int getAircraft_number() {
return aircraft_number;
}
public void setAircraft_number(int aircraft_number) {
this.aircraft_number = aircraft_number;
}
public String getAirline_company() {
return airline_company;
}
public void setAirline_company(String airline_company) {
this.airline_company = airline_company;
}
public String getDeparture_airport() {
return departure_airport;
}
public void setDeparture_airport(String departure_airport) {
this.departure_airport = departure_airport;
}
public float getPassenger_number() {
return passenger_number;
}
public void setPassenger_number(float passenger_number) {
this.passenger_number = passenger_number;
}
public float getFuel_percentage() {
return fuel_percentage;
}
public void setFuel_percentage(float fuel_percentage) {
this.fuel_percentage = fuel_percentage;
}
public int isFlight_time_remaining() {
return flight_time_remaining;
}
public void setFlight_time_remaining(int flight_time_remaining) {
this.flight_time_remaining = flight_time_remaining;
}
public boolean isIn_queue() {
return in_queue;
}
public void setIn_queue(boolean in_queue) {
this.in_queue = in_queue;
}
public boolean isIs_landed() {
return is_landed;
}
public void setIs_landed(boolean is_landed) {
this.is_landed = is_landed;
}
}
This is the code which makes the connection to the sql DB and trys to add the info to an arraylist...
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
public class FlightsDbtoArrayList {
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
public static void main(String[] args) {
// Entering username to verify connection to SQL Server
String url = "jdbc:mysql://";
Connection con;
Statement statement1;
try {
Class.forName("com.mysql.jdbc.Driver");
//Catching any errors and printing a message to the user
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
try {
// Entering username and password to verify connection to SQL Server
con = DriverManager.getConnection(url);
//Creating platform for a SQL query Statement
statement1 = con.createStatement();
//Creating and executing the designed SQL query statement
ResultSet results1 = statement1.executeQuery("SELECT aircraft_number, airline_company, departure_airport, passenger_number, fuel_Percentage, flight_time_remaining, in_queue, is_landed FROM flights");
//Displaying the results of the query to screen
printResults(results1);
con.close();
statement1.close();
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
}
/**
* Method to display the results of the three SQL queries
* #param results
* #throws SQLException
*
*
*/
public ArrayList<Aircraft> allFlights() {
return allFlights;
}
/**
* set songs on the system
* #param allSongs
*/
public void setSongs(ArrayList<Aircraft> allSongs) {
allSongs = this.allFlights;
}
private static void printResults(ResultSet results) throws SQLException {
while (results.next()) {
int aircraft_number = results.getInt("aircraft_number");
String airline_company = results.getString("airline_company");
String departure_airport = results.getString("departure_airport");
int passenger_number = results.getInt("passenger_number");
float fuel_percentage = results.getFloat("fuel_percentage");
int flight_time_remaining = results.getInt("flight_time_remaining");
boolean in_queue = results.getBoolean("in_queue");
boolean is_landed = results.getBoolean("is_landed");
Aircraft a1;
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
a1 = new Aircraft(aircraft_number, airline_company, departure_airport, passenger_number, fuel_percentage, flight_time_remaining, in_queue, is_landed);
allFlights.add(a1);
System.out.println(allFlights);
}
}
}
`
Yes it is definitely possible to have list of objects(Aircraft) derived from database. But in this case your while loop inside the PrintResult has some errors.
You are creating list allFights within the while loop which will create new list in each iteration and add a1 to it so in the end you will only have a list with one aircraft details in it.
System.out.println(allFlights) will not give much desired output (or it might), but I would advice you should override toString() method in your AirCraft class.
Try to change your PrintResult method as following.
private static void printResults(ResultSet results) throws SQLException {
ArrayList<Aircraft> allFlights = new ArrayList<Aircraft>();
Aircraft a1;
while (results.next()) {
int aircraft_number = results.getInt("aircraft_number");
String airline_company = results.getString("airline_company");
String departure_airport = results.getString("departure_airport");
int passenger_number = results.getInt("passenger_number");
float fuel_percentage = results.getFloat("fuel_percentage");
int flight_time_remaining = results.getInt("flight_time_remaining");
boolean in_queue = results.getBoolean("in_queue");
boolean is_landed = results.getBoolean("is_landed");
a1 = new Aircraft(aircraft_number, airline_company, departure_airport, passenger_number, fuel_percentage, flight_time_remaining, in_queue, is_landed);
allFlights.add(a1);
//Instead of this line System.out.println(allFlights);
//write following code
For(AirCraft aircraft : allFlights){
System.out.println(aircraft.toString());
}
}
}
Edit 2: Write the following method in your AirCraft class.
#Override
Public String toString(){
String string;
//Write some code here so that you can represent you object using this method
//for example I am adding just the aircraft_number
string = getAircraft_number()+"";
return string;
}
Important: The toString() method I wrote is just an example you need to learn how to correctly write toString() method for any of your class. this and this are good starting point to learn that. And stop worrying about your your list of allFlights because as per this code it is getting created but you can not print it the way you are trying to.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Google Maps output=kml broken?
I started to get Error when I'm trying to retrieve Google Directions using KML data since few days. The Error seems that the URL I'm requesting doesn't retreieve KML data anymore, it returns a whole page. I followed this in order to achieve that.
What is the solution for this? Is there any alternatives?
Update:
Since Android Google Maps v2 is now used, the code needs to be adjusted to work on v2 maps which can be found here.
Original Answer:
This way of extracting the Google Directions from Google by parsing the KML file is no longer available since 27 July 2012 (because Google has changed the structure of retrieving Google Directions, now you can only get it by JSON or XML), it is time to migrate your code to JSON instead of KML.
I did it by creating 6 classes like this:
Parser.java:
public interface Parser {
public Route parse();
}
XMLParser.java:
public class XMLParser {
// names of the XML tags
protected static final String MARKERS = "markers";
protected static final String MARKER = "marker";
protected URL feedUrl;
protected XMLParser(final String feedUrl) {
try {
this.feedUrl = new URL(feedUrl);
} catch (MalformedURLException e) {
//Log.e(e.getMessage(), "XML parser - " + feedUrl);
}
}
protected InputStream getInputStream() {
try {
return feedUrl.openConnection().getInputStream();
} catch (IOException e) {
//Log.e(e.getMessage(), "XML parser - " + feedUrl);
return null;
}
}
}
Segment.java:
public class Segment {
/** Points in this segment. **/
private GeoPoint start;
/** Turn instruction to reach next segment. **/
private String instruction;
/** Length of segment. **/
private int length;
/** Distance covered. **/
private double distance;
/**
* Create an empty segment.
*/
public Segment() {
}
/**
* Set the turn instruction.
* #param turn Turn instruction string.
*/
public void setInstruction(final String turn) {
this.instruction = turn;
}
/**
* Get the turn instruction to reach next segment.
* #return a String of the turn instruction.
*/
public String getInstruction() {
return instruction;
}
/**
* Add a point to this segment.
* #param point GeoPoint to add.
*/
public void setPoint(final GeoPoint point) {
start = point;
}
/** Get the starting point of this
* segment.
* #return a GeoPoint
*/
public GeoPoint startPoint() {
return start;
}
/** Creates a segment which is a copy of this one.
* #return a Segment that is a copy of this one.
*/
public Segment copy() {
final Segment copy = new Segment();
copy.start = start;
copy.instruction = instruction;
copy.length = length;
copy.distance = distance;
return copy;
}
/**
* #param length the length to set
*/
public void setLength(final int length) {
this.length = length;
}
/**
* #return the length
*/
public int getLength() {
return length;
}
/**
* #param distance the distance to set
*/
public void setDistance(double distance) {
this.distance = distance;
}
/**
* #return the distance
*/
public double getDistance() {
return distance;
}
}
Route.java:
public class Route {
private String name;
private final List<GeoPoint> points;
private List<Segment> segments;
private String copyright;
private String warning;
private String country;
private int length;
private String polyline;
public Route() {
points = new ArrayList<GeoPoint>();
segments = new ArrayList<Segment>();
}
public void addPoint(final GeoPoint p) {
points.add(p);
}
public void addPoints(final List<GeoPoint> points) {
this.points.addAll(points);
}
public List<GeoPoint> getPoints() {
return points;
}
public void addSegment(final Segment s) {
segments.add(s);
}
public List<Segment> getSegments() {
return segments;
}
/**
* #param name the name to set
*/
public void setName(final String name) {
this.name = name;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param copyright the copyright to set
*/
public void setCopyright(String copyright) {
this.copyright = copyright;
}
/**
* #return the copyright
*/
public String getCopyright() {
return copyright;
}
/**
* #param warning the warning to set
*/
public void setWarning(String warning) {
this.warning = warning;
}
/**
* #return the warning
*/
public String getWarning() {
return warning;
}
/**
* #param country the country to set
*/
public void setCountry(String country) {
this.country = country;
}
/**
* #return the country
*/
public String getCountry() {
return country;
}
/**
* #param length the length to set
*/
public void setLength(int length) {
this.length = length;
}
/**
* #return the length
*/
public int getLength() {
return length;
}
/**
* #param polyline the polyline to set
*/
public void setPolyline(String polyline) {
this.polyline = polyline;
}
/**
* #return the polyline
*/
public String getPolyline() {
return polyline;
}
}
GoogleParser.java:
public class GoogleParser extends XMLParser implements Parser {
/** Distance covered. **/
private int distance;
public GoogleParser(String feedUrl) {
super(feedUrl);
}
/**
* Parses a url pointing to a Google JSON object to a Route object.
* #return a Route object based on the JSON object.
*/
public Route parse() {
// turn the stream into a string
final String result = convertStreamToString(this.getInputStream());
//Create an empty route
final Route route = new Route();
//Create an empty segment
final Segment segment = new Segment();
try {
//Tranform the string into a json object
final JSONObject json = new JSONObject(result);
//Get the route object
final JSONObject jsonRoute = json.getJSONArray("routes").getJSONObject(0);
//Get the leg, only one leg as we don't support waypoints
final JSONObject leg = jsonRoute.getJSONArray("legs").getJSONObject(0);
//Get the steps for this leg
final JSONArray steps = leg.getJSONArray("steps");
//Number of steps for use in for loop
final int numSteps = steps.length();
//Set the name of this route using the start & end addresses
route.setName(leg.getString("start_address") + " to " + leg.getString("end_address"));
//Get google's copyright notice (tos requirement)
route.setCopyright(jsonRoute.getString("copyrights"));
//Get the total length of the route.
route.setLength(leg.getJSONObject("distance").getInt("value"));
//Get any warnings provided (tos requirement)
if (!jsonRoute.getJSONArray("warnings").isNull(0)) {
route.setWarning(jsonRoute.getJSONArray("warnings").getString(0));
}
/* Loop through the steps, creating a segment for each one and
* decoding any polylines found as we go to add to the route object's
* map array. Using an explicit for loop because it is faster!
*/
for (int i = 0; i < numSteps; i++) {
//Get the individual step
final JSONObject step = steps.getJSONObject(i);
//Get the start position for this step and set it on the segment
final JSONObject start = step.getJSONObject("start_location");
final GeoPoint position = new GeoPoint((int) (start.getDouble("lat")*1E6),
(int) (start.getDouble("lng")*1E6));
segment.setPoint(position);
//Set the length of this segment in metres
final int length = step.getJSONObject("distance").getInt("value");
distance += length;
segment.setLength(length);
segment.setDistance(distance/1000);
//Strip html from google directions and set as turn instruction
segment.setInstruction(step.getString("html_instructions").replaceAll("<(.*?)*>", ""));
//Retrieve & decode this segment's polyline and add it to the route.
route.addPoints(decodePolyLine(step.getJSONObject("polyline").getString("points")));
//Push a copy of the segment to the route
route.addSegment(segment.copy());
}
} catch (JSONException e) {
Log.e(e.getMessage(), "Google JSON Parser - " + feedUrl);
}
return route;
}
/**
* Convert an inputstream to a string.
* #param input inputstream to convert.
* #return a String of the inputstream.
*/
private static String convertStreamToString(final InputStream input) {
final BufferedReader reader = new BufferedReader(new InputStreamReader(input));
final StringBuilder sBuf = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sBuf.append(line);
}
} catch (IOException e) {
Log.e(e.getMessage(), "Google parser, stream2string");
} finally {
try {
input.close();
} catch (IOException e) {
Log.e(e.getMessage(), "Google parser, stream2string");
}
}
return sBuf.toString();
}
/**
* Decode a polyline string into a list of GeoPoints.
* #param poly polyline encoded string to decode.
* #return the list of GeoPoints represented by this polystring.
*/
private List<GeoPoint> decodePolyLine(final String poly) {
int len = poly.length();
int index = 0;
List<GeoPoint> decoded = new ArrayList<GeoPoint>();
int lat = 0;
int lng = 0;
while (index < len) {
int b;
int shift = 0;
int result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = poly.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
decoded.add(new GeoPoint(
(int) (lat*1E6 / 1E5), (int) (lng*1E6 / 1E5)));
}
return decoded;
}
}
RouteOverlay.java:
public class RouteOverlay extends Overlay {
/** GeoPoints representing this routePoints. **/
private final List<GeoPoint> routePoints;
/** Colour to paint routePoints. **/
private int colour;
/** Alpha setting for route overlay. **/
private static final int ALPHA = 120;
/** Stroke width. **/
private static final float STROKE = 4.5f;
/** Route path. **/
private final Path path;
/** Point to draw with. **/
private final Point p;
/** Paint for path. **/
private final Paint paint;
/**
* Public constructor.
*
* #param route Route object representing the route.
* #param defaultColour default colour to draw route in.
*/
public RouteOverlay(final Route route, final int defaultColour) {
super();
routePoints = route.getPoints();
colour = defaultColour;
path = new Path();
p = new Point();
paint = new Paint();
}
#Override
public final void draw(final Canvas c, final MapView mv,
final boolean shadow) {
super.draw(c, mv, shadow);
paint.setColor(colour);
paint.setAlpha(ALPHA);
paint.setAntiAlias(true);
paint.setStrokeWidth(STROKE);
paint.setStyle(Paint.Style.STROKE);
redrawPath(mv);
c.drawPath(path, paint);
}
/**
* Set the colour to draw this route's overlay with.
*
* #param c Int representing colour.
*/
public final void setColour(final int c) {
colour = c;
}
/**
* Clear the route overlay.
*/
public final void clear() {
routePoints.clear();
}
/**
* Recalculate the path accounting for changes to
* the projection and routePoints.
* #param mv MapView the path is drawn to.
*/
private void redrawPath(final MapView mv) {
final Projection prj = mv.getProjection();
path.rewind();
final Iterator<GeoPoint> it = routePoints.iterator();
prj.toPixels(it.next(), p);
path.moveTo(p.x, p.y);
while (it.hasNext()) {
prj.toPixels(it.next(), p);
path.lineTo(p.x, p.y);
}
path.setLastPoint(p.x, p.y);
}
}
And then you do this inside the Activity that includes the Map:
1-Add this function:
private Route directions(final GeoPoint start, final GeoPoint dest) {
Parser parser;
//https://developers.google.com/maps/documentation/directions/#JSON <- get api
String jsonURL = "http://maps.googleapis.com/maps/api/directions/json?";
final StringBuffer sBuf = new StringBuffer(jsonURL);
sBuf.append("origin=");
sBuf.append(start.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(start.getLongitudeE6()/1E6);
sBuf.append("&destination=");
sBuf.append(dest.getLatitudeE6()/1E6);
sBuf.append(',');
sBuf.append(dest.getLongitudeE6()/1E6);
sBuf.append("&sensor=true&mode=driving");
parser = new GoogleParser(sBuf.toString());
Route r = parser.parse();
return r;
}
2- Add this in onCreate() function:
MapView mapView = (MapView) findViewById(R.id.mapview); //or you can declare it directly with the API key
Route route = directions(new GeoPoint((int)(26.2*1E6),(int)(50.6*1E6)), new GeoPoint((int)(26.3*1E6),(int)(50.7*1E6)));
RouteOverlay routeOverlay = new RouteOverlay(route, Color.BLUE);
mapView.getOverlays().add(routeOverlay);
mapView.invalidate();
EDIT: If you get an exception, please use directions() function in an AsyncTask to avoid network processing on the UI thread.
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;
}
}