Why object is becoming null when accessed out of thread - java

In the following program I'm inserting
files[i].lastModified() value in allFiles HashMap in RThread class
when I tried to retrive the value of lastModified from allFiles HashMap in the main class the value is coming as null. So instead of lastModified value I placed File object directly in HashMpa then it worked.
Anyone guide me the concept behind this.
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
public class RCFLister {
ConcurrentHashMap allFiles = new ConcurrentHashMap();
String fileType = null;
/**
* #param args
*/
public static void main(String[] args) {
RCFLister rcFileLister = new RCFLister();
rcFileLister.recentFiles(args);
}
public void recentFiles(String[] args) {
int days = 1;
ThreadGroup rootthreadGr = new ThreadGroup("rootsThreadGroup");
// reading number of days
if (args.length > 0 && args[0] != null) {
days = Integer.valueOf(args[0]);
}
// reading file type
if (args.length > 0 && args[0] != null) {
fileType = args[1];
}
fileType = "png";
// fileextFilter = new FileExtensionFilter(fileType);
File[] roots = File.listRoots();
List threads = new ArrayList();
for (int i = 0; i < roots.length; i++) {
// System.out.println(roots[i].getAbsolutePath());
// rfThread = null;
RThread rfThread = new RThread(roots[i]);
Thread t = new Thread(rfThread);
t.start();
threads.add(t);
}
for (int i = 0; i < threads.size(); i++) {
try {
((Thread) threads.get(i)).join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
ValueComparator vc = new ValueComparator(allFiles);
TreeMap sortedMap = new TreeMap(vc);
sortedMap.putAll(allFiles);
System.out.println(sortedMap.size());
Iterator it = sortedMap.keySet().iterator();
while (it.hasNext()) {
Object key = it.next();
System.out.println(key + " " + sortedMap.get(key));
}
}
private class ValueComparator implements Comparator {
Map allFiles;
public ValueComparator(Map allFiles) {
this.allFiles = allFiles;
}
public int compare(Object o1, Object o2) {
if (((Long) allFiles.get(o1)) >= ((Long) allFiles.get(o2))) {
return -1;
} else {
return 1;
}
}
}
private class RThread implements Runnable {
File rootFolder;
RThread(File root) {
rootFolder = root;
}
public void run() {
getFiles(rootFolder);
}
public void getFiles(File folder) {
File[] files = folder.listFiles();
for (int i = 0; files != null && i < files.length; i++) {
// System.out.println(files[i].getAbsolutePath());
if (files[i].isDirectory()) {
getFiles(files[i]);
} else if (fileType == null
|| (fileType != null && files[i].getName().endsWith(
fileType))) {
String filename = null;
try {
filename = files[i].getCanonicalPath();
} catch (Exception e) {
e.printStackTrace();
}
if(files[i].lastModified()!=0)
allFiles.put(filename, files[i].lastModified());
}
}
}
}
}

compare() method of ValueComparator never returns 0. Return 0 means equality which is missing so even if key is present it is not found.
Also the key is String(filename) and you are comparing by value (long). Need to rethink how you want to store data.
Just to make sure it is only problem, print CocurrentHashMap.
Do use Generic, it looks tedious at beginning but is really not that bad. It will help to compiler code without warning and achieve type safety.

Related

How to save an instance of a JavaFX javafx.scene.shape.Path to a file

I am trying to save a javafx.scene.shape.Path to a file (at least its elements) however since Path is non-serializable and its PathElement as well it has proven very difficult.
Could someone inform me of a way to either convert the object to a String (preferred), JSON or something else?
Here are all the ways I have tried saving the object:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import javafx.scene.shape.Path;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
class Test {
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
Path path;
Gson gson = builder.create();
{
Rectangle rectangle = new Rectangle(100, 100);
Polygon polygon = new Polygon(0, 0, 50, 50, 0, 50);
path = (Path) Shape.subtract(rectangle, polygon);
}
try {
String completePathObject = gson.toJson(path);
System.out.println(completePathObject);
} catch (IllegalArgumentException e) {
e.printStackTrace();
// java.lang.IllegalArgumentException: class com.sun.javafx.util.WeakReferenceQueue$ListEntry declares multiple JSON fields named next
}
try {
String pathObjectElements = gson.toJson(path.getElements());
System.out.println(pathObjectElements);
} catch (IllegalArgumentException e) {
e.printStackTrace();
// java.lang.IllegalArgumentException: class com.sun.javafx.util.WeakReferenceQueue$ListEntry declares multiple JSON fields named next
}
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.set"))) {
objectOutputStream.writeObject(path);
} catch (IOException e) {
e.printStackTrace();
// java.io.NotSerializableException: javafx.scene.shape.Path
}
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.set"))) {
objectOutputStream.writeObject(path.getElements());
} catch (IOException e) {
e.printStackTrace();
// java.io.NotSerializableException: javafx.scene.shape.Path$2
}
}
}
Nodes contain a lot of properties you'd need to convert to a form that can be written to a file.
Since your last attempt indicates you'll be satisfied with writing the path elements to the file, you could convert the PathElements to parts of a SVG path and also implement logic for parsing the elements PathElements from a svg path string.
The following doesn't accept all possible SVG paths and may accept some invalid paths:
public class SVGConverter {
private enum PathElementType {
ARC('a', ArcTo.class, ArcTo::new,
ArcTo::radiusXProperty,
ArcTo::radiusYProperty,
ArcTo::XAxisRotationProperty,
ArcTo::largeArcFlagProperty,
ArcTo::sweepFlagProperty,
ArcTo::xProperty,
ArcTo::yProperty),
CLOSE_PATH('z', ClosePath.class, ClosePath::new),
CUBIC_CURVE('c', CubicCurveTo.class, CubicCurveTo::new,
CubicCurveTo::controlX1Property,
CubicCurveTo::controlY1Property,
CubicCurveTo::controlX2Property,
CubicCurveTo::controlY2Property,
CubicCurveTo::xProperty,
CubicCurveTo::yProperty),
H_LINE_TO('h', HLineTo.class, HLineTo::new,
HLineTo::xProperty),
LINE_TO('l', LineTo.class, LineTo::new,
LineTo::xProperty, LineTo::yProperty),
MOVE_TO('m', MoveTo.class, MoveTo::new,
MoveTo::xProperty, MoveTo::yProperty),
QUAD_CURVE_TO('q', QuadCurveTo.class, QuadCurveTo::new,
QuadCurveTo::controlXProperty, QuadCurveTo::controlYProperty,
QuadCurveTo::xProperty, QuadCurveTo::yProperty),
V_LINE_TO('v', VLineTo.class, VLineTo::new,
VLineTo::yProperty);
private final char letter;
private final String typeName;
private final Supplier<? extends PathElement> factory;
private final Function[] propertyGetters;
<T extends PathElement> PathElementType(char letter, Class<T> type, Supplier<T> factory, Function<T, ? extends Property<?>>... propertyGetters) {
this.letter = letter;
this.typeName = type.getName();
this.factory = factory;
this.propertyGetters = propertyGetters;
}
}
private final Map<String, PathElementType> ELEMENT_TYPES_BY_TYPE;
private final Map<Character, PathElementType> ELEMENT_TYPES_BY_LETTER;
public SVGConverter() {
ELEMENT_TYPES_BY_LETTER = new HashMap<>();
ELEMENT_TYPES_BY_TYPE = new HashMap<>();
for (PathElementType et : PathElementType.values()) {
ELEMENT_TYPES_BY_LETTER.put(et.letter, et);
ELEMENT_TYPES_BY_TYPE.put(et.typeName, et);
}
}
public String pathToSvg(Path path) {
StringBuilder sb = new StringBuilder();
for (PathElement element : path.getElements()) {
PathElementType elementType = ELEMENT_TYPES_BY_TYPE.get(element.getClass().getName());
if (elementType == null) {
throw new IllegalArgumentException("Unknown PathElement type: " + element.getClass().getName());
}
// specify path element type
char c = elementType.letter;
if (element.isAbsolute()) {
c = Character.toUpperCase(c);
}
sb.append(c);
// write property values
for (Function f : elementType.propertyGetters) {
Property property = (Property) f.apply(element);
sb.append((property instanceof BooleanProperty)
// special treatment for booleans to convert true/false to 1/0
? (((BooleanProperty) property).get() ? "1" : "0")
: property.getValue().toString()).append(' ');
}
}
// trim, if necessary
int lastIndex = sb.length() - 1;
if (lastIndex >= 0 && sb.charAt(lastIndex) == ' ') {
sb.deleteCharAt(lastIndex);
}
return sb.toString();
}
private static final String NUMBER_PATTERN_STRING = "[+-]?\\d*\\.\\d*(?:[eE][+-]?\\d+)?";
private static final Pattern NUMBER_PATTERN = Pattern.compile("(?<![\\d.+-])(" + NUMBER_PATTERN_STRING + ')');
private static final Pattern SVG_PATTERN = Pattern.compile("([aAcChHlLvmMqQVzZ])((?:\\s*" + NUMBER_PATTERN_STRING + "(?:[\\s,]+" + NUMBER_PATTERN_STRING + ")*)?)");
// parses doubles from number sequence
private static double[] getNumberMatches(Matcher m, int count) {
double[] result = new double[count];
for (int i = 0; i < count; i++) {
if (!m.find()) {
throw new IllegalArgumentException("missing numbers");
}
result[i] = Double.parseDouble(m.group(1));
}
if (m.find()) {
throw new IllegalArgumentException("too many numbers");
}
return result;
}
public Path svgToPath(String svg) {
Path path = new Path();
Matcher matcher = SVG_PATTERN.matcher(svg);
while (matcher.find()) {
// find out path element type
char c = matcher.group(1).charAt(0);
PathElementType elementType = ELEMENT_TYPES_BY_LETTER.get(Character.toLowerCase(c));
if (elementType == null) {
throw new IllegalArgumentException("Unknown path type " + c);
}
PathElement element = (PathElement) elementType.factory.get();
element.setAbsolute(Character.isUpperCase(c));
// retrieve parameters
if (elementType.propertyGetters.length > 0) {
Matcher numberMatcher = NUMBER_PATTERN.matcher(matcher.group(2));
double[] numbers = getNumberMatches(numberMatcher, elementType.propertyGetters.length);
for (int i = 0; i < elementType.propertyGetters.length; i++) {
Property property = (Property) elementType.propertyGetters[i].apply(element);
property.setValue((property instanceof BooleanProperty)
? (numbers[i] == 1) // convert to boolean (true iff 1.0)
: numbers[i]);
}
}
path.getElements().add(element);
}
return path;
}
}
Note: This does not restore any kind of bindings that may have existed before converting to string of course.

How to iterate column values in an object's list?

Here's my code:
public String generateEISReports_PDF(){
surveyReportService.setSurveyReportDA(surveyReportDA);
surveyReportList = surveyReportService.getSurveyReport(surveyType, surveyDate, projectCode, employeeCode);
if(surveyReportList != null){
System.out.println(surveyReportList + "testing");
System.out.println(surveyReportList.size() + "size ito");
for (SurveyReport surveyReport : surveyReportList) {
System.out.println(surveyReport.getRiskRank().toString() + "asdf");
surveyReports.add(surveyReport);
}
}
this.compileTheJasperReports();
return SUCCESS;
}
I am getting the whole row values with this code as an object. I want to iterate the field values in every list of objects. How can I do that?
By using reflection you can achieve that. Following is the code. This might help you.
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SurveyReport {
public int localServeryCont; // if you make it private then changes have to be done in 'SurveyIterator' inner class.
public String surveyReporterName;
public static void main(String[] args) {
List<SurveyReport> surveyReportList = new ArrayList<SurveyReport>();
SurveyReport sr = new SurveyReport(); //first object creation
sr.localServeryCont = 10;
sr.surveyReporterName = "AAA";
surveyReportList.add(sr);
sr = new SurveyReport(); //second object creation
sr.localServeryCont = 100;
sr.surveyReporterName = "BBB";
surveyReportList.add(sr); //two objects are in the list-object.
for (SurveyReport surveyReport : surveyReportList) {
Iterator<String> itr = surveyReport.iterator(); //You can work around with 'java.lang.Iterable' to use 'foreach' loop
while (itr.hasNext()) { //this is what you might be expecting
System.out.println("SurveyReport's object's values : " + itr.next());
}
}
}
public Iterator<String> iterator() { //here is method to get iterator object.
return new SurveyIterator();
}
private class SurveyIterator implements Iterator<String> { //creating 'SurveyIterator' INNER class
private int totalAvailableField = SurveyReport.class.getDeclaredFields().length;
int cursor = 0;
Field[] surveyReportFields = SurveyReport.class.getFields();
#Override
public boolean hasNext() {
return cursor != totalAvailableField;
}
#Override
public String next() {
String next = null;
try {
next = (surveyReportFields[cursor].get(SurveyReport.this)).toString();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
cursor++;
return next;
}
#Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}

Java: Why isn't this method recognized?

I am having a problem where a method from another class is not being recognized as existing by Eclipse, even though all the other methods are. I have no idea why this is happening, and cannot figure it out. I get the error The method getData() is undefined for the type TMXReader.TMXHandler when I try doing this:
package tiled.simple.reader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import tiled.simple.core.Map;
import tiled.simple.core.MapLayer;
import tiled.simple.core.TileSet;
import davidiserovich.TMXLoader.TMXHandler;
import davidiserovich.TMXLoader.TileMapData;
TMXHandler handler = new TMXHandler();
handler.getData();
Here is the TMXHandler class:
package davidiserovich.TMXLoader;
import java.util.HashMap;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
//import android.sax.StartElementListener;
public class TMXHandler extends DefaultHandler {
/*
* This is an SAX2 XML parser that interprets the input TMX file and creates
* a TileMapData object.
*/
// NOTE: Map Object loading is not yet implemented
// Markers for which tag we're in
private boolean inTileSet, inTile, inLayer, inData, inObjectGroup,
inProperties;
// ID of the current tile that we're adding properties to.
// This is actually an OFFSET from firstGID of the tile in
// the tileset. Beware.
private String currentTileID;
private String currentObjectGroupName;
TileMapData.TMXObject currentObject;
TileMapData.TileSet currentTileSet;
TileMapData.Layer currentLayer;
HashMap<String, HashMap<String, String>> currentTileSetProperties;
HashMap<String, String> currentLayerProperties;
private TileMapData data;
/*
* These fields hold the buffer and data to help decode the long stream of
* gids in the data field
*/
private char buffer[];
private int bufferIndex;
private int currentX;
private int currentY;
public int MAX_INT_DECIMAL_LENGTH = 10;
public TMXHandler() {
super();
buffer = new char[MAX_INT_DECIMAL_LENGTH];
bufferIndex = 0;
currentX = 0;
currentY = 0;
}
public TileMapData getData() {
return data;
}
#Override
public void startDocument() throws SAXException {
data = new TileMapData();
}
#Override
public void endDocument() throws SAXException {
}
#Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
if (localName.equals("map")) {
// inMap = true;
// Check that the orientation is orthogonal
if (!(atts.getValue("orientation").equals("orthogonal"))) {
throw new SAXException(
"Unsupported orientation. Parse Terminated.");
}
data.orientation = atts.getValue("orientation");
data.height = Integer.parseInt(atts.getValue("height"));
data.width = Integer.parseInt(atts.getValue("width"));
data.tilewidth = Integer.parseInt(atts.getValue("tilewidth"));
data.tileheight = Integer.parseInt(atts.getValue("tileheight"));
// data.sectionId = atts.getValue("id");
} else if (localName.equals("tileset")) {
inTileSet = true;
currentTileSet = new TileMapData.TileSet();
currentTileSet.firstGID = Integer.parseInt(atts
.getValue("firstgid"));
currentTileSet.tileWidth = Integer.parseInt(atts
.getValue("tilewidth"));
currentTileSet.tileHeight = Integer.parseInt(atts
.getValue("tileheight"));
currentTileSet.name = atts.getValue("name");
currentTileSetProperties = new HashMap<String, HashMap<String, String>>();
} else if (inTileSet && localName.equals("image")) {
currentTileSet.ImageFilename = atts.getValue("source");
currentTileSet.imageWidth = Integer
.parseInt(atts.getValue("width"));
currentTileSet.imageHeight = Integer.parseInt(atts
.getValue("height"));
} else if (inTileSet && localName.equals("tile")) {
inTile = true;
currentTileID = atts.getValue("id");
} else if (inTile && localName.equals("properties")) {
inProperties = true;
currentTileSetProperties.put(currentTileID,
new HashMap<String, String>());
} else if (inLayer && localName.equals("properties")) {
inProperties = true;
} else if (inTile && inProperties && localName.equals("property")) {
(currentTileSetProperties.get(currentTileID)).put(
atts.getValue("name"), atts.getValue("value"));
} else if (inLayer && inProperties && localName.equals("property")) {
currentLayerProperties.put(atts.getValue("name"),
atts.getValue("value"));
} else if (localName.equals("layer")) {
inLayer = true;
currentLayer = new TileMapData.Layer();
currentLayer.name = atts.getValue("name");
currentLayer.width = Integer.parseInt(atts.getValue("width"));
currentLayer.height = Integer.parseInt(atts.getValue("height"));
if (atts.getValue("opacity") != null)
currentLayer.opacity = Double.parseDouble(atts
.getValue("opacity"));
currentLayer.tiles = new long[currentLayer.height][currentLayer.width];
currentLayerProperties = new HashMap<String, String>();
} else if (localName.equals("data")) {
/*
* Data is loaded directly into the int array in characters() We
* just check if the encoding is supported here.
*/
inData = true;
String encoding = atts.getValue("encoding");
if (!encoding.equals("csv")) {
throw new SAXException(
"Unsupported encoding. Parse Terminated.");
}
} else if (localName.equals("objectgroup")) {
inObjectGroup = true;
currentObjectGroupName = atts.getValue("name");
} else if (localName.equals("object")) {
currentObject = new TileMapData.TMXObject();
currentObject.name = atts.getValue("name");
currentObject.type = atts.getValue("type");
currentObject.x = Integer.parseInt(atts.getValue("x"));
currentObject.y = Integer.parseInt(atts.getValue("y"));
currentObject.width = Integer.parseInt(atts.getValue("width"));
currentObject.height = Integer.parseInt(atts.getValue("height"));
if (inObjectGroup) {
currentObject.objectGroup = currentObjectGroupName;
} else {
currentObject.objectGroup = null;
}
}
}
#Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (localName.equals("map")) {
// inMap = false;
} else if (localName.equals("tileset")) {
inTileSet = false;
currentTileSet.properties = currentTileSetProperties;
currentTileSetProperties = null;
data.tilesets.add(currentTileSet);
currentTileSet = null; // Clear it just in case
} else if (localName.equals("tile")) {
inTile = false;
currentTileID = "-1"; // -1 won't be produced when searching for
// properties. Just a safeguard for
// improperly formatted files.
} else if (localName.equals("properties")) {
inProperties = false;
} else if (localName.equals("layer")) {
inLayer = false;
currentLayer.properties = currentLayerProperties;
data.layers.add(currentLayer);
currentLayer = null; // Clear it just in case
} else if (localName.equals("data")) {
inData = false;
// In case we missed the last entry (no non-numeral chars before tag
// end)
if (bufferIndex > 0) {
currentLayer.tiles[currentY][currentX] = Long
.parseLong(new String(buffer, 0, bufferIndex));
}
// Clear buffer
bufferIndex = 0;
currentX = 0;
currentY = 0;
} else if (localName.equals("objectgroup")) {
inObjectGroup = false;
} else if (localName.equals("object")) {
data.objects.add(currentObject);
}
}
#Override
public void characters(char ch[], int start, int length) {
/*
* Java has no unsigned types, so we have to use a long instead of an
* int so we can "simulate" an unsigned int. Disgusting. Anyway, we're
* going to add the numbers from the character stream to a buffer until
* we hit a comma, at which point we empty the buffer and convert it to
* a long, and dump it into the array. These are raw, so the horizontal
* and vertical flip bits may be set - to get the actual GID number,
* we'll use TileMapData's getGIDAt(x, y), which will mask it properly.
*/
if (inData) {
for (int i = 0; i < length; i++) {
if (ch[start + i] <= '9' && ch[start + i] >= '0') {
buffer[bufferIndex] = ch[start + i];
// Log.d("Wrote to index", String.valueOf(bufferIndex));
bufferIndex++;
} else {
// When we hit a comma or any non-number character, empty
// the buffer and enter the relevant
// GID into the data field
// int what = Integer.parseInt(new String(buffer, 0,
// bufferIndex));
// Log.d("Number", new String(buffer, 0, bufferIndex));
String nextNumber = new String(buffer, 0, bufferIndex);
if ((nextNumber != null) && ((nextNumber.trim()) != "")
&& (bufferIndex != 0)) {
// Log.d("Checking", nextNumber + " yes");
currentLayer.tiles[currentY][currentX] = Long
.parseLong(nextNumber);
bufferIndex = 0;
// Move to the next tile
if (currentX < (currentLayer.width - 1)) {
currentX++;
} else if (currentY < (currentLayer.height - 1)) {
currentX = 0;
currentY++;
}
}
}
}
}
}
}
Auto-complete shows all the other methods as usable, but for some reason getData "doesn't exist"...
I'm sure this is apparent for experienced Java programmers, but I have no idea why this is happening... so if anyone could tell me why, I'd be grateful. Thanks!
Change this:
TMXHandler handler = new TMXHandler;
To this:
TMXHandler handler = new TMXHandler();
EDIT
If it's just a typo issue... and if your question is complete... You may have forgot to put it in a class ? :<
import davidiserovich.TMXLoader.TMXHandler;
public class Main {
public static void main(String[] args) {
TMXHandler handler = new TMXHandler();
handler.getData();
}
}
You have to create object. You have forget ()
TMXHandler handler = new TMXHandler();
Are you sure the java code which is referring TMXHandler class have correct TMXHandler.class file in Runtime. This may be caused by old TMXHandler.class which dont have getData() method defined.
maybe try a clean build
TMXHandler handler = new TMXHandler;
The above line is the culprit.
- When we call new on a Class name its always accompanied by () as postfix, which indicates the constructor of the class whose object is now created on the heap.
- And this line gives the opportunity to step in, to initialize the state of the object before the Actual object is assigned to the Object reference variable.
So it should be....
TMXHandler handler = new TMXHandler();
I solved it... turns out that the one project already had a class named TMXHandler, so it was referring to that, and not my other project... A very stupid mistake. :

assigning values to objects in arrays

package macroreader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class MacroReader {
public static Macro[] macroArray = new Macro[20];
public static int macroID;
public static BufferedReader br;
public static void main(String[] args) throws IOException {
br = new BufferedReader(new FileReader("Macros.txt"));
String currentLine;
while((currentLine = br.readLine()) != null) {
if(currentLine.equalsIgnoreCase("#newmacro")) {
br.mark(1000);
createMacro();
br.reset();
}
}
if (br != null) {
br.close();
}
}
public static void createMacro() throws IOException {
String currentLine;
macroID = getEmptyMacro();
while((currentLine = br.readLine()) != null && !currentLine.equalsIgnoreCase("#newmacro")) {
macroArray[macroID].readMacro(currentLine);
}
macroArray[macroID].inUse = true;
macroArray[macroID].printData();
}
public static int getEmptyMacro() {
for(int i = 0; i < macroArray.length; i++) {
if(!macroArray[i].inUse) {
return i;
}
}
return 0;
}
}
rather than assigning the values read from the file reader to the specified object in the array, in this case 'macroID', it assigns the values to all objects in the array
just edited in the whole file now but the issue is around the createMacro() void
here is my Macro class
package macroreader;
public class Macro {
public static String key;
public static String[] commands = new String[20];
public static boolean inUse;
public static void readMacro(String input) {
if (!input.equals("")) {
if (input.startsWith("key = ")) {
key = input.substring(6);
System.out.println("Key Value for Macro set to " + key);
} else {
for (int i = 0; i < commands.length; i++) {
if (commands[i] == null) {
commands[i] = input;
System.out.println("Command [" + input + "] assigned");
break;
}
}
}
}
}
public static void printData() {
System.out.println("Macro Key: " + key);
for(int i = 0; i < commands.length; i++) {
if(commands[i] != null) {
System.out.println(commands[i]);
}
}
}
}
As I suspected - your inUse is static, so it will always be the same for all instances of the class. As are your other class members.
The classic cause of "changing everything in an array" is if you have actually assigned the same object to every element in the array. We can't tell whether you're doing that because you didn't show us the initialization of macroArray, but it might be like:
Macro m = new Macro();
for (int i = 0; i < macroArray.length; i++) {
macroArray[i] = m;
}
This will cause the results you describe. To fix it, create a separate object for every element of the array:
for (int i = 0; i < macroArray.length; i++) {
macroArray[i] = new Macro();
}

lines of a class in Java

I have a class in Java which is written bellow.I want to know does that has normal size or it is big and huge and should be broken into some pieces:
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class AddressTree
{
private AddressNode structureRoot, userRoot;
private String xmlAddress;
public AddressTree(String XMLaddress)
{
this.xmlAddress = XMLaddress;
createEmptyTree();
startParsing();
}
private void startParsing()
{
AddressXMLParser handler = new AddressXMLParser(this);
try
{
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
File xml = new File(xmlAddress);
parser.parse(xml, handler);
ArrayList<AddressNode> rawNodes = createRawNodes(handler.getAddressStructure());
createTreeFromRawNodes(rawNodes, handler.getStartItem());
for (int i = 0; i < handler.getFinalItems().size(); i++)
{
getAddressNode(handler.getFinalItems().get(i), structureRoot).setIsFinal(true);
}
}
catch (StartAddressNodeNotFoundException ex)
{
Logger.getLogger(AddressTree.class.getName()).log(Level.SEVERE, null, ex);
}
catch (ParserConfigurationException ex)
{
}
catch (SAXException ex)
{
}
catch (IOException ex)
{
}
}
private void createEmptyTree()
{
structureRoot = new AddressNode("root", null);
userRoot = new AddressNode("root", null);
}
public void setValue(String nodeName, String value) throws AddressNodeNotFoundException
{
AddressNode node = getAddressNode(nodeName, userRoot);
if (node != null)
{
node.setNodeValue(value);
}
else
{
throw new AddressNodeNotFoundException();
}
}
public ArrayList<String> getCompleteAddress()
{
return null;
}
public boolean isAddressCompleted()
{
AddressNode iterator = userRoot;
while (iterator.getAllChilds().size() != 0)
{
iterator = iterator.getAllChilds().get(0);
}
if (getAddressNode(iterator.getNodeName(), structureRoot).isFinal())
{
return true;
}
else
{
return false;
}
}
public List<String> getSubAddressItems(String addressItem)
{
ArrayList<String> subAddressItems = new ArrayList<String>();
List<AddressNode> childNodes = getAddressNode(addressItem, structureRoot).getAllChilds();
for (int i = 0; i < childNodes.size(); i++)
{
subAddressItems.add(childNodes.get(i).getNodeName());
}
return subAddressItems;
}
private AddressNode getAddressNode(String nodeName, AddressNode root)
{
ArrayList<AddressNode> graphNodes = new ArrayList<AddressNode>();
ArrayList<AddressNode> passedNodes = new ArrayList<AddressNode>();
graphNodes.add(root);
while (graphNodes.size() != 0)
{
AddressNode cureNode = graphNodes.remove(0);
passedNodes.add(cureNode);
if (cureNode.getNodeName().equals(nodeName))
{
return cureNode;
}
else
{
for (int i = 0; i < cureNode.getAllChilds().size(); i++)
{
if (!passedNodes.contains(cureNode.getAllChilds().get(i)))
{
graphNodes.add(cureNode.getAllChilds().get(i));
}
}
}
}
return null;
}
private ArrayList<AddressNode> createRawNodes(TreeMap<String, ArrayList<String>> addressStructure)
{
int itemsSize = addressStructure.size();
ArrayList<AddressNode> tmpNodes = new ArrayList<AddressNode>();
ArrayList<AddressNode> finalNodes = new ArrayList<AddressNode>();
for (int i = 0; i < itemsSize; i++)
{
String curKey = addressStructure.firstKey();
ArrayList<String> curSubItems = addressStructure.remove(curKey);
AddressNode curNode = new AddressNode(curKey);
finalNodes.add(new AddressNode(curKey));
for (int j = 0; j < curSubItems.size(); j++)
{
curNode.addChlid(curSubItems.get(j));
}
tmpNodes.add(curNode);
}
for (int i = 0; i < finalNodes.size(); i++)
{
for (int j = 0; j < tmpNodes.get(i).getAllChilds().size(); j++)
{
AddressNode childNode = null;
boolean existNodeBefore = false;
for (int k = 0; k < finalNodes.size(); k++)
{
if (finalNodes.get(k).getNodeName().equals(tmpNodes.get(i).getAllChilds().get(j).getNodeName()))
{
childNode = finalNodes.get(k);
existNodeBefore = true;
}
}
if (!existNodeBefore)
{
finalNodes.get(i).addChlid(tmpNodes.get(i).getAllChilds().get(j).getNodeName());
}
else
{
finalNodes.get(i).addChildNode(childNode);
}
}
}
return finalNodes;
}
private void createTreeFromRawNodes(ArrayList<AddressNode> rawNodes, String rootName) throws StartAddressNodeNotFoundException
{
if (rootName == null)
{
throw new StartAddressNodeNotFoundException();
}
for (int i = 0; i < rawNodes.size(); i++)
{
if (rawNodes.get(i).getNodeName().equals(rootName))
{
structureRoot.addChildNode(rawNodes.get(i));
rawNodes.get(i).setParent(structureRoot);
}
}
}
public void addAddressItem(String itemName) throws AddressStructureAbusingException
{
AddressNode iterator = userRoot;
while (iterator.getAllChilds().size() > 0)
{
iterator = iterator.getAllChilds().get(0);
}
AddressNode fatherNode = getAddressNode(iterator.getNodeName(), structureRoot);
for (int i = 0; i < fatherNode.getAllChilds().size(); i++)
{
if (fatherNode.getAllChilds().get(i).getNodeName().equals(itemName))
{
iterator.addChlid(itemName);
return;
}
}
throw new AddressStructureAbusingException();
}
public void removeLastAddressItem() throws AddressNodeNotFoundException
{
if (userRoot.getAllChilds().size() > 0)
{
AddressNode iterator = userRoot;
while (iterator.getAllChilds().get(0).getAllChilds().size() > 0)
{
iterator = iterator.getAllChilds().get(0);
}
iterator.clearChilds();
}
else
{
throw new AddressNodeNotFoundException();
}
}
}
if it has to be broken how?
Your class has 230 lines - that's by no means excessive. However, size alone is only a very vague indicator of whether a class should be broken up.
A more general indicator is cohesion - basically, most of a class's methods should be using most of its fields. But that also isn't a problem in your class - it looks OK.
it has several responsibilites as I can see:
XML parsing (the representation)
XML manipulation (AddressNode)
hold parsing's output (the model)
at least I separate these two responsabilities in at least two separated classes.
NB
not concerned by the question there are also several empty catch blocks, see here why they are a bad idea
I've certainly seen bigger classes than that.
If you're finding it hard to read, I suggest strongly recommend putting some comments in there.
As long as your class revolves around a specific purpose, it should be as big as it needs to be to perform that purpose.
You may want to adapt
if (foo) {
bar();
} else {
fum();
}
instead. This allows the code to be shorter in length, allowing you to see more at once on the screen.
Also. Never have empty catch blocks. Consider "throw new RuntimeException("unexpected", e)" in them.

Categories