MimeMessage can't use inner class - java

We are trying to run some standard Java code to send a message via Javamail from a 3rd part application, problem we have is there is a bug in the application meaning it isn't able to use inner classes.
Before anyone asks, please don't ask to fix the application, as it's not within our control. The company who owns the application has suggested others resolve the issue by creating a separate class, instead of using the inner class of RecipientType within setRecipients.
We have tried to no avail to get this to work, creating a new class for RecipientType, although we are having trouble referencing it as it's not a method within setRecipients.
Would be grateful if anyone has an idea of how to get round having to use an inner class within MimeMessage? Is there a way we can hard code this?
Additional info:
This is what we are calling in the application
// new MIME message, version 1.0:
javax.mail.Message message = new javax.mail.internet.MimeMessage(session);
message.setHeader("MIME-Version" , "1.0" );
message.setFrom(new javax.mail.internet.InternetAddress(fromEmailAddress, fromEmailPersonal ));
message.setRecipients(javax.mail.Message.RecipientType.TO, javax.mail.internet.InternetAddress.parse( recipientEmailAddress ));
message.setSubject( emailSubject );
message.setText(emailBody);
javax.mail.Transport.send(message);
This is the section of Message.java that is failing
/**
* This inner class defines the types of recipients allowed by
* the Message class. The currently defined types are TO,
* CC and BCC.
*
* Note that this class only has a protected constructor, thereby
* restricting new Recipient types to either this class or subclasses.
* This effectively implements an enumeration of the allowed Recipient
* types.
*
* The following code sample shows how to use this class to obtain
* the "TO" recipients from a message.
* <blockquote><pre>
*
* Message msg = folder.getMessages(1);
* Address[] a = m.getRecipients(Message.RecipientType.TO);
*
* </pre></blockquote>
*
* #see javax.mail.Message#getRecipients
* #see javax.mail.Message#setRecipients
* #see javax.mail.Message#addRecipients
*/
public static class RecipientType implements Serializable {
/**
* The "To" (primary) recipients.
*/
public static final RecipientType TO = new RecipientType("To");
/**
* The "Cc" (carbon copy) recipients.
*/
public static final RecipientType CC = new RecipientType("Cc");
/**
* The "Bcc" (blind carbon copy) recipients.
*/
public static final RecipientType BCC = new RecipientType("Bcc");
/**
* The type of recipient, usually the name of a corresponding
* Internet standard header.
*
* #serial
*/
protected String type;
private static final long serialVersionUID = -7479791750606340008L;
/**
* Constructor for use by subclasses.
*
* #param type the recipient type
*/
protected RecipientType(String type) {
this.type = type;
}
/**
* When deserializing a RecipientType, we need to make sure to
* return only one of the known static final instances defined
* in this class. Subclasses must implement their own
* <code>readResolve</code> method that checks for their known
* instances before calling this super method.
*
* #return the RecipientType object instance
* #exception ObjectStreamException for object stream errors
*/
protected Object readResolve() throws ObjectStreamException {
if (type.equals("To"))
return TO;
else if (type.equals("Cc"))
return CC;
else if (type.equals("Bcc"))
return BCC;
else
throw new InvalidObjectException(
"Attempt to resolve unknown RecipientType: " + type);
}
#Override
public String toString() {
return type;
}
}
This is the custom class we tried to implement in place of the inner class, labelled RecipientType
import javax.mail.*;
import javax.activation.*;
import java.lang.*;
import java.io.*;
import java.util.*;
import java.text.ParseException;
public class RecipientType implements Serializable {
/**
* The "To" (primary) recipients.
*/
public static final RecipientType TO = new RecipientType("To");
/**
* The "Cc" (carbon copy) recipients.
*/
public static final RecipientType CC = new RecipientType("Cc");
/**
* The "Bcc" (blind carbon copy) recipients.
*/
public static final RecipientType BCC = new RecipientType("Bcc");
/**
* The type of recipient, usually the name of a corresponding
* Internet standard header.
*
* #serial
*/
protected String type;
private static final long serialVersionUID = -7479791750606340008L;
/**
* Constructor for use by subclasses.
*
* #param type the recipient type
*/
protected RecipientType(String type) {
this.type = type;
}
/**
* When deserializing a RecipientType, we need to make sure to
* return only one of the known static final instances defined
* in this class. Subclasses must implement their own
* <code>readResolve</code> method that checks for their known
* instances before calling this super method.
*
* #return the RecipientType object instance
* #exception ObjectStreamException for object stream errors
*/
protected Object readResolve() throws ObjectStreamException {
if (type.equals("To"))
return TO;
else if (type.equals("Cc"))
return CC;
else if (type.equals("Bcc"))
return BCC;
else
throw new InvalidObjectException(
"Attempt to resolve unknown RecipientType: " + type);
}
#Override
public String toString() {
return type;
}
}
This is how we tried implementing the custom class
message.setRecipients(RecipientType.TO,
javax.mail.internet.InternetAddress.parse( recipientEmailAddress ));
We get the following error:
Unable to parse expression; undefined method: addRecipient for class: javax.mal.Message (line: 29, col:2)

Related

Can not extend directly enum [duplicate]

I want to take an existing enum and add more elements to it as follows:
enum A {a,b,c}
enum B extends A {d}
/*B is {a,b,c,d}*/
Is this possible in Java?
No, you can't do this in Java. Aside from anything else, d would then presumably be an instance of A (given the normal idea of "extends"), but users who only knew about A wouldn't know about it - which defeats the point of an enum being a well-known set of values.
If you could tell us more about how you want to use this, we could potentially suggest alternative solutions.
Enums represent a complete enumeration of possible values. So the (unhelpful) answer is no.
As an example of a real problem take weekdays, weekend days and, the union, days of week. We could define all days within days-of-week but then we would not be able to represent properties special to either weekdays and weekend-days.
What we could do, is have three enum types with a mapping between weekdays/weekend-days and days-of-week.
public enum Weekday {
MON, TUE, WED, THU, FRI;
public DayOfWeek toDayOfWeek() { ... }
}
public enum WeekendDay {
SAT, SUN;
public DayOfWeek toDayOfWeek() { ... }
}
public enum DayOfWeek {
MON, TUE, WED, THU, FRI, SAT, SUN;
}
Alternatively, we could have an open-ended interface for day-of-week:
interface Day {
...
}
public enum Weekday implements Day {
MON, TUE, WED, THU, FRI;
}
public enum WeekendDay implements Day {
SAT, SUN;
}
Or we could combine the two approaches:
interface Day {
...
}
public enum Weekday implements Day {
MON, TUE, WED, THU, FRI;
public DayOfWeek toDayOfWeek() { ... }
}
public enum WeekendDay implements Day {
SAT, SUN;
public DayOfWeek toDayOfWeek() { ... }
}
public enum DayOfWeek {
MON, TUE, WED, THU, FRI, SAT, SUN;
public Day toDay() { ... }
}
The recommended solution to this is the extensible enum pattern.
This involves creating an interface and using that where you currently use the enum. Then make the enum implement the interface. You can add more constants by adding an additional enum/class that also extends the interface. Here is the general idea:
public interface TrafficLights {
public abstract String getColour();
}
public enum StandardTrafficLights implements TrafficLights {
RED, YELLOW, GREEN;
public String getColour() {
return name();
}
}
public enum WeirdTrafficLights implements TrafficLights {
DOUBLE_RED;
public String getColour() {
return name();
}
}
Note that if you want something like TrafficLights.valueof(String) you will have to implement it yourself.
Under the covers your ENUM is just a regular class generated by the compiler. That generated class extends java.lang.Enum. The technical reason you can't extend the generated class is that the generated class is final. The conceptual reasons for it being final are discussed in this topic. But I'll add the mechanics to the discussion.
Here is a test enum:
public enum TEST {
ONE, TWO, THREE;
}
The resulting code from javap:
public final class TEST extends java.lang.Enum<TEST> {
public static final TEST ONE;
public static final TEST TWO;
public static final TEST THREE;
static {};
public static TEST[] values();
public static TEST valueOf(java.lang.String);
}
Conceivably you could type this class on your own and drop the "final". But the compiler prevents you from extending "java.lang.Enum" directly. You could decide NOT to extend java.lang.Enum, but then your class and its derived classes would not be an instanceof java.lang.Enum ... which might not really matter to you any way!
enum A {a,b,c}
enum B extends A {d}
/*B is {a,b,c,d}*/
can be written as:
public enum All {
a (ClassGroup.A,ClassGroup.B),
b (ClassGroup.A,ClassGroup.B),
c (ClassGroup.A,ClassGroup.B),
d (ClassGroup.B)
...
ClassGroup.B.getMembers() contains {a,b,c,d}
How it can be useful: Let say we want something like:
We have events and we are using enums. Those enums can be grouped by similar processing. If we have operation with many elements, then some events starts operation, some are just step and other end the operation. To gather such operation and avoid long switch case we can group them as in example and use:
if(myEvent.is(State_StatusGroup.START)) makeNewOperationObject()..
if(myEnum.is(State_StatusGroup.STEP)) makeSomeSeriousChanges()..
if(myEnum.is(State_StatusGroup.FINISH)) closeTransactionOrSomething()..
Example:
public enum AtmOperationStatus {
STARTED_BY_SERVER (State_StatusGroup.START),
SUCCESS (State_StatusGroup.FINISH),
FAIL_TOKEN_TIMEOUT (State_StatusGroup.FAIL,
State_StatusGroup.FINISH),
FAIL_NOT_COMPLETE (State_StatusGroup.FAIL,
State_StatusGroup.STEP),
FAIL_UNKNOWN (State_StatusGroup.FAIL,
State_StatusGroup.FINISH),
(...)
private AtmOperationStatus(StatusGroupInterface ... pList){
for (StatusGroupInterface group : pList){
group.addMember(this);
}
}
public boolean is(StatusGroupInterface with){
for (AtmOperationStatus eT : with.getMembers()){
if( eT .equals(this)) return true;
}
return false;
}
// Each group must implement this interface
private interface StatusGroupInterface{
EnumSet<AtmOperationStatus> getMembers();
void addMember(AtmOperationStatus pE);
}
// DEFINING GROUPS
public enum State_StatusGroup implements StatusGroupInterface{
START, STEP, FAIL, FINISH;
private List<AtmOperationStatus> members = new LinkedList<AtmOperationStatus>();
#Override
public EnumSet<AtmOperationStatus> getMembers() {
return EnumSet.copyOf(members);
}
#Override
public void addMember(AtmOperationStatus pE) {
members.add(pE);
}
static { // forcing initiation of dependent enum
try {
Class.forName(AtmOperationStatus.class.getName());
} catch (ClassNotFoundException ex) {
throw new RuntimeException("Class AtmEventType not found", ex);
}
}
}
}
//Some use of upper code:
if (p.getStatus().is(AtmOperationStatus.State_StatusGroup.FINISH)) {
//do something
}else if (p.getStatus().is(AtmOperationStatus.State_StatusGroup.START)) {
//do something
}
Add some more advanced:
public enum AtmEventType {
USER_DEPOSIT (Status_EventsGroup.WITH_STATUS,
Authorization_EventsGroup.USER_AUTHORIZED,
ChangedMoneyAccountState_EventsGroup.CHANGED,
OperationType_EventsGroup.DEPOSIT,
ApplyTo_EventsGroup.CHANNEL),
SERVICE_DEPOSIT (Status_EventsGroup.WITH_STATUS,
Authorization_EventsGroup.TERMINAL_AUTHORIZATION,
ChangedMoneyAccountState_EventsGroup.CHANGED,
OperationType_EventsGroup.DEPOSIT,
ApplyTo_EventsGroup.CHANNEL),
DEVICE_MALFUNCTION (Status_EventsGroup.WITHOUT_STATUS,
Authorization_EventsGroup.TERMINAL_AUTHORIZATION,
ChangedMoneyAccountState_EventsGroup.DID_NOT_CHANGED,
ApplyTo_EventsGroup.DEVICE),
CONFIGURATION_4_C_CHANGED(Status_EventsGroup.WITHOUT_STATUS,
ApplyTo_EventsGroup.TERMINAL,
ChangedMoneyAccountState_EventsGroup.DID_NOT_CHANGED),
(...)
At above if we have some fail (myEvent.is(State_StatusGroup.FAIL)) then iterating by previous events we can easily check if we must revert money transfer by:
if(myEvent2.is(ChangedMoneyAccountState_EventsGroup.CHANGED)) rollBack()..
It can be useful for:
including explicite meta-data about processing logic, less to remember
implementing some of multi-inheritance
we don't want to use class structures, ex. for sending short status messages
In case you missed it, there's a chapter in the excellent Joshua Bloch's book "Effective Java, 2nd edition".
Chapter 6 - Enums and Annotations
Item 34 : Emulate extensible enums with interfaces
Just the conclusion :
A minor disadvantage of the use of interfaces to emulate extensible enums is
those implementations cannot be inherited from one enum type to another. In the
case of our Operation example, the logic to store and retrieve the symbol associated
with an operation is duplicated in BasicOperation and ExtendedOperation.
In this case, it doesn’t matter because very little code is duplicated. If there were a
a larger amount of shared functionality, you could encapsulate it in a helper class or
a static helper method to eliminate the code duplication.
In summary, while you cannot write an extensible enum type, you can
emulate it by writing an interface to go with a basic enum type that implements
the interface. This allows clients to write their own enums that implement
the interface. These enums can then be used wherever the basic enum type can be
used, assuming APIs are written in terms of the interface.
Here is a way how I found how to extend a enum into other enum, is a very straighfoward approach:
Suposse you have a enum with common constants:
public interface ICommonInterface {
String getName();
}
public enum CommonEnum implements ICommonInterface {
P_EDITABLE("editable"),
P_ACTIVE("active"),
P_ID("id");
private final String name;
EnumCriteriaComun(String name) {
name= name;
}
#Override
public String getName() {
return this.name;
}
}
then you can try to do a manual extends in this way:
public enum SubEnum implements ICommonInterface {
P_EDITABLE(CommonEnum.P_EDITABLE ),
P_ACTIVE(CommonEnum.P_ACTIVE),
P_ID(CommonEnum.P_ID),
P_NEW_CONSTANT("new_constant");
private final String name;
EnumCriteriaComun(CommonEnum commonEnum) {
name= commonEnum.name;
}
EnumCriteriaComun(String name) {
name= name;
}
#Override
public String getName() {
return this.name;
}
}
of course every time you need to extend a constant you have to modify your SubEnum files.
This is how I enhance the enum inheritance pattern with runtime check in static initializer.
The BaseKind#checkEnumExtender checks that "extending" enum declares all the values of the base enum in exactly the same way so #name() and #ordinal() remain fully compatible.
There is still copy-paste involved for declaring values but the program fails fast if somebody added or modified a value in the base class without updating extending ones.
Common behavior for different enums extending each other:
public interface Kind {
/**
* Let's say we want some additional member.
*/
String description() ;
/**
* Standard {#code Enum} method.
*/
String name() ;
/**
* Standard {#code Enum} method.
*/
int ordinal() ;
}
Base enum, with verifying method:
public enum BaseKind implements Kind {
FIRST( "First" ),
SECOND( "Second" ),
;
private final String description ;
public String description() {
return description ;
}
private BaseKind( final String description ) {
this.description = description ;
}
public static void checkEnumExtender(
final Kind[] baseValues,
final Kind[] extendingValues
) {
if( extendingValues.length < baseValues.length ) {
throw new IncorrectExtensionError( "Only " + extendingValues.length + " values against "
+ baseValues.length + " base values" ) ;
}
for( int i = 0 ; i < baseValues.length ; i ++ ) {
final Kind baseValue = baseValues[ i ] ;
final Kind extendingValue = extendingValues[ i ] ;
if( baseValue.ordinal() != extendingValue.ordinal() ) {
throw new IncorrectExtensionError( "Base ordinal " + baseValue.ordinal()
+ " doesn't match with " + extendingValue.ordinal() ) ;
}
if( ! baseValue.name().equals( extendingValue.name() ) ) {
throw new IncorrectExtensionError( "Base name[ " + i + "] " + baseValue.name()
+ " doesn't match with " + extendingValue.name() ) ;
}
if( ! baseValue.description().equals( extendingValue.description() ) ) {
throw new IncorrectExtensionError( "Description[ " + i + "] " + baseValue.description()
+ " doesn't match with " + extendingValue.description() ) ;
}
}
}
public static class IncorrectExtensionError extends Error {
public IncorrectExtensionError( final String s ) {
super( s ) ;
}
}
}
Extension sample:
public enum ExtendingKind implements Kind {
FIRST( BaseKind.FIRST ),
SECOND( BaseKind.SECOND ),
THIRD( "Third" ),
;
private final String description ;
public String description() {
return description ;
}
ExtendingKind( final BaseKind baseKind ) {
this.description = baseKind.description() ;
}
ExtendingKind( final String description ) {
this.description = description ;
}
}
Based on #Tom Hawtin - tackline answer we add switch support,
interface Day<T> {
...
T valueOf();
}
public enum Weekday implements Day<Weekday> {
MON, TUE, WED, THU, FRI;
Weekday valueOf(){
return valueOf(name());
}
}
public enum WeekendDay implements Day<WeekendDay> {
SAT, SUN;
WeekendDay valueOf(){
return valueOf(name());
}
}
Day<Weekday> wds = Weekday.MON;
Day<WeekendDay> wends = WeekendDay.SUN;
switch(wds.valueOf()){
case MON:
case TUE:
case WED:
case THU:
case FRI:
}
switch(wends.valueOf()){
case SAT:
case SUN:
}
I tend to avoid enums, because they are not extensible. To stay with the example of the OP, if A is in a library and B in your own code, you can't extend A if it is an enum. This is how I sometimes replace enums:
// access like enum: A.a
public class A {
public static final A a = new A();
public static final A b = new A();
public static final A c = new A();
/*
* In case you need to identify your constant
* in different JVMs, you need an id. This is the case if
* your object is transfered between
* different JVM instances (eg. save/load, or network).
* Also, switch statements don't work with
* Objects, but work with int.
*/
public static int maxId=0;
public int id = maxId++;
public int getId() { return id; }
}
public class B extends A {
/*
* good: you can do like
* A x = getYourEnumFromSomeWhere();
* if(x instanceof B) ...;
* to identify which enum x
* is of.
*/
public static final A d = new A();
}
public class C extends A {
/* Good: e.getId() != d.getId()
* Bad: in different JVMs, C and B
* might be initialized in different order,
* resulting in different IDs.
* Workaround: use a fixed int, or hash code.
*/
public static final A e = new A();
public int getId() { return -32489132; };
}
There are some pits to avoid, see the comments in the code. Depending on your needs, this is a solid, extensible alternative to enums.
I suggest you take the other way around approach.
Instead of extending the existing enumeration, create a larger one and create a subset of it.
For exemple if you had an enumeration called PET and you wanted to extend it to ANIMAL you should do this instead:
public enum ANIMAL {
WOLF,CAT, DOG
}
EnumSet<ANIMAL> pets = EnumSet.of(ANIMAL.CAT, ANIMAL.DOG);
Be careful, pets is not an immutable collections, you might want to use Guava or Java9 for more safety.
As an aid to understanding why extending an Enum is not reasonable at the language implementation level to consider what would happen if you passed an instance of the extended Enum to a routine that only understands the base Enum. A switch that the compiler promised had all cases covered would in fact not cover those extended Enum values.
This further emphasizes that Java Enum values are not integers such as C's are, for instances: to use a Java Enum as an array index you must explicitly ask for its ordinal() member, to give a java Enum an arbitrary integer value you must add an explicit field for that and reference that named member.
This is not a comment on the OP's desire, just on why Java ain't never going to do it.
Having had this same problem myself I'd like to post my perspective. I think that there are a couple motivating factors for doing something like this:
You want to have some related enum codes, but in different classes. In my case I had a base class with several codes defined in an associated enum. At some later date (today!) I wanted to provide some new functionality to the base class, which also meant new codes for the enum.
The derived class would support both the base classes' enum as well as its own. No duplicate enum values! So: how to have an enum for the subclass that includes the enum's of its parent along with its new values.
Using an interface doesn't really cut it: you can accidentally get duplicate enum values. Not desirable.
I ended up just combining the enums: this ensures that there cannot be any duplicate values, at the expense of being less tightly tied to its associated class. But, I figured the duplicate issue was my main concern...
In the hopes this elegant solution of a colleague of mine is even seen in this long post I'd like to share this approach for subclassing which follows the interface approach and beyond.
Please be aware that we use custom exceptions here and this code won't compile unless you replace it with your exceptions.
The documentation is extensive and I hope it's understandable for most of you.
The interface that every subclassed enum needs to implement.
public interface Parameter {
/**
* Retrieve the parameters name.
*
* #return the name of the parameter
*/
String getName();
/**
* Retrieve the parameters type.
*
* #return the {#link Class} according to the type of the parameter
*/
Class<?> getType();
/**
* Matches the given string with this parameters value pattern (if applicable). This helps to find
* out if the given string is a syntactically valid candidate for this parameters value.
*
* #param valueStr <i>optional</i> - the string to check for
* #return <code>true</code> in case this parameter has no pattern defined or the given string
* matches the defined one, <code>false</code> in case <code>valueStr</code> is
* <code>null</code> or an existing pattern is not matched
*/
boolean match(final String valueStr);
/**
* This method works as {#link #match(String)} but throws an exception if not matched.
*
* #param valueStr <i>optional</i> - the string to check for
* #throws ArgumentException with code
* <dl>
* <dt>PARAM_MISSED</dt>
* <dd>if <code>valueStr</code> is <code>null</code></dd>
* <dt>PARAM_BAD</dt>
* <dd>if pattern is not matched</dd>
* </dl>
*/
void matchEx(final String valueStr) throws ArgumentException;
/**
* Parses a value for this parameter from the given string. This method honors the parameters data
* type and potentially other criteria defining a valid value (e.g. a pattern).
*
* #param valueStr <i>optional</i> - the string to parse the parameter value from
* #return the parameter value according to the parameters type (see {#link #getType()}) or
* <code>null</code> in case <code>valueStr</code> was <code>null</code>.
* #throws ArgumentException in case <code>valueStr</code> is not parsable as a value for this
* parameter.
*/
Object parse(final String valueStr) throws ArgumentException;
/**
* Converts the given value to its external form as it is accepted by {#link #parse(String)}. For
* most (ordinary) parameters this is simply a call to {#link String#valueOf(Object)}. In case the
* parameter types {#link Object#toString()} method does not return the external form (e.g. for
* enumerations), this method has to be implemented accordingly.
*
* #param value <i>mandatory</i> - the parameters value
* #return the external form of the parameters value, never <code>null</code>
* #throws InternalServiceException in case the given <code>value</code> does not match
* {#link #getType()}
*/
String toString(final Object value) throws InternalServiceException;
}
The implementing ENUM base class.
public enum Parameters implements Parameter {
/**
* ANY ENUM VALUE
*/
VALUE(new ParameterImpl<String>("VALUE", String.class, "[A-Za-z]{3,10}"));
/**
* The parameter wrapped by this enum constant.
*/
private Parameter param;
/**
* Constructor.
*
* #param param <i>mandatory</i> - the value for {#link #param}
*/
private Parameters(final Parameter param) {
this.param = param;
}
/**
* {#inheritDoc}
*/
#Override
public String getName() {
return this.param.getName();
}
/**
* {#inheritDoc}
*/
#Override
public Class<?> getType() {
return this.param.getType();
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
return this.param.match(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) {
this.param.matchEx(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public Object parse(final String valueStr) throws ArgumentException {
return this.param.parse(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public String toString(final Object value) throws InternalServiceException {
return this.param.toString(value);
}
}
The subclassed ENUM which "inherits" from base class.
public enum ExtendedParameters implements Parameter {
/**
* ANY ENUM VALUE
*/
VALUE(my.package.name.VALUE);
/**
* EXTENDED ENUM VALUE
*/
EXTENDED_VALUE(new ParameterImpl<String>("EXTENDED_VALUE", String.class, "[0-9A-Za-z_.-]{1,20}"));
/**
* The parameter wrapped by this enum constant.
*/
private Parameter param;
/**
* Constructor.
*
* #param param <i>mandatory</i> - the value for {#link #param}
*/
private Parameters(final Parameter param) {
this.param = param;
}
/**
* {#inheritDoc}
*/
#Override
public String getName() {
return this.param.getName();
}
/**
* {#inheritDoc}
*/
#Override
public Class<?> getType() {
return this.param.getType();
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
return this.param.match(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) {
this.param.matchEx(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public Object parse(final String valueStr) throws ArgumentException {
return this.param.parse(valueStr);
}
/**
* {#inheritDoc}
*/
#Override
public String toString(final Object value) throws InternalServiceException {
return this.param.toString(value);
}
}
Finally the generic ParameterImpl to add some utilities.
public class ParameterImpl<T> implements Parameter {
/**
* The default pattern for numeric (integer, long) parameters.
*/
private static final Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+");
/**
* The default pattern for parameters of type boolean.
*/
private static final Pattern BOOLEAN_PATTERN = Pattern.compile("0|1|true|false");
/**
* The name of the parameter, never <code>null</code>.
*/
private final String name;
/**
* The data type of the parameter.
*/
private final Class<T> type;
/**
* The validation pattern for the parameters values. This may be <code>null</code>.
*/
private final Pattern validator;
/**
* Shortcut constructor without <code>validatorPattern</code>.
*
* #param name <i>mandatory</i> - the value for {#link #name}
* #param type <i>mandatory</i> - the value for {#link #type}
*/
public ParameterImpl(final String name, final Class<T> type) {
this(name, type, null);
}
/**
* Constructor.
*
* #param name <i>mandatory</i> - the value for {#link #name}
* #param type <i>mandatory</i> - the value for {#link #type}
* #param validatorPattern - <i>optional</i> - the pattern for {#link #validator}
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>The default validation patterns {#link #NUMBER_PATTERN} or
* {#link #BOOLEAN_PATTERN} are applied accordingly.
* </dl>
*/
public ParameterImpl(final String name, final Class<T> type, final String validatorPattern) {
this.name = name;
this.type = type;
if (null != validatorPattern) {
this.validator = Pattern.compile(validatorPattern);
} else if (Integer.class == this.type || Long.class == this.type) {
this.validator = NUMBER_PATTERN;
} else if (Boolean.class == this.type) {
this.validator = BOOLEAN_PATTERN;
} else {
this.validator = null;
}
}
/**
* {#inheritDoc}
*/
#Override
public boolean match(final String valueStr) {
if (null == valueStr) {
return false;
}
if (null != this.validator) {
final Matcher matcher = this.validator.matcher(valueStr);
return matcher.matches();
}
return true;
}
/**
* {#inheritDoc}
*/
#Override
public void matchEx(final String valueStr) throws ArgumentException {
if (false == this.match(valueStr)) {
if (null == valueStr) {
throw ArgumentException.createEx(ErrorCode.PARAM_MISSED, "The value must not be null",
this.name);
}
throw ArgumentException.createEx(ErrorCode.PARAM_BAD, "The value must match the pattern: "
+ this.validator.pattern(), this.name);
}
}
/**
* Parse the parameters value from the given string value according to {#link #type}. Additional
* the value is checked by {#link #matchEx(String)}.
*
* #param valueStr <i>optional</i> - the string value to parse the value from
* #return the parsed value, may be <code>null</code>
* #throws ArgumentException in case the parameter:
* <ul>
* <li>does not {#link #matchEx(String)} the {#link #validator}</li>
* <li>cannot be parsed according to {#link #type}</li>
* </ul>
* #throws InternalServiceException in case the type {#link #type} cannot be handled. This is a
* programming error.
*/
#Override
public T parse(final String valueStr) throws ArgumentException, InternalServiceException {
if (null == valueStr) {
return null;
}
this.matchEx(valueStr);
if (String.class == this.type) {
return this.type.cast(valueStr);
}
if (Boolean.class == this.type) {
return this.type.cast(Boolean.valueOf(("1".equals(valueStr)) || Boolean.valueOf(valueStr)));
}
try {
if (Integer.class == this.type) {
return this.type.cast(Integer.valueOf(valueStr));
}
if (Long.class == this.type) {
return this.type.cast(Long.valueOf(valueStr));
}
} catch (final NumberFormatException e) {
throw ArgumentException.createEx(ErrorCode.PARAM_BAD, "The value cannot be parsed as "
+ this.type.getSimpleName().toLowerCase() + ".", this.name);
}
return this.parseOther(valueStr);
}
/**
* Field access for {#link #name}.
*
* #return the value of {#link #name}.
*/
#Override
public String getName() {
return this.name;
}
/**
* Field access for {#link #type}.
*
* #return the value of {#link #type}.
*/
#Override
public Class<T> getType() {
return this.type;
}
/**
* {#inheritDoc}
*/
#Override
public final String toString(final Object value) throws InternalServiceException {
if (false == this.type.isAssignableFrom(value.getClass())) {
throw new InternalServiceException(ErrorCode.PANIC,
"Parameter.toString(): Bad type of value. Expected {0} but is {1}.", this.type.getName(),
value.getClass().getName());
}
if (String.class == this.type || Integer.class == this.type || Long.class == this.type) {
return String.valueOf(value);
}
if (Boolean.class == this.type) {
return Boolean.TRUE.equals(value) ? "1" : "0";
}
return this.toStringOther(value);
}
/**
* Parse parameter values of other (non standard types). This method is called by
* {#link #parse(String)} in case {#link #type} is none of the supported standard types (currently
* String, Boolean, Integer and Long). It is intended for extensions.
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>This default implementation always throws an InternalServiceException.
* </dl>
*
* #param valueStr <i>mandatory</i> - the string value to parse the value from
* #return the parsed value, may be <code>null</code>
* #throws ArgumentException in case the parameter cannot be parsed according to {#link #type}
* #throws InternalServiceException in case the type {#link #type} cannot be handled. This is a
* programming error.
*/
protected T parseOther(final String valueStr) throws ArgumentException, InternalServiceException {
throw new InternalServiceException(ErrorCode.PANIC,
"ParameterImpl.parseOther(): Unsupported parameter type: " + this.type.getName());
}
/**
* Convert the values of other (non standard types) to their external form. This method is called
* by {#link #toString(Object)} in case {#link #type} is none of the supported standard types
* (currently String, Boolean, Integer and Long). It is intended for extensions.
* <dl>
* <dt style="margin-top:0.25cm;"><i>Note:</i>
* <dd>This default implementation always throws an InternalServiceException.
* </dl>
*
* #param value <i>mandatory</i> - the parameters value
* #return the external form of the parameters value, never <code>null</code>
* #throws InternalServiceException in case the given <code>value</code> does not match
* {#link #getClass()}
*/
protected String toStringOther(final Object value) throws InternalServiceException {
throw new InternalServiceException(ErrorCode.PANIC,
"ParameterImpl.toStringOther(): Unsupported parameter type: " + this.type.getName());
}
}
My way to code that would be as follows:
// enum A { a, b, c }
static final Set<Short> enumA = new LinkedHashSet<>(Arrays.asList(new Short[]{'a','b','c'}));
// enum B extends A { d }
static final Set<Short> enumB = new LinkedHashSet<>(enumA);
static {
enumB.add((short) 'd');
// If you have to add more elements:
// enumB.addAll(Arrays.asList(new Short[]{ 'e', 'f', 'g', '♯', '♭' }));
}
LinkedHashSet provides both that each entry only exists once, and that their order is preserved. If order doesn’t matter, you can use HashSet instead. The following code is not possible in Java:
for (A a : B.values()) { // enum B extends A { d }
switch (a) {
case a:
case b:
case c:
System.out.println("Value is: " + a.toString());
break;
default:
throw new IllegalStateException("This should never happen.");
}
}
The code can be written as follows:
for (Short a : enumB) {
switch (a) {
case 'a':
case 'b':
case 'c':
System.out.println("Value is: " + new String(Character.toChars(a)));
break;
default:
throw new IllegalStateException("This should never happen.");
}
}
From Java 7 onwards you can even do the same with String:
// enum A { BACKWARDS, FOREWARDS, STANDING }
static final Set<String> enumA = new LinkedHashSet<>(Arrays.asList(new String[] {
"BACKWARDS", "FOREWARDS", "STANDING" }));
// enum B extends A { JUMP }
static final Set<String> enumB = new LinkedHashSet<>(enumA);
static {
enumB.add("JUMP");
}
Using the enum replacement:
for (String a : enumB) {
switch (a) {
case "BACKWARDS":
case "FOREWARDS":
case "STANDING":
System.out.println("Value is: " + a);
break;
default:
throw new IllegalStateException("This should never happen.");
}
}

Subclass Parse.Object in Javascript

Forgive me if this is a stupid question, I've been doing iphone and android for a while now and recently I need to develop for the web.
I'm using parse.com to handle my server requests. According to their documentation, I can do a subclass like this.
//A complex subclass of Parse.Object
var Monster = Parse.Object.extend("Monster", {
// Instance methods
hasSuperHumanStrength: function () {
return this.get("strength") > 18;
},
// Instance properties go in an initialize method
initialize: function (attrs, options) {
this.sound = "Rawr"
}
}, {
// Class methods
spawn: function(strength) {
var monster = new Monster();
monster.set("strength", strength);
return monster;
}
});
var monster = Monster.spawn(200);
alert(monster.get('strength')); // Displays 200.
alert(monster.sound); // Displays Rawr.
Ultimately I'm trying to translate the following code from Java to JS.
/**
* #author XujieSong
*
*/
#ParseClassName("_User")
public class SHUser extends ParseUser {
/**
* SHUser is a subclass of ParseUser
* Class name _User
*/
/**
* Default constructor
*/
public SHUser() {
}
/**
* Create a SHUser object with known objectId
* This method only returns a SHUser without data
* #param userID the objectId of the SHUser
* #return user a reference to a SHUser
*/
public SHUser(String userId) {
this.setObjectId(userId);
}
/**
* Create a new SHUser with attributes
* #param userName
* #param password
* #param email
* #param displayName
* #param installation
* #param profileImage
* #return user a new user
*/
public SHUser(String userName, String password, String email, String displayName) {
this.setUsername(userName);
this.setPassword(password);
this.setEmail(email);
this.setDisplayName(displayName);
}
}
And this is what I have got so far,
var SHUser = Parse.Object.extend("_User", {
/**
* Instance properties go in an initialize method
* #param {userId}
* #return {[type]}
*/
SHUser: function () {
},
/**
* Instance properties go in an initialize method
* #param {userId}
* #return {[type]}
*/
SHUser: function (userId) {
this.id = userId;
},
/**
* Instance properties go in an initialize method
* #param {userName}
* #param {password}
* #param {email}
* #param {displayName}
* #return {[type]}
*/
SHUser: function (userName, password, email, displayName) {
this.setUsername(userName);
this.setPassword(password);
this.setEmail(email);
this.setDisplayName(displayName);
}
}, {
// Class methods
});
after
var user = new SHUser(userId);
window.alert(Shelf.seller.id);
I got undefined.
So here's the question. Is it possible to have a default constructor, then a few customized constructors like the way it is in Java? Is it a good practice to do so? Thank you.
After further digging in Backbone.js, I've found the answer.
Turns out there's no need for any additional coding.
var SHUser = Parse.Object.extend("_User", {
/**
* Instance properties go in an initialize method
*/
initialize: function (attr, options) {
},
}, {
// Class methods
});
It's a backbone.js model, so when initializing, just pass the parameters in and it would work.
var seller = new SHUser({"id": sellerId});
And that's it!
For more information please refer to backbonejs.org

Why isn't this PropertyChangeListener working?

I am working on adding support for property observations for my open source library droidQuery, however the propertyChange method is not being called in my tests. What do I need to do to get this to work? Here is my code:
ViewObserver.java
package self.philbrown.droidQuery;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import android.view.View;
/**
* Provides Property Change Listening to simulate bindings
* #author Phil Brown
*
*/
public class ViewObserver implements PropertyChangeListener
{
/** The function to call when the interface's method is invoked. */
private Function function;
/**
* Constructor
* #param droidQuery an instance of droidQuery
* #param function the function to call when the value changes. Will include a {#link Observation}
* Object with information about the KVO operation.
*/
public ViewObserver(Function function)
{
this.function = function;
}
#Override
public void propertyChange(PropertyChangeEvent event) //<-- This is never reached!
{
Observation observation = new Observation(event);
function.invoke($.with((View) event.getSource()), observation);
}
/**
* Represents an observation event that occured.
*/
public static class Observation
{
/** The old value prior the this Observation */
public Object oldValue;
/** The new value */
public Object newValue;
/** The name of the property that has changed from {#code oldValue} to {#code newValue}. */
public String property;
/**
* Constructor. Private since it is only used locally.
* #param event
*/
private Observation(PropertyChangeEvent event)
{
oldValue = event.getOldValue();
newValue = event.getNewValue();
property = event.getPropertyName();
}
}
}
Relevant portions of droidQuery.java (the rest available on github):
/** Used for Property Change Listening to simulate KVO Binding in droidQuery */
private static Map<View, Map<String, WeakReference<Observer>>> observers;
//The constructor has this:
//if (observers == null)
// observers = new HashMap<View, Map<String, WeakReference<Observer>>>();
/**
* Observe changes to the given property and respond to modification events. This requires
* a getter and setter method for the given property on the selected views. Passing "*" will
* add the property observer for all of the fields in each selected view. For example:
* <pre>
* $.with(myButton).observe("selected", new Function() {
* #Override
* public void invoke($ droidQuery, Object... params) {
* Observation ob = (Observation) params[0];
* Log.i("$", ob.property + " changed to " + ob.newValue);
* }
* });
* </pre>
* #param property name of the property to observe. If set to "*", all fields will be observed.
* #param onPropertyChanged the Function to call when the given property has changed. The argument
* passed to {#code onPropertyChanged} will be an instance of {#link ViewObserver.Observation},
* and will contain the old value, new value, and the property name. The given instance of droidQuery
* will have the observing view selected.
*/
public $ observe(String property, Function onPropertyChanged)
{
for (View view : views)
{
Map<String, WeakReference<Observer>> kvo = observers.get(view);
if (kvo == null)
{
kvo = new HashMap<String, WeakReference<Observer>>();
}
WeakReference<Observer> ref = kvo.get(property);
if (ref != null && ref.get() != null)
{
if (property.equals("*"))
ref.get().support.removePropertyChangeListener(ref.get().kvo);
else
ref.get().support.removePropertyChangeListener(property, ref.get().kvo);
}
Observer observer = new Observer();
observer.support = new PropertyChangeSupport(view);
observer.kvo = new ViewObserver(onPropertyChanged);
ref = new WeakReference<Observer>(observer);
if (property.equals("*"))
observer.support.addPropertyChangeListener(observer.kvo);
else
observer.support.addPropertyChangeListener(property, observer.kvo);
kvo.put(property, ref);
observers.put(view, kvo);
}
return this;
}
/**
* Contains Objects pertaining to the property change listener for a view in droidQuery.
*/
public static class Observer
{
/** Manages property observers registered to receive events */
public PropertyChangeSupport support;
/** The property observer */
public ViewObserver kvo;
}

How to cast child class instance

I don't really know exactly how to word this but basically I need to get the child class instance of an Actor without assigning it (if that makes since?). Is this possible?
package org.game.world.entity.actor;
import java.util.HashMap;
import java.util.Map;
import org.game.world.entity.Entity;
import org.game.world.entity.actor.npc.NPC;
import org.game.world.entity.actor.player.Player;
import org.game.world.entity.actor.player.PlayerData;
public abstract class Actor extends Entity {
/**
* The type of Actor this Entity should be
* recognized as.
*/
private final ActorType actorType;
/**
* A map of ActionStates, not necessarily 'Attributes'.
*/
private final Map<ActionState, Boolean> actionState = new HashMap<ActionState, Boolean>();
/**
* Constructs a new Actor {#Entity}.
*/
public Actor(ActorType actorType) {
this.actorType = actorType;
actionState.putAll(ActionState.DEFAULT_ACTION_STATES);
}
/**
* Gets the status of a {#Actor} ActionSate.
* #param state The ActionState.
* #return The ActionState flag.
*/
public boolean getActionState(ActionState state) {
return actionState.get(state);
}
/**
* Sets a {#Actor} ActionState flag.
* #param state The ActionState.
* #param flag The flag true:false.
*/
public void setActionState(ActionState state, boolean flag) {
actionState.put(state, flag);
}
/**
* Resets all ActionState's for this Actor.
*/
public void setDefaultActionStates() {
actionState.putAll(ActionState.DEFAULT_ACTION_STATES);
}
/**
* Checks if this Actor is a specific ActorType (i.e NPC)
* #param actorType The ActorType
* #return
*/
public boolean isActorType(ActorType actorType) {
return this.actorType == actorType;
}
/**
* The type of Actor.
*/
public static enum ActorType {
PLAYER,
NPC
}
}
An Actor type.
package org.game.world.entity.actor.player;
import org.game.world.entity.Location;
import org.game.world.entity.actor.Actor;
import org.game.world.entity.actor.SkillLink;
/**
* This class represents a Player {#Actor} in the world.
*
* #author dillusion
*
*/
public class Player extends Actor {
/**
* This Player objects unique set of stored
* data.
*/
private final PlayerData playerData;
/**
* Creates a new Player object in the world.
* #param playerData The set of data unique to this Player.
*/
public Player(PlayerData playerData) {
super(ActorType.PLAYER);
this.playerData = playerData;
}
/**
* Gets the players name.
* #return The name.
*/
public String getName() {
return playerData.name;
}
/**
* Gets the players password.
* #return The password.
*/
public String getPassword() {
return playerData.password;
}
/**
* Gets the players permission level.
* #return The permission.
*/
public Permission getPermission() {
return playerData.permission;
}
/**
* Gets the players SkillLink instance.
* #return The SkillLink.
*/
public SkillLink getSkillLink() {
return playerData.skillLink;
}
#Override
public Location getLocation() {
return playerData.location;
}
#Override
public Location setLocation(Location location) {
return playerData.location = location;
}
}
But let's say I have multiple 'Actors'. I don't want to have to cast if I don't need to.
Sorry if I didn't explain this very well.
I dont know what are you questioning about here - so what i have figured out that you might want to do is to use Player as Actor right? Well that is possible by Java standard and inheritance
Actor temp=new Actor(){//implementing abstract methods if any}
Actor player=new Player(); //that is still fine as Actor is common superclas for player and actor
Player another=(Player)player; // thats just fine after typecasting
////but
another=player; // compile error, type mismatch
another=(Player)temp; // ClassCastException but no compilation error;
But still you can use different Actors and Players as Actors.

Nice way to convert AxisDatatypes from the same .xsd

I am looking for a possibility to convert two Axis Datatypes (generated by WSDL2Java) into each other. Both DataTypes consists of exactly the same Attributes because they are both from the same XSD.
The Problem is Axis generates them as Seperated Datatypes.
DataType1:
public static class AbstractAsynchronousResponse extends AbstractResponse implements org.apache.axis2.databinding.ADBBean {
/*
* This type was generated from the piece of schema that had name =
* AbstractAsynchronousResponse Namespace URI =
* http://www.example.org/AllCallbackTypes Namespace Prefix = ns2
*/
.........}
DataType2:
public static class AbstractAsynchronousResponse extends AbstractResponse implements org.apache.axis2.databinding.ADBBean {
/*
* This type was generated from the piece of schema that had name =
* AbstractAsynchronousResponse Namespace URI =
* http://www.example.org/AllCallbackTypes Namespace Prefix = ns2
*/
.........}
Now I want to do Something like this:
AbstractAsynchronousResponse1 response1 = new AbstractAsynchronousResponse1();
AbstractAsynchronousResponse2 response2 = (AbstractAsynchronousResponse2) response1;
Is there a solution?
Here is a Method I created to solve this Problem. However this isn't really nice but it works.
/**
* This will cast an {#link ADBBean} implementation to another
* {#link ADBBean}, but the Implementation will be a subClass of
* <b>parentLocationOfSourceClass</b>.<br>
* This only is possible because of the structure of all ADBBean
* implementations created by <code>Axis2 ADB-Databinding</code>. If you
* cange the Databinding you probably have to adapt this Method.
*
* #param inputADBBean
* An ADBBean Implementation created by
* <code>Axis2 ADB-Databinding</code>
* #param parentLocationOfSourceClass
* This is meant to be the <code>ClientStub</code> Class created
* by <code>Axis2 ADB-Databinding</code>. The Implementation of
* the <code>inputADBBean</code> has to be available with the
* same name in the <code>ClientStub</code>
* #return An {#link ADBBean} implementation defined as SubClass of the
* <code>ClientStub</code> Class created by
* <code>Axis2 ADB-Databinding</code>
* #throws Exception
*/
public static ADBBean castADBBean(ADBBean inputADBBean, String parentLocationOfSourceClass) throws Exception {
Class clazz = CallbackResponsePoolClient.getClassForParentLocation(inputADBBean, parentLocationOfSourceClass);
ADBBean outputADBBean = CallbackResponsePoolClient.getInstanceForADBBean(clazz);
for (Method method : outputADBBean.getClass().getMethods()) {
String methodName = method.getName();
if (methodName.startsWith("set")) {
CallbackResponsePoolClient.logger.debug("Found a setter: " + methodName);
String getterName = methodName.replaceFirst("set", "get");
Object arg = inputADBBean.getClass().getMethod(getterName).invoke(inputADBBean);
// We need to check if arg lives in the namespace:
// org.example.www.callbackresponsepoolinterface
// This will happen if we have nested Objects. E.g.
// EndpointType inside of EndpointResponse
// TODO: instanceof ADBBean could lead to problems, maybe
// sometimes we don't want to cast an ADBBean, but I can't think
// a scenario right now
if (arg instanceof ADBBean) {
arg = CallbackResponsePoolClient.castADBBean((ADBBean) arg, parentLocationOfSourceClass);
}
// We also need to handle Arrays of ADBBeans. See above
if (arg instanceof ADBBean[]) {
Class innputClass = ((ADBBean[]) arg).getClass().getComponentType();
// Better Create a new Object, because arg[0], can get you
// an Exception for an empty Array
ADBBean inputArrObj = CallbackResponsePoolClient.getInstanceForADBBean(innputClass);
Class outputArrClass = CallbackResponsePoolClient.getClassForParentLocation(inputArrObj, parentLocationOfSourceClass);
Object outputArray = Array.newInstance(outputArrClass, ((ADBBean[]) arg).length);
for (int i = 0; i < Array.getLength(arg); i++) {
Array.set(outputArray, i, CallbackResponsePoolClient.castADBBean((ADBBean) Array.get(arg, i), parentLocationOfSourceClass));
}
arg = outputArray;
}
method.invoke(outputADBBean, arg);
}
}
return outputADBBean;
}
private static Class getClassForParentLocation(ADBBean inputADBBean, String parentLocationOfSourceClass) throws ClassNotFoundException {
return Class.forName(parentLocationOfSourceClass + "$" + inputADBBean.getClass().getSimpleName());
}
private static ADBBean getInstanceForADBBean(Class clazz) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Constructor constructor = clazz.getConstructor();
return (ADBBean) constructor.newInstance();
}

Categories