JavaFX How to throws exception message to label? - java

I write warehouse application and firstly I wrote code which will be displayed in console. Now i want to display it as window in javafx. How I can throw it to javaFX label? Below is code which i have as validators and now i want to throw it in javafx. I have also implement user service which send login and password and check it by validators. Im working in scenebuilder. Maybe anyone has easier solution for check login, password and throw information about wrong length?
Validator
public class UserValidator {
private UserDao userDao = UserDaoImpl.getInstance();
private static UserValidator instance = null;
public static UserValidator getInstance() {
if(instance == null) {
instance = new UserValidator();
}
return instance;
}
private final int LOGIN_MIN_LENGTH = 5;
private final int LOGIN_MAX_LENGTH = 20;
private final int PASSWORD_MIN_LENGTH = 8;
private final int PASSWORD_MAX_LENGTH = 20;
public boolean isValidateAddUser(User user) throws UserLoginIsExistException, UserLoginEnoughLengthException, UserPasswordEnoughLengthException,
UserPasswordIsOneCharUpCaseException {
if(isLoginEnoughLength(user.getLogin()))
throw new UserLoginEnoughLengthException("Login must be minimum 5 and maximum 20 letters!");
if(isPasswordEnoughLength(user.getPassword()))
throw new UserPasswordEnoughLengthException("Password must be minimum 8 and maximum 20 letters!");
if(isPasswordOneCharUpperCase(user.getPassword()))
throw new UserPasswordIsOneCharUpCaseException("Password must have one uppercase letter!");
if (isUserAlreadyExist(user.getLogin()))
throw new UserLoginIsExistException("Login is exist!");
return true;
}
public boolean isValidateUpdateUserPassword(String newPassword) throws UserPasswordEnoughLengthException,
UserPasswordIsOneCharUpCaseException{
if(isPasswordEnoughLength(newPassword)) {
throw new UserPasswordEnoughLengthException("Password must be minimum 8 and maximum 20 letters!");
}
if(isPasswordOneCharUpperCase(newPassword)) {
throw new UserPasswordIsOneCharUpCaseException("Password must have one uppercase letter!");
}
return true;
}
private boolean isLoginEnoughLength(String login) {
return login.length() < LOGIN_MIN_LENGTH || login.length() > LOGIN_MAX_LENGTH;
}
private boolean isPasswordEnoughLength(String password) {
return password.length() < PASSWORD_MIN_LENGTH || password.length() > PASSWORD_MAX_LENGTH;
}
private boolean isPasswordOneCharUpperCase(String password) {
for(char checkUpperCase : password.toCharArray()) {
if(Character.isUpperCase(checkUpperCase)) {
return false;
}
}
return true;
}
private boolean isUserAlreadyExist(String login) {
List<User> users = null;
users = userDao.getAllUsers();
for(User user : users) {
if(user.getLogin().equals(login)) {
return true;
}
}
return false;
}
}
UI
public class UserImpl implements UserService {
private UserValidator userValidator = UserValidator.getInstance();
private UserDao userDao = UserDaoImpl.getInstance();
private static UserImpl instance = null;
public static UserImpl getInstance() {
if (instance == null) {
instance = new UserImpl();
}
return instance;
}
public boolean addUser(User user) {
try {
if (userValidator.isValidateAddUser(user)) {
userDao.addUser(user);
return true;
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
return false;
}
UI facade
public class UserFacadeImpl implements UserFacade {
private static UserService userService = UserImpl.getInstance();
private static UserFacadeImpl instance = null;
public static UserFacadeImpl getInstance() {
if(instance == null) {
instance = new UserFacadeImpl();
}
return instance;
}
public boolean registerUser(User user) {
return userService.addUser(user);
}
Register Controller
public class RegisterControler {
String login, password, email;
private static UserFacade userFacade = UserFacadeImpl.getInstance();
#FXML
TextField fieldLogin;
#FXML
TextField fieldPassword;
#FXML
TextField fieldEmail;
#FXML
Label labelValidator;
public boolean isRegister() {
login = fieldLogin.getText();
password = fieldPassword.getText();
email = fieldEmail.getText();
User user = new User(login, password, email);
if (userFacade.registerUser(user)) {
labelValidator.setText("Register Successfully!");
}
else {
}
return false;
}
public void buttonRegister() {
isRegister();
}

Related

Implementing custom prefix remover token filter in lucene producing dirty tokens

i'm trying to implement a lucene filter to remove a prefix from a term in a query.
It seems that sometime after multiple queries, the filter has been reused so the char buffer is dirty.
Code below is simplified, prefix is an external parameter.
public static class PrefixFilter extends TokenFilter {
private final PackedTokenAttributeImpl termAtt = (PackedTokenAttributeImpl) addAttribute(CharTermAttribute.class);
public PrefixFilter(TokenStream in) {
super(in);
}
#Override
public final boolean incrementToken() throws IOException {
if (!input.incrementToken()) {
return false;
}
String value = new String(termAtt.buffer());
value = value.trim();
value = value.toLowerCase();
value = StringUtils.removeStart(value, "prefix_");
if (value.isBlank()) {
termAtt.setEmpty();
} else {
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
}
return true;
}
}
So after 10 or twelve queries, the value "prefix_a" became "abcde".
So i'm trying to add termBuffer offset end value in this way:
termAtt.setEmpty();
termAtt.resizeBuffer(value.length());
termAtt.copyBuffer(value.toCharArray(), 0, value.length());
termAtt.setLength(value.length());
termAtt.setOffset(0, value.length());
But i don't know if it's correct. Can anyone help me?
Thanks.
See if this helps you,
/**
* Standard number token filter.
*/
public class StandardnumberTokenFilter extends TokenFilter {
private final LinkedList<PackedTokenAttributeImpl> tokens;
private final StandardnumberService service;
private final Settings settings;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private final PositionIncrementAttribute posIncAtt = addAttribute(PositionIncrementAttribute.class);
private State current;
protected StandardnumberTokenFilter(TokenStream input, StandardnumberService service, Settings settings) {
super(input);
this.tokens = new LinkedList<>();
this.service = service;
this.settings = settings;
}
#Override
public final boolean incrementToken() throws IOException {
if (!tokens.isEmpty()) {
if (current == null) {
throw new IllegalArgumentException("current is null");
}
PackedTokenAttributeImpl token = tokens.removeFirst();
restoreState(current);
termAtt.setEmpty().append(token);
posIncAtt.setPositionIncrement(0);
return true;
}
if (input.incrementToken()) {
detect();
if (!tokens.isEmpty()) {
current = captureState();
}
return true;
} else {
return false;
}
}
private void detect() throws CharacterCodingException {
CharSequence term = new String(termAtt.buffer(), 0, termAtt.length());
Collection<CharSequence> variants = service.lookup(settings, term);
for (CharSequence ch : variants) {
if (ch != null) {
PackedTokenAttributeImpl token = new PackedTokenAttributeImpl();
token.append(ch);
tokens.add(token);
}
}
}
#Override
public void reset() throws IOException {
super.reset();
tokens.clear();
current = null;
}
#Override
public boolean equals(Object object) {
return object instanceof StandardnumberTokenFilter &&
service.equals(((StandardnumberTokenFilter)object).service) &&
settings.equals(((StandardnumberTokenFilter)object).settings);
}
#Override
public int hashCode() {
return service.hashCode() ^ settings.hashCode();
}
}
https://github.com/jprante/elasticsearch-plugin-bundle/blob/f63690f877cc7f50360faffbac827622c9d404ef/src/main/java/org/xbib/elasticsearch/plugin/bundle/index/analysis/standardnumber/StandardnumberTokenFilter.java

Global combine not producing output Apache Beam

I am trying to write an unbounded ping pipeline that takes output from a ping command and parses it to determine some statistics about the RTT (avg/min/max) and for now, just print the results.
I have already written an unbounded ping source that outputs each line as it comes in. The results are windowed every second for every 5 seconds of pings. The windowed data is fed to a Combine.globally call to statefully process the string outputs. The problem is that the accumulators are never merged and the output is never extracted. This means that the pipeline never continues past this point. What am I doing wrong here?
public class TestPingIPs {
public static void main(String[] args)
{
PipelineOptions options = PipelineOptionsFactory.create();
Pipeline pipeline = Pipeline.create(options);
String destination = "8.8.8.8";
PCollection<PingResult> res =
/*
Run the unbounded ping command. Only the lines where the result of the ping command are returned.
No statistics or first startup lines are returned here.
*/
pipeline.apply("Ping command",
PingCmd.read()
.withPingArguments(PingCmd.PingArguments.create(destination, -1)))
/*
Window the ping command strings into 5 second sliding windows produced every 1 second
*/
.apply("Window strings",
Window.into(SlidingWindows.of(Duration.standardSeconds(5))
.every(Duration.standardSeconds(1))))
/*
Parse and aggregate the strings into a PingResult object using stateful processing.
*/
.apply("Combine the pings",
Combine.globally(new ProcessPings()).withoutDefaults())
/*
Test our output to see what we get here
*/
.apply("Test output",
ParDo.of(new DoFn<PingResult, PingResult>() {
#ProcessElement
public void processElement(ProcessContext c)
{
System.out.println(c.element().getAvgRTT());
System.out.println(c.element().getPacketLoss());
c.output(c.element());
}
}));
pipeline.run().waitUntilFinish();
}
static class ProcessPings extends Combine.CombineFn<String, RttStats, PingResult> {
private long getRTTFromLine(String line){
long rtt = Long.parseLong(line.split("time=")[1].split("ms")[0]);
return rtt;
}
#Override
public RttStats createAccumulator()
{
return new RttStats();
}
#Override
public RttStats addInput(RttStats mutableAccumulator, String input)
{
mutableAccumulator.incTotal();
if (input.contains("unreachable")) {
_unreachableCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("General failure")) {
_transmitFailureCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("timed out")) {
_timeoutCount.inc();
mutableAccumulator.incPacketLoss();
}
else if (input.contains("could not find")) {
_unknownHostCount.inc();
mutableAccumulator.incPacketLoss();
}
else {
_successfulCount.inc();
mutableAccumulator.add(getRTTFromLine(input));
}
return mutableAccumulator;
}
#Override
public RttStats mergeAccumulators(Iterable<RttStats> accumulators)
{
Iterator<RttStats> iter = accumulators.iterator();
if (!iter.hasNext()){
return createAccumulator();
}
RttStats running = iter.next();
while (iter.hasNext()){
RttStats next = iter.next();
running.addAll(next.getVals());
running.addLostPackets(next.getLostPackets());
}
return running;
}
#Override
public PingResult extractOutput(RttStats stats)
{
stats.calculate();
boolean connected = stats.getPacketLoss() != 1;
return new PingResult(connected, stats.getAvg(), stats.getMin(), stats.getMax(), stats.getPacketLoss());
}
private final Counter _successfulCount = Metrics.counter(ProcessPings.class, "Successful pings");
private final Counter _unknownHostCount = Metrics.counter(ProcessPings.class, "Unknown hosts");
private final Counter _transmitFailureCount = Metrics.counter(ProcessPings.class, "Transmit failures");
private final Counter _timeoutCount = Metrics.counter(ProcessPings.class, "Timeouts");
private final Counter _unreachableCount = Metrics.counter(ProcessPings.class, "Unreachable host");
}
I would guess that there are some issues with the CombineFn that I wrote, but I can't seem to figure out what's going wrong here! I tried following the example here, but there's still something I must be missing.
EDIT: I added the ping command implementation below. This is running on a Direct Runner while I test.
PingCmd.java:
public class PingCmd {
public static Read read(){
if (System.getProperty("os.name").startsWith("Windows")) {
return WindowsPingCmd.read();
}
else{
return null;
}
}
WindowsPingCmd.java:
public class WindowsPingCmd extends PingCmd {
private WindowsPingCmd()
{
}
public static PingCmd.Read read()
{
return new WindowsRead.Builder().build();
}
static class PingCheckpointMark implements UnboundedSource.CheckpointMark, Serializable {
#VisibleForTesting
Instant oldestMessageTimestamp = Instant.now();
#VisibleForTesting
transient List<String> outputs = new ArrayList<>();
public PingCheckpointMark()
{
}
public void add(String message, Instant timestamp)
{
if (timestamp.isBefore(oldestMessageTimestamp)) {
oldestMessageTimestamp = timestamp;
}
outputs.add(message);
}
#Override
public void finalizeCheckpoint()
{
oldestMessageTimestamp = Instant.now();
outputs.clear();
}
// set an empty list to messages when deserialize
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
stream.defaultReadObject();
outputs = new ArrayList<>();
}
#Override
public boolean equals(#Nullable Object other)
{
if (other instanceof PingCheckpointMark) {
PingCheckpointMark that = (PingCheckpointMark) other;
return Objects.equals(this.oldestMessageTimestamp, that.oldestMessageTimestamp)
&& Objects.deepEquals(this.outputs, that.outputs);
}
else {
return false;
}
}
}
#VisibleForTesting
static class UnboundedPingSource extends UnboundedSource<String, PingCheckpointMark> {
private final WindowsRead spec;
public UnboundedPingSource(WindowsRead spec)
{
this.spec = spec;
}
#Override
public UnboundedReader<String> createReader(
PipelineOptions options, PingCheckpointMark checkpointMark)
{
return new UnboundedPingReader(this, checkpointMark);
}
#Override
public List<UnboundedPingSource> split(int desiredNumSplits, PipelineOptions options)
{
// Don't really need to ever split the ping source, so we should just have one per destination
return Collections.singletonList(new UnboundedPingSource(spec));
}
#Override
public void populateDisplayData(DisplayData.Builder builder)
{
spec.populateDisplayData(builder);
}
#Override
public Coder<PingCheckpointMark> getCheckpointMarkCoder()
{
return SerializableCoder.of(PingCheckpointMark.class);
}
#Override
public Coder<String> getOutputCoder()
{
return StringUtf8Coder.of();
}
}
#VisibleForTesting
static class UnboundedPingReader extends UnboundedSource.UnboundedReader<String> {
private final UnboundedPingSource source;
private String current;
private Instant currentTimestamp;
private final PingCheckpointMark checkpointMark;
private BufferedReader processOutput;
private Process process;
private boolean finishedPings;
private int maxCount = 5;
private static AtomicInteger currCount = new AtomicInteger(0);
public UnboundedPingReader(UnboundedPingSource source, PingCheckpointMark checkpointMark)
{
this.finishedPings = false;
this.source = source;
this.current = null;
if (checkpointMark != null) {
this.checkpointMark = checkpointMark;
}
else {
this.checkpointMark = new PingCheckpointMark();
}
}
#Override
public boolean start() throws IOException
{
WindowsRead spec = source.spec;
String cmd = createCommand(spec.pingConfiguration().getPingCount(), spec.pingConfiguration().getDestination());
try {
ProcessBuilder builder = new ProcessBuilder(cmd.split(" "));
builder.redirectErrorStream(true);
process = builder.start();
processOutput = new BufferedReader(new InputStreamReader(process.getInputStream()));
return advance();
} catch (Exception e) {
throw new IOException(e);
}
}
private String createCommand(int count, String dest){
StringBuilder builder = new StringBuilder("ping");
String countParam = "";
if (count <= 0){
countParam = "-t";
}
else{
countParam += "-n " + count;
}
return builder.append(" ").append(countParam).append(" ").append(dest).toString();
}
#Override
public boolean advance() throws IOException
{
String line = processOutput.readLine();
// Ignore empty/null lines
if (line == null || line.isEmpty()) {
line = processOutput.readLine();
}
// Ignore the 'Pinging <dest> with 32 bytes of data' line
if (line.contains("Pinging " + source.spec.pingConfiguration().getDestination())) {
line = processOutput.readLine();
}
// If the pings have finished, ignore
if (finishedPings) {
return false;
}
// If this is the start of the statistics, the pings are done and we can just exit
if (line.contains("statistics")) {
finishedPings = true;
}
current = line;
currentTimestamp = Instant.now();
checkpointMark.add(current, currentTimestamp);
if (currCount.incrementAndGet() == maxCount){
currCount.set(0);
return false;
}
return true;
}
#Override
public void close() throws IOException
{
if (process != null) {
process.destroy();
if (process.isAlive()) {
process.destroyForcibly();
}
}
}
#Override
public Instant getWatermark()
{
return checkpointMark.oldestMessageTimestamp;
}
#Override
public UnboundedSource.CheckpointMark getCheckpointMark()
{
return checkpointMark;
}
#Override
public String getCurrent()
{
if (current == null) {
throw new NoSuchElementException();
}
return current;
}
#Override
public Instant getCurrentTimestamp()
{
if (current == null) {
throw new NoSuchElementException();
}
return currentTimestamp;
}
#Override
public UnboundedPingSource getCurrentSource()
{
return source;
}
}
public static class WindowsRead extends PingCmd.Read {
private final PingArguments pingConfig;
private WindowsRead(PingArguments pingConfig)
{
this.pingConfig = pingConfig;
}
public Builder builder()
{
return new WindowsRead.Builder(this);
}
PingArguments pingConfiguration()
{
return pingConfig;
}
public WindowsRead withPingArguments(PingArguments configuration)
{
checkArgument(configuration != null, "configuration can not be null");
return builder().setPingArguments(configuration).build();
}
#Override
public PCollection<String> expand(PBegin input)
{
org.apache.beam.sdk.io.Read.Unbounded<String> unbounded =
org.apache.beam.sdk.io.Read.from(new UnboundedPingSource(this));
return input.getPipeline().apply(unbounded);
}
#Override
public void populateDisplayData(DisplayData.Builder builder)
{
super.populateDisplayData(builder);
pingConfiguration().populateDisplayData(builder);
}
static class Builder {
private PingArguments config;
Builder()
{
}
private Builder(WindowsRead source)
{
this.config = source.pingConfiguration();
}
WindowsRead.Builder setPingArguments(PingArguments config)
{
this.config = config;
return this;
}
WindowsRead build()
{
return new WindowsRead(this.config);
}
}
#Override
public int hashCode()
{
return Objects.hash(pingConfig);
}
}
One thing I notice in your code is that advance() always returns True. The watermark only advances on bundle completion, and I think it's runner-dependent whether a runner will ever complete a bundle if advance ever never returns False. You could try returning False after a bounded amount of time/number of pings.
You could also consider re-writing this as an SDF.

Binding DatePicker

I want to bindBiderectional() DatePicker. Here is what I did
#FXMLController("title.fxml")
public class Controller {
#FXML
private DatePicker dp_date_from;
#Inject
private Model model;
...
#PostConstruct
public void init(){
...
dp_date_from.valueProperty().bindBidirectional(model.dateFromProperty());
...
}
Model Class
#FlowScoped
public class Model {
private ObjectProperty<LocalDate> dateFrom;
public ObjectProperty<LocalDate> dateFromProperty() {
return dateFrom;
}
...
}
It throws an error:
io.datafx.controller.FxmlLoaderException:java.lang.reflect.InvocationTargetException
What can be the reason for that?
Error, is thrown in application itself, it doesn't write anything in a console. I've debegged the code, and when it comes to line dp_date_from.valueProperty... it goes here for throwing an exception:
public <T> ViewContext<T> createByController(Class<T> controllerClass, String fxmlName, ViewConfiguration viewConfiguration, Object... viewContextResources) throws FxmlLoadException {
try {
Object e = controllerClass.newInstance();
ViewMetadata metadata = new ViewMetadata();
FXMLController controllerAnnotation = (FXMLController)controllerClass.getAnnotation(FXMLController.class);
if(controllerAnnotation != null && !controllerAnnotation.title().isEmpty()) {
metadata.setTitle(controllerAnnotation.title());
}
if(controllerAnnotation != null && !controllerAnnotation.iconPath().isEmpty()) {
metadata.setGraphic(new ImageView(controllerClass.getResource(controllerAnnotation.iconPath()).toExternalForm()));
}
FXMLLoader loader = this.createLoader(e, fxmlName, viewConfiguration);
Node viewNode = (Node)loader.load();
ViewContext context = new ViewContext(viewNode, e, metadata, viewConfiguration, viewContextResources);
context.register(e);
context.register("controller", e);
this.injectFXMLNodes(context);
context.getResolver().injectResources(e);
Method[] var11 = e.getClass().getMethods();
int var12 = var11.length;
for(int var13 = 0; var13 < var12; ++var13) {
Method method = var11[var13];
if(method.isAnnotationPresent(PostConstruct.class)) {
method.invoke(e, new Object[0]);
}
}
return context;
} catch (Exception var15) {
throw new FxmlLoadException(var15);
}
}
Thanks, the error is due to I didn't initialized dateFrom. I've just added this part into Model class
public ObjectProperty<LocalDate> dateFromProperty() {
if(dateFrom == null){
dateFrom = new SimpleObjectProperty<>();
}
return dateFrom;
}
Thanks to everybody

entity can not be null?

I wanted to retrieve found object or a null from a database.
In my ProjectFollowerImpl, for a method useFollowingProject I return a single instance that matches the query, or null if the query returns no results.
#Override
public ProjectFollower userFollowingProject(Integer userId, Integer projectId) {
return (ProjectFollower) session.createCriteria(classType)
.add(Restrictions.eq("user.id", userId))
.add(Restrictions.eq("project.id", projectId))
.uniqueResult();
}
Then in a tapestry page, I have following methods:
public ProjectFollower getUserFollowingProject() {
return projectFollowerDao.userFollowingProject(loggedInUser.getId(), project.getId());
}
#CommitAfter
void onActionFromFollowProject() {
ProjectFollower pf = getUserFollowingProject();
if (pf != null) {
projectFollowerDao.delete(pf.getId());
} else {
pf = new ProjectFollower();
pf.setProjectId(project);
pf.setUserId(loggedInUser);
projectFollowerDao.merge(pf);
}
}
However, tapestry throws null pointer exception, stack trace:
com.rile.issuetracker.pages.Tracker getUserFollowingProject() Tracker.java 75
com.rile.issuetracker.pages.Tracker advised$onActionFromFollowProject_6d8b9673baf() Tracker.java 80
So why is it a problem to return a null value for a object? What am I doing wrong ?
UPDATE:
public class Tracker {
#Property
#SessionState
private User loggedInUser;
#Property
#Inject
private ProjectDao projectDao;
#Property
private Project projectP1, project;
#Property
private List<Project> projectList;
#Property
#Inject
private ProjectFollowerDao projectFollowerDao;
#Property
#Inject
private TicketDao ticketDao;
#Property
private List<Ticket> ticketList;
#Property
private Ticket ticketP1;
#Property
#Inject
private TicketFollowerDao ticketFollowerDao;
#Property
private Util util = new Util();
public boolean getLoggedIn() {
return loggedInUser.getEmail() != null;
}
#PageLoaded
void onPageLoad() {
projectList = projectDao.loadAll();
ticketList = ticketDao.loadAll();
}
void onActivate(Integer contextValue) {
if (contextValue != null) {
project = projectDao.getByID(contextValue);
}
if (project != null) {
List ticketListByProjectID = ticketDao.getTicketsByProjectID(project.getId());
if (!ticketListByProjectID.isEmpty()) {
ticketList = ticketListByProjectID;
} else {
ticketList = null;
}
}
}
public ProjectFollower getUserFollowingProject() {
return projectFollowerDao.userFollowingProject(loggedInUser.getId(), project.getId());
}
#CommitAfter
void onActionFromFollowProject() {
ProjectFollower pf = getUserFollowingProject();
if (pf != null) {
projectFollowerDao.delete(pf.getId());
} else {
pf = new ProjectFollower();
pf.setProjectId(project);
pf.setUserId(loggedInUser);
projectFollowerDao.merge(pf);
}
}
public boolean getIsUserFollowingTicket() {
return ticketFollowerDao.isUserFollowingTicket(loggedInUser.getId(), ticketP1.getId());
}
#CommitAfter
void onActionFromFollowTicket() {}
public String getActiveFor(String parameter) {
if (parameter == null || parameter.isEmpty()) {
return null;
}
switch (parameter) {
case "userFollowingProject":
return getUserFollowingProject() != null ? "active" : "null";
case "userFollowingTicket":
return getIsUserFollowingTicket() ? "anchor-active" : "anchor-inactive";
default:
return null;
}
}
}
From the complete code, it looks like the best bet is that project is null, after checking complete class, we see that its not injected, and its value is only set in onActivate function, if contextValue is not null and projectDao.getByID(contextValue) returns a non-null value.
Could you please confirm that is happenning correctly before the call to onActionFromFollowProject

Inner Class. What is its purpose?

Can someone tell me what the purpose of having inner classes? I can think of a few but may be they are not good reasons for using inner classes. My reasoning is that inner class is helpful when you want to use a class that no other classes can use. What else?
When I was learning Java we used inner classes for GUI event handling classes. It is sort of a "one time use" class that need not be available to other classes, and only is relevant to the class in which it resides.
Inner classes can be used to simulate closures: http://en.wikipedia.org/wiki/Closure_(computer_science)#Java
I use inner classes to define a structure that is best represented by the containing class, but doesn't necessarily make sense to use a separate external class to represent the structure.
To give an example I have a class that represents a particular type of network device, and the class has certain types of tests that can be run on that device. For each test there is also a potential set of errors that can be found. Each type of device may have a different structure for the errors.
With this you could do things like
List<Error> errors = RemoteDeviceA.getErrors();
With methods being available from the inner class, like
for ( Error error : errors ) {
System.out.println("MOnitor Type: " + error.getMonType());
...
}
Of course there are other ways to do this, this is just an inner class approach.
Simplified (aka incomplete) code for above:
public class RemoteDeviceA {
private String host;
private String user;
private String password;
private static List<Error> errors;
public RemoteDeviceA(String user, String host, String password) {
this.host = host;
this.user = user;
this.password = password;
login();
}
private void login() {
// Logs in
}
public void runTestA() {
List<Error> errorList = new ArrayList<Error>();
//loop through test results
if (!value.equals("0")) {
Error error = new Error(node, rackNum, shelfNum, slotNum, monType, value);
if (error.isError()) {
errorList.add(error);
}
}
setErrors(errorList);
}
private static void setErrors(List<Error> errors) {
RemoteDeviceA.errors = errors;
}
public List<Error> getErrors() {
return errors;
}
public class Error {
private String monType;
private String node;
private String rack;
private String shelf;
private String slot;
private String value;
private boolean error = false;
private boolean historyError = false;
private boolean critical = false;
private boolean criticalHistory = false;
Error(String node, String rack, String shelf, String slot,
String monType, String value) {
parseAlarm(node, rack, shelf, slot, monType, value);
}
private void parseAlarm(String node, String rack, String shelf,
String slot, String monType, String value) {
String modType = "";
if (monType.startsWith("ES_15") && !value.equals("0")) {
setMonType("ES_15");
setError(true);
} else if (monType.startsWith("SES_15") && !value.equals("0")) {
setMonType("SES_15");
setError(true);
} else if (monType.startsWith("BBE_15") && !value.equals("0")) {
setMonType("BBE_15");
setError(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(critical);
} else if (monType.startsWith("ES_24") && !value.equals("0")) {
setMonType("ES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("SES_24") && !value.equals("0")) {
setMonType("SES_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("BBE_24") && !value.equals("0")) {
setMonType("BBE_24");
setHistoryError(true);
setError(true);
} else if (monType.startsWith("UT_24") && !value.equals("0")) {
setMonType("UT_24");
setHistoryError(true);
setError(true);
setCriticalHistory(true);
} else if (monType.startsWith("UT_15") && !value.equals("0")) {
setMonType("UT_15");
setError(true);
setCritial(true);
} else if (monType.startsWith("LASPWR")) {
float laserPwr = Float.valueOf(value);
if (node.startsWith("LEM_EM")) {
if ((laserPwr < 8.0) || (laserPwr > 12.0)) {
setMonType("LASERPWR");
setError(true);
}
} else if (node.startsWith("LEM10")) {
if ((laserPwr < 18.0) || (laserPwr > 22.0)) {
setMonType("LASERPWR");
setError(true);
}
}
}
if (isError()) {
setNode(node);
setRack(rack);
setShelf(shelf);
setSlot(slot);
setValue(value);
setError(true);
}
}
private void setMonType(String monType) {
this.monType = monType;
}
public String getMonType() {
return monType;
}
private void setNode(String node) {
this.node = node;
}
public String getNode() {
return node;
}
public void setRack(String rack) {
this.rack = rack;
}
public String getRack() {
return rack;
}
public void setShelf(String shelf) {
this.shelf = shelf;
}
public String getShelf() {
return shelf;
}
public void setSlot(String slot) {
this.slot = slot;
}
public String getSlot() {
return slot;
}
private void setValue(String value) {
this.value = value;
}
public String getValue() {
return value;
}
private void setError(boolean error) {
this.error = error;
}
public boolean isError() {
return error;
}
public void setCritial(boolean critical) {
this.critical = critical;
}
public boolean isCritical() {
return critical;
}
public void setCriticalHistory(boolean criticalHistory) {
this.criticalHistory = criticalHistory;
}
public boolean isCriticalHistory() {
return criticalHistory;
}
public void setHistoryError(boolean historyError) {
this.historyError = historyError;
}
public boolean isHistoryError() {
return historyError;
}
}
}
A list implementation that internally uses a linked list to store the elements could make good use of an inner class to represent the nodes within the list. I think you've hit the nail on the head by saying that you'd use such a class where you want to use it internally to a class but don't want it exposed - a 'one off' class that is only really useful 'here'.
I use inner classes (in C++) in situations where multiple classes, unrelated through inheritance, have conceptually similar implementation details, which form an implicit part of the public interface and ought to be named similarly.
class lib::Identifier { ... };
class lib::Person {
public:
class Identifier : public lib::Identifier { ... };
};
class lib::File {
public:
class Identifier : public lib::Identifier { ... };
};
This makes it convenient to refer to Identifier, Person::Identifier, and File::Identifier as simply Identifier, in the appropriate scopes.

Categories

Resources