I have created a method in which i have multiple if conditions. Now i want to refactor these if conditions. What would be the best design pattern/strategy to overcome multiple if conditions?
if
(
poConfiguration.strSampleLoaderPluginClass != null
&& poConfiguration.strSampleLoaderPluginClass.equals("") == false
)
{
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
if
(
poConfiguration.strPreprocessingPluginClass != null
&& poConfiguration.strPreprocessingPluginClass.equals("") == false
)
{
setPreprocessingPluginClass(poConfiguration.strPreprocessingPluginClass);
}
if
(
poConfiguration.strFeatureExtractionPluginClass != null
&& poConfiguration.strFeatureExtractionPluginClass.equals("") == false
)
{
setFeatureExtractionPluginClass(poConfiguration.strFeatureExtractionPluginClass);
}
if
(
poConfiguration.strClassificationPluginClass != null
&& poConfiguration.strClassificationPluginClass.equals("") == false
)
{
setClassificationPluginClass(poConfiguration.strClassificationPluginClass);
}
Please share your thoughts with implementations, if possible. Thanks in advance
My first idea would be the polymorphism (Click here for more info), it depends from the concrete situation:
interface MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration);
public void process(PoConfiguration poConfiguration);
}
public class SampleLoader implements MyInterface {
public boolean checkCondition(PoConfiguration poConfiguration) {
return poConfiguration.strSampleLoaderPluginClass != null
&& !poConfiguration.strSampleLoaderPluginClass.isEmpty();
}
public void process(PoConfiguration poConfiguration) {
setSampleLoaderPluginClass(poConfiguration.strSampleLoaderPluginClass);
}
}
public class ClientAPI {
public void caller() {
for (MyInterface current : this.myInterfaces) {
if (current.checkCondition(current)) {
current.process();
}
}
}
You might try something like the following:
Create a Configuration class that contains ConfigurationItems
Each ConfigurationItem would have a name, value and a default value
As an improvement, you may want to create static values for the configuration items instead of using Strings.
TestConfig main Class
package com.example.config;
public class TestConfig {
static TestConfig me;
static String[][] confSettings = {{"sampleLoader","loaderDefault"}
,{"preProcessing","preProcessingDefualt"}
,{"featureExtraction","featureExtractionDefault"}
,{"classification","classificationDefault"}
};
// Object fields
Configuration configuration;
public static void main(String[] args) {
// TODO Auto-generated method stub
me = new TestConfig();
me.doWork();
}
private void doWork() {
configuration = new Configuration();
for (int i=0; i < confSettings.length; i++) {
configuration.addConfigurationItem(confSettings[i][0], confSettings[i][1], null);
}
configuration.setConfigurationItemDefault("classification", "newValue");
System.out.println("sampleLoader = " + configuration.getConfigurationItemValue("sampleLoader"));
System.out.println("classification = " + configuration.getConfigurationItemValue("classification"));
}
}
Configuration Class
package com.example.config;
import java.util.ArrayList;
import java.util.HashMap;
public class Configuration {
// Class fields
// Object fields
HashMap<String,Integer> itemNames;
ArrayList<ConfigurationItem> items;
public Configuration() {
items = new ArrayList<ConfigurationItem>();
itemNames = new HashMap<String,Integer>();
}
public Configuration addConfigurationItem(String name, String defaultValue, String value) {
if (itemNames.containsKey(name)) {
// handle duplicate configuration item
} else {
items.add(new ConfigurationItem(name, defaultValue, value));
Integer loc = new Integer(items.size()-1);
itemNames.put(name, loc);
}
return this;
}
public void setConfigurationItemDefault(String name, String defaultValue) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
items.get(loc).setDefaultValue(defaultValue);
}
}
public String getConfigurationItemValue(String name) {
int loc = getConfigurationItemIndex(name);
if (loc > -1) {
return items.get(loc).getValue();
} else {
// handle unknown parameter
return null;
}
}
private int getConfigurationItemIndex(String name) {
if (itemNames.containsKey(name)) {
return itemNames.get(name);
} else {
// handle unknown parameter
return -1;
}
}
}
ConfigurationItem Class
package com.example.config;
public class ConfigurationItem {
// Object fields
String name;
String value;
String defaultValue;
public ConfigurationItem(){};
public ConfigurationItem(String name, String defaultValue, String value) {
this.setName(name).setDefaultValue(defaultValue).setValue(value);
}
public ConfigurationItem setName(String name) {
this.name = name;
return this;
}
public ConfigurationItem setValue(String value) {
this.value = value;
return this;
}
public ConfigurationItem setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
return this;
}
public String getValue() {
if (value == null || value.length() == 0) {
return defaultValue;
} else {
return value;
}
}
}
Related
I want compare values of any class in java no matter the type, for example i have next class:
public class Car {
private int windows;
private int doors;
private int drive;
private String model;
public int getWindows() {
return windows;
}
public void setWindows(int windows) {
this.windows = windows;
}
public int getDoors() {
return doors;
}
public void setDoors(int doors) {
this.doors = doors;
}
public int getDrive() {
return drive;
}
public void setDrive(int drive) {
this.drive = drive;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
And this other:
public class Moto {
private String model;
private String color;
private int year;
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
And i want compare if is not null or empty attributes of this class, for example :
if(Validator.myClass(objectValue)){
}
else{
}
Class Validador example:
public class Validador {
public static boolean myClass(Object obj){
Class myClass = null;
String cla = obj.toString();
int a = cla.indexOf("#");
cla = cla.substring(0, a);
try {
myClass = Class.forName(cla);
Field[] fields = myClass.getDeclaredFields();
int contador =0;
for (Field field : fields) {
System.out.println("Field type is: " + field.getType());
System.out.println("Field name is: " + field.getName());
if(!field.getName().equals("") && field.getName() != null){
contador++;
}
}
log.info(contador);
} catch (Exception e) {
}
return true;
}
}
This line not compare if value is not null or empity this attribute:
if(!field.getName().equals("") && field.getName() != null){
How to do that?
I currently do it in the following way:
if(Nameclass != null && Nameclass.getNameAttributeA != null && !Nameclass.getNameAttributeA.equals(""){
}else{
}
Update
Not compare 2 object, only one, but not matter type Object, for example: i have obejct Car.class i want compare all or any attribute this class or do the same with others Object(class).
Thanks!
Instead of writing your own validator you can use Apache Commons Validator https://commons.apache.org/proper/commons-validator/apidocs/org/apache/commons/validator/package-summary.html
You can check if and object is not null with the following code:
if(motoObject!=null) {
} else {
}
But your question is not so clear. Can you add further details?
You should use Class Types, for example in class Car you can use:
private Integer doors;//default is null
The method you can use for your validation is:
public static boolean validator(Object myObject) {
Field[] fields = myObject.getClass().getDeclaredFields();
for (Field field : fields) {
try {
Object objectValue = field.get(myObject);
if (objectValue == null || objectValue.toString().length() == 0) {
System.out.println("null or empty field = '" + field.getName() + "' in : " + myObject.getClass().getCanonicalName());
return false; //or you can throw a exception with a message, is better that return a boolean
}
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(MyClass.class.getName()).log(Level.SEVERE, "Something is wrong", ex);
}
}
return true;
}
pd. Sorry for my english, isn't so good
I need to return the value of a method and also I need to print the name of the method including the object by which it is called. For example:
public class FindMethod {
public void accessor(String m){
String amount = "getamount()" ;
String str="";
if(m.equals("Receive(int)"))
str+= "LS."+amount;
System.out.println(str);
}
public static void main(String[] args)
{
FindMethod fm = new FindMethod();
fm.accessor("Receive(int)");
}
}
Result: LS.getamount()
The above program is printing the method name as a string including the object where LS is the object and getamount() is the method of another class LoanApprovalSystem().
But I need to print the integer value that will be returned by the result LS.getamount(). But I have returned LS.getamount() as a string. I am not sure how to return the actual value of LS.getamount() from the string.
Can any one give me some idea that, how can I return the value of the method getamount() which is given by a string?? I mean can I use the string LS.getamount() as a reference to call the method getamount() from the class LoanApprovalSystem()??
The class LoanApprovalSystem() is given below:
public class LoanApprovalSystem {
private static int amount;
private static String risklevel ;
private static boolean approve;
private static boolean message;
private static String result ;
public LoanApprovalSystem(){
}
void initialize(){
amount=0;
risklevel=null;
approve=false;
message=false;
}
public void Receive(int req){
amount = req;
}
public void Asses(int req){
if (req > 1000 && req <= 5000)
{
risklevel = "low";
approve = true;
}
else if (req > 5000 && req <= 10000)
{
risklevel = "high";
}
else
risklevel = " ";
}
public void Approval(int req){
if ((req > 10000) || ((req <= 10000) & getrisklevel() =="high"))
{
approve = false;
}
else if (amount <= 5000 && getrisklevel() == "low")
{
approve = true;
}
}
public void Sendmessage(String risklevel){
if(risklevel == "low")
{
message=true;
//System.out.println(message);
//System.out.println("Loan approved");
}
else
message=false;
}
public void Reply(boolean message, boolean approve){
if(message == true || approve == true)
{
result = ("Loan Approved");
//System.out.println("Loan Approved");
}
else
{
result = ("Loan Rejected");
//System.out.println("Loan Rejected");
}
}
public int getamount(){
return (amount);
}
public String getrisklevel(){
return(risklevel);
}
public boolean getapprove(){
return (approve);
}
public boolean getmessage(){
return(message);
}
public String getresult(){
return (result);
}
public String toString(){
String str = "";
str += "(" +result+ ").";
return str;
}
public static void main(String[] args){
LoanApprovalSystem LS = new LoanApprovalSystem();
TestdataGeneration testdata = new TestdataGeneration();
LS.initialize();
//for(int data:testdata.Testdata())
{
LS.Receive(testdata.thirddata());
LS.Asses(LS.getamount());
LS.Approval(LS.getamount());
LS.Sendmessage(LS.getrisklevel());
LS.Reply(LS.getmessage(), LS.getapprove());
System.out.println("Final state: "+LS);
}
}
}
Use reflection:
http://java.sun.com/docs/books/tutorial/reflect/member/methodInvocation.html
Class<?> c = Class.forName("className");
Method method = c.getDeclaredMethod ("methodName", parameterTypes)
Object o = method.invoke (objectToInvokeOn, paramList)
But usually you don't use reflection. Only if there is no other way to do.
Look for use and danger of reflection here https://softwareengineering.stackexchange.com/questions/123956/why-should-i-use-reflection
I have a method that return an object of a class.The object sets the properties of class and returns.
I have to traverse the object and get the value of the properties which the object has set before.
I tried to use for-each loop,iterator but failed to traverse.
Can someone please help me to get through this.Thanks in advance.
code:
public class ConsumerTool {
public MessageBean getMessages() {
MessageBean msgBean = new MessageBean();
msgBean.setAtmId(atmId.trim());
msgBean.setEventText(eventText.trim());
msgBean.setEventNumber(eventNumber.trim());
msgBean.setSeverity(severity.trim());
msgBean.setSubsystemID(subsystemID.trim());
msgBean.setUniqueEventID(uniqueEventID.trim());
msgBean.setTaskID(taskID.trim());
msgBean.setGenerator(generator.trim());
msgBean.setGeneratorBuildVsn(generatorBuildVsn.trim());
msgBean.setDateTime(dateTime.trim());
this.msgBean = msgBean;
return msgBean;
}
}
JavaBean class:
public class MessageBean implements java.io.Serializable {
public String dateTime;
public String severity;
public String eventText;
public String eventNumber;
public String generator;
public String generatorBuildVsn;
public String atmId;
public String uniqueEventID;
public String subsystemID;
public String taskID;
//System.out.println("dateTime2222222"+dateTime);
public String getAtmId() {
return this.atmId;
}
public void setAtmId(String n) {
this.atmId = n;
}
public String getDateTime() {
return this.dateTime;
}
public void setDateTime(String n) {
this.dateTime = n.trim();
}
public String getEventNumber() {
return this.eventNumber;
}
public void setEventNumber(String n) {
this.eventNumber = n;
}
public String getEventText() {
return this.eventText;
}
public void setEventText(String n) {
this.eventText = n;
}
public String getGenerator() {
return this.generator;
}
public void setGenerator(String n) {
this.generator = n;
}
public String getGeneratorBuildVsn() {
return this.generatorBuildVsn;
}
public void setGeneratorBuildVsn(String n) {
this.generatorBuildVsn = n;
}
public String getSeverity() {
return this.severity;
}
public void setSeverity(String n) {
this.severity = n;
}
public String getSubsystemID() {
return this.subsystemID;
}
public void setSubsystemID(String n) {
this.subsystemID = n;
}
public String getTaskID() {
return this.taskID;
}
public void setTaskID(String n) {
this.taskID = n;
}
public String getUniqueEventID() {
return this.uniqueEventID;
}
public void setUniqueEventID(String n) {
this.uniqueEventID = n;
}
}
The theme is the object sets the properties of javabean class and I have to get those values from UI.
In Jsp
<%
MessageBean consumer = msg.getMessages();
//Now here i want to iterate that consumer object
%>
As the MessagesBean seems to comply the javabeans specification, you can just use java.beans.Introspector for this.
MessageBean messageBean = consumerTool.getMessages();
// ...
BeanInfo beanInfo = Introspector.getBeanInfo(MessageBean.class);
for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
String name = property.getName();
Object value = property.getReadMethod().invoke(messageBean);
System.out.println(name + "=" + value);
}
This all is under the covers using the reflection API.
Update your edit reveals that you're intending to use this to present the data in JSP. This is then not really the right approach. Bite the bullet and specify every property separately. This way you've full control over the ordering.
I'm quite new to Java so this is probably pretty straight forward question.
I want to sort an ArrayList in the class MediaLib based on the natural order of a specified key.
I can't work out how to use my comparator (compareTo(MediaInterface, key)) which is in the Media class. Whats the best way to go about this?
package assign1;
import java.util.*;
public class Media implements MediaInterface {
private Map<String, Object> fields;
private static int compare;
public Media(String title, String format) {
fields = new TreeMap<String, Object>();
fields.put("title", title);
fields.put("format", format);
}
public Object get(String key) {
return fields.get(key);
}
public void put(String key, Object value) {
fields.put(key, value);
}
public boolean hasKeywords(String[] words, boolean combineWithAND) {
Collection<Object> values = (Collection<Object>) fields.values();
int count = 0;
int size = 0;
for (String s: words) {
for (Object o: values) {
String t = o.toString();
if (t.indexOf(s) >= 0) {
count++;
break;
}
}
size++;
}
if ((count == 0 && !combineWithAND) || (combineWithAND && (count != size))) {
return false;
}
return true;
}
public int compareTo(MediaInterface mi, String key) { //<<<<<<<------calling this!!
if (mi == null)
throw new NullPointerException();
Media m = (Media) mi;
Comparable mValue = (Comparable) m.get(key);
Comparable lValue = (Comparable) fields.get(key);
if ((mValue == null) && (lValue == null)){
return 0;
}
if ((lValue == null)){
return 1;
}
if ((mValue == null)){
return -1;
}
return (lValue).compareTo(mValue);
}
#Override
public int compareTo(MediaInterface mi) {
if (mi == null)
throw new NullPointerException();
Media m = (Media) mi;
Set<String> lSet = fields.keySet();
if (compareTo(m, "title") != 0) {
return compareTo(m, "title");
}
if (compareTo(m, "year") != 0) {
return compareTo(m, "year");
}
for (String s: lSet) {
if (compareTo(m, s) != 0) {
return compareTo(m, s);
}
}
return 0;
}
public boolean equals(Object object) {
if (object == null)
return false;
if (!(object instanceof Media))
return false;
Media m = (Media) object;
if (compareTo(m) != 0) {
return false;
}
return true;
}
}
package assign1;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
public class MediaLib implements Searchable {
private ArrayList<MediaInterface> media;
public MediaLib() {
media = new ArrayList<MediaInterface>();
}
#Override
public void add(MediaInterface mi) {
if (media.isEmpty()) {
media.add(mi);
}
else {
for (MediaInterface m: media) {
if (mi.equals(m)) {
return;
}
}
media.add(mi);
}
}
#Override
public boolean contains(MediaInterface mi) {
for (MediaInterface m: media) {
if (mi.equals(m)) {
return true;
}
}
return false;
}
#Override
public Collection<MediaInterface> findByKeyword(String[] words, boolean combineWithAND) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if (mi.hasKeywords(words, combineWithAND)) {
foundList.add(mi);
}
}
return foundList;
}
#Override
public Collection<MediaInterface> findByTitle(String str) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if ((mi.get("title")).equals(str)) {
foundList.add(mi);
}
}
return foundList;
}
#Override
public Collection<MediaInterface> getAllWithFormat(String formatName) {
Collection<MediaInterface> foundList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
if ((mi.get("format")).equals(formatName)) {
foundList.add(mi);
}
}
return foundList;
}
public Collection<MediaInterface> getAll() {
Collection<MediaInterface> fullList = new ArrayList<MediaInterface>();
for (MediaInterface mi: media) {
fullList.add(mi);
}
return fullList;
}
#Override
public void removeAllWithKeyword(String[] words, boolean combineWithAND) {
Collection<MediaInterface> foundList = findByKeyword(words, combineWithAND);
for (MediaInterface mi: foundList) {
media.remove(mi);
}
}
#Override
public void removeAllWithFormat(String format) {
Collection<MediaInterface> foundList = getAllWithFormat(format);
for (MediaInterface mi: foundList) {
media.remove(mi);
}
}
#Override
public void sort() {
Collections.sort(media);
}
#Override
public void sort(final String fieldName) {
Collections.sort(media, new Media.compareTo(MediaInterface, fieldName)) //<<<<<--------Trying to call compareTo()
}
}
public void parse(java.io.BufferedReader br) throws java.io.IOException {
while(br.readLine()!= null) {
Media mi = new Media(/n br.readLine(), br.readLine());
while
}
}
}
You already implement the Comparable interface in your MediaInterface class, this is a generic interface, so you then implement Comparable<MediaInterface> which will then require you to implement a method with the signature
public int compareTo(final MediaInterface other)
This is why your call to Collections.sort(media); compiles
In order to sort by a specific field name, you need to provide an instance of a Comparator, the easiest way to do this will be to create an inner class in your Media class which you can then pass into Collections.sort. For example
public class Media implements MediaInterface {
public static final class FieldComparator implements Comparator<Media> {
private final String field;
public FieldComparator(final String field) {
this.field = field;
}
public int compare(final Media a, final Media b) {
// implementation to compare a.field to b.field
}
}
}
You can then rewrite your second sort method as
#Override
public void sort(final String fieldName) {
Collections.sort(media, new Media.FieldComparator(fieldName));
}
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.