001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2001-2003 © Softaris Pty.Ltd. All Rights Reserved.
015: package metalib.core;
016:
017: import java.io.PrintWriter;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import com.metaboss.util.StringUtils;
021: import com.metaboss.javatemplate.*;
022:
023: /** The basic enumerated value datatype. */
024: public final class EntityStateField implements JavaTemplate {
025: // This comment is inserted in javadoc when description of the object is miissing from the model
026: private static final String sMissingDescriptionComment = "<font color=\"red\">Description is missing in the model</font>";
027:
028: private final class StateTransitionVariables {
029: public String DestinationStateName = "";
030: public String Description = "";
031: };
032:
033: private class StateVariables {
034: public String StateName = "";
035: public String VariableName = "";
036: public String Description = "";
037: public boolean IsInitial = false;
038: public boolean IsFinal = false;
039: public HashMap StateTransitions = new HashMap();
040: };
041:
042: /* This method is called to perform the template merge with the values supplied in context */
043: public void mergeTemplate(PrintWriter pOutputWriter,
044: JavaTemplateContext pContext) throws JavaTemplateException {
045: String lDatatypeName = pContext
046: .getMandatoryString("DatatypeName");
047: String lDatatypeDescription = pContext.getString(
048: "DatatypeDescription", null);
049: if (lDatatypeDescription == null
050: || lDatatypeDescription.length() == 0)
051: lDatatypeDescription = sMissingDescriptionComment;
052:
053: String lEmptyString = pContext.getString(
054: "TemplateProperties.EmptyString", "");
055: String lConcealedString = pContext.getString(
056: "TemplateProperties.ConcealedString", "xxxxxx");
057: int lMaxValueLength = 1;
058: // Build map of states
059: StateVariables lInitialState = null;
060: HashMap lStateVariables = new HashMap();
061: {
062: for (int i = 1;; i++) {
063: String lStateName = pContext.getString(
064: "TemplateProperties.State[" + i + "].Name",
065: null);
066: if (lStateName == null)
067: break; //no more states
068: if (lStateVariables.containsKey(lStateName))
069: throw new JavaTemplateException(
070: "Can not generate the " + lDatatypeName
071: + " datatype because State '"
072: + lStateName
073: + "' is defined at least twice.");
074: StateVariables lVariables = new StateVariables();
075: lVariables.StateName = lStateName;
076: lVariables.VariableName = StringUtils.replace(
077: lStateName, " ", "_").toUpperCase();
078: lVariables.Description = pContext.getString(
079: "TemplateProperties.State[" + i
080: + "].Description", null);
081: if (lVariables.Description == null
082: || lVariables.Description.length() == 0)
083: lVariables.Description = sMissingDescriptionComment;
084: String lType = pContext.getString(
085: "TemplateProperties.State[" + i + "].Type",
086: "NORMAL");
087: if (lType.equalsIgnoreCase("FINAL")) {
088: lVariables.IsFinal = true;
089: } else {
090: if (lType.equalsIgnoreCase("INITIAL")) {
091: if (lInitialState != null)
092: throw new JavaTemplateException(
093: "Can not generate the "
094: + lDatatypeName
095: + " datatype because there are at least two INITIAL states defined.");
096: lVariables.IsInitial = true;
097: lInitialState = lVariables;
098: }
099: // Not final states may have transitions
100: for (int j = 1;; j++) {
101: String lDestinationStateName = pContext
102: .getString("TemplateProperties.State["
103: + i + "].Transition[" + j
104: + "].DestinationStateName",
105: null);
106: if (lDestinationStateName == null)
107: break; //no more transitions
108: if (lVariables.StateTransitions
109: .containsKey(lDestinationStateName))
110: throw new JavaTemplateException(
111: "Can not generate the "
112: + lDatatypeName
113: + " datatype because State with name '"
114: + lStateName
115: + "' has duplicate transitions going to the same destination state '"
116: + lDestinationStateName
117: + "'");
118: StateTransitionVariables lTransitionVariables = new StateTransitionVariables();
119: lTransitionVariables.DestinationStateName = lDestinationStateName;
120: lTransitionVariables.Description = pContext
121: .getString("TemplateProperties.State["
122: + i + "].Transition[" + j
123: + "].Description", null);
124: if (lTransitionVariables.Description == null
125: || lTransitionVariables.Description
126: .length() == 0)
127: lTransitionVariables.Description = sMissingDescriptionComment;
128:
129: lVariables.StateTransitions.put(
130: lDestinationStateName,
131: lTransitionVariables);
132: }
133: }
134: // Keep the state in the map
135: lStateVariables.put(lStateName, lVariables);
136: // Accumulate maximum value length
137: int lValueLength = lStateName.length();
138: if (lValueLength > lMaxValueLength)
139: lMaxValueLength = lValueLength;
140: }
141: // Make sure that we have got initial state
142: if (lInitialState == null)
143: throw new JavaTemplateException(
144: "Can not generate the "
145: + lDatatypeName
146: + " datatype because initial state (Type = 'INITIAL') is not defined.");
147: }
148: pOutputWriter.println("import java.io.Serializable;");
149: pOutputWriter
150: .println("import com.metaboss.enterprise.datatypes.DataType;");
151: pOutputWriter
152: .println("import com.metaboss.enterprise.datatypes.DataTypeTranslationMetadata;");
153: pOutputWriter
154: .println("import com.metaboss.enterprise.datatypes.DataTypeValidationException;");
155: pOutputWriter
156: .println("import com.metaboss.enterprise.datatypes.DataTypeRuntimeException;");
157: pOutputWriter
158: .println("import com.metaboss.enterprise.datatypes.DefaultDataTypeTranslationMetadataImplementation;");
159: pOutputWriter
160: .println("import com.metaboss.enterprise.datatypes.DataTypeInstanceCreationFailureException;");
161: pOutputWriter
162: .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForEmptyInstanceException;");
163: pOutputWriter
164: .println("import com.metaboss.enterprise.datatypes.DataTypeInvalidOperationForConcealedInstanceException;");
165: pOutputWriter
166: .println("import com.metaboss.enterprise.datatypes.sqltranslation.SqlVarcharTranslator;");
167: pOutputWriter
168: .println("import com.metaboss.enterprise.datatypes.primitivetranslation.PrimitiveStringTranslator;");
169: pOutputWriter
170: .println("import com.metaboss.enterprise.datatypes.xmltranslation.XmlTextTranslator;");
171:
172: pOutputWriter.println("/** " + lDatatypeDescription);
173: pOutputWriter
174: .println(" * <p>This datatype is an 'enumerable type', which means that it has a limited set of valid constant values.");
175: pOutputWriter
176: .println(" * Each valid value is represented by public member constant, which must be used as concrete instance of this type.");
177: pOutputWriter
178: .println(" * In addition to usual enumerable type features this datatype has a number of special methods supporting state transitions.</p>");
179: pOutputWriter.println(" * <p><b>Valid states are:</b>");
180: pOutputWriter.println(" * <table border=\"1\">");
181: pOutputWriter
182: .println(" * <tr><th>State</th><th>Member Variable</th><th>State Description</th></tr>");
183: // Write out table rows
184: {
185: Iterator lStatesIterator = lStateVariables.values()
186: .iterator();
187: while (lStatesIterator.hasNext()) {
188: StateVariables lVariables = (StateVariables) lStatesIterator
189: .next();
190: pOutputWriter.println(" * <tr><td>"
191: + lVariables.StateName + "</td><td><a href=\"#"
192: + lVariables.VariableName + "\">"
193: + lVariables.VariableName + "</a></td><td>"
194: + lVariables.Description + "</td></tr>");
195: }
196: }
197: pOutputWriter.println(" * </table></p>");
198: pOutputWriter.println(" */");
199: pOutputWriter.println("public final class " + lDatatypeName
200: + " implements DataType, Serializable");
201: pOutputWriter.println("{");
202: pOutputWriter
203: .println(" // Static storage for metadata. Create once and return many times");
204: pOutputWriter
205: .println(" private static DataTypeTranslationMetadata sTranslationMetadata;");
206: pOutputWriter
207: .println(" // Static storage for the empty string constant.");
208: pOutputWriter
209: .println(" private static final String sEmptyString = \""
210: + lEmptyString + "\";");
211: pOutputWriter
212: .println(" // Static storage for the concealed string constant.");
213: pOutputWriter
214: .println(" private static final String sConcealedString = \""
215: + lConcealedString + "\";");
216: pOutputWriter
217: .println(" // Static storage for all valid string constants except empty and concealed");
218: pOutputWriter
219: .print(" private static final String[] sAllStrings = new String[] {");
220: // Write out public final values
221: {
222: Iterator lStatesIterator = lStateVariables.values()
223: .iterator();
224: while (lStatesIterator.hasNext()) {
225: StateVariables lVariables = (StateVariables) lStatesIterator
226: .next();
227: pOutputWriter.print("\"" + lVariables.StateName + "\"");
228: if (lStatesIterator.hasNext())
229: pOutputWriter.print(", ");
230: else
231: pOutputWriter.println("};");
232: }
233: }
234: pOutputWriter
235: .println(" // State of the object is stored here : 0 - normal, 1 - empty, 2 - concealed");
236: pOutputWriter.println(" private byte mState = 0;");
237: pOutputWriter.println(" // Actual value stored here");
238: pOutputWriter.println(" private String mValue;");
239: pOutputWriter
240: .println(" // States this state can transition to stored here");
241: pOutputWriter.println(" private String [] mTransitions;");
242: pOutputWriter
243: .println(" // Special constant representing empty instance");
244: pOutputWriter.println(" private static final "
245: + lDatatypeName + " sEmptyInstance = new "
246: + lDatatypeName + "((byte)1, sEmptyString, null);");
247: pOutputWriter
248: .println(" // Special constant representing concealed instance");
249: pOutputWriter.println(" private static final "
250: + lDatatypeName + " sConcealedInstance = new "
251: + lDatatypeName + "((byte)2, sConcealedString, null);");
252: // Write out public final values
253: {
254: Iterator lStatesIterator = lStateVariables.values()
255: .iterator();
256: while (lStatesIterator.hasNext()) {
257: StateVariables lVariables = (StateVariables) lStatesIterator
258: .next();
259: pOutputWriter
260: .println(" /** This constant represents one of the possible states */");
261: if (lVariables.StateTransitions.size() == 0)
262: pOutputWriter.println(" public static final "
263: + lDatatypeName + " "
264: + lVariables.VariableName + " = new "
265: + lDatatypeName + "((byte)0,\""
266: + lVariables.StateName + "\", null);");
267: else {
268: pOutputWriter.print(" public static final "
269: + lDatatypeName + " "
270: + lVariables.VariableName + " = new "
271: + lDatatypeName + "((byte)0,\""
272: + lVariables.StateName
273: + "\", new String[] { ");
274: Iterator lTransitionsIterator = lVariables.StateTransitions
275: .values().iterator();
276: while (lTransitionsIterator.hasNext()) {
277: StateTransitionVariables lTransitionVariables = (StateTransitionVariables) lTransitionsIterator
278: .next();
279: StateVariables lDestinationStateVariables = (StateVariables) lStateVariables
280: .get(lTransitionVariables.DestinationStateName);
281: if (lDestinationStateVariables == null)
282: throw new JavaTemplateException(
283: "Can not generate the "
284: + lDatatypeName
285: + " datatype because State with name '"
286: + lVariables.StateName
287: + "' has transitions going to the unknown destination state '"
288: + lTransitionVariables.DestinationStateName
289: + "'");
290: pOutputWriter.print("\"");
291: pOutputWriter
292: .print(lDestinationStateVariables.StateName);
293: pOutputWriter.print("\"");
294: if (lTransitionsIterator.hasNext())
295: pOutputWriter.print(", ");
296: }
297: pOutputWriter.println("});");
298: }
299: }
300: }
301: pOutputWriter.println(" static");
302: pOutputWriter.println(" {");
303: pOutputWriter
304: .println(" SqlVarcharTranslator lSqlTranslator = new SqlVarcharTranslator()");
305: pOutputWriter.println(" {");
306: pOutputWriter
307: .println(" public String getSqlValue(DataType pDataTypeInstance) throws ClassCastException, DataTypeInvalidOperationForEmptyInstanceException, DataTypeInvalidOperationForConcealedInstanceException");
308: pOutputWriter.println(" {");
309: pOutputWriter.println(" " + lDatatypeName
310: + " lInstance = (" + lDatatypeName
311: + ")pDataTypeInstance;");
312: pOutputWriter
313: .println(" if (lInstance.isConcealed())");
314: pOutputWriter
315: .println(" throw new DataTypeInvalidOperationForConcealedInstanceException();");
316: pOutputWriter
317: .println(" if (lInstance.isEmpty())");
318: pOutputWriter
319: .println(" throw new DataTypeInvalidOperationForEmptyInstanceException();");
320: pOutputWriter
321: .println(" return lInstance.mValue;");
322: pOutputWriter.println(" }");
323: pOutputWriter
324: .println(" public DataType createFromSqlValue(String pSqlValue) throws DataTypeInstanceCreationFailureException");
325: pOutputWriter.println(" {");
326: pOutputWriter.println(" if (pSqlValue == null)");
327: pOutputWriter
328: .println(" throw new DataTypeInstanceCreationFailureException(\"Supplied Sql value is null.\");");
329: {
330: Iterator lStatesIterator = lStateVariables.values()
331: .iterator();
332: while (lStatesIterator.hasNext()) {
333: StateVariables lVariables = (StateVariables) lStatesIterator
334: .next();
335: pOutputWriter
336: .println(" if (pSqlValue.equals("
337: + lVariables.VariableName + ".mValue))");
338: pOutputWriter.println(" return "
339: + lVariables.VariableName + ";");
340: }
341: }
342: pOutputWriter
343: .println(" throw new DataTypeInstanceCreationFailureException(\"'\" + pSqlValue + \"' is not a legal value for "
344: + lDatatypeName + ".\");");
345: pOutputWriter.println(" }");
346: pOutputWriter.println(" };");
347: pOutputWriter
348: .println(" PrimitiveStringTranslator lPrimitiveTranslator = new PrimitiveStringTranslator()");
349: pOutputWriter.println(" {");
350: pOutputWriter
351: .println(" public String getPrimitiveValue(DataType pDataTypeInstance) throws ClassCastException, DataTypeInvalidOperationForEmptyInstanceException, DataTypeInvalidOperationForConcealedInstanceException");
352: pOutputWriter.println(" {");
353: pOutputWriter.println(" " + lDatatypeName
354: + " lInstance = (" + lDatatypeName
355: + ")pDataTypeInstance;");
356: pOutputWriter
357: .println(" if (lInstance.isConcealed())");
358: pOutputWriter
359: .println(" throw new DataTypeInvalidOperationForConcealedInstanceException();");
360: pOutputWriter
361: .println(" if (lInstance.isEmpty())");
362: pOutputWriter
363: .println(" throw new DataTypeInvalidOperationForEmptyInstanceException();");
364: pOutputWriter
365: .println(" return lInstance.mValue;");
366: pOutputWriter.println(" }");
367: pOutputWriter
368: .println(" public DataType createFromPrimitiveValue(String pPrimitiveValue) throws DataTypeInstanceCreationFailureException");
369: pOutputWriter.println(" {");
370: pOutputWriter
371: .println(" if (pPrimitiveValue == null)");
372: pOutputWriter
373: .println(" throw new DataTypeInstanceCreationFailureException(\"Supplied Primitive value is null.\");");
374: {
375: Iterator lStatesIterator = lStateVariables.values()
376: .iterator();
377: while (lStatesIterator.hasNext()) {
378: StateVariables lVariables = (StateVariables) lStatesIterator
379: .next();
380: pOutputWriter
381: .println(" if (pPrimitiveValue.equals("
382: + lVariables.VariableName + ".mValue))");
383: pOutputWriter.println(" return "
384: + lVariables.VariableName + ";");
385: }
386: }
387: pOutputWriter
388: .println(" throw new DataTypeInstanceCreationFailureException(\"'\" + pPrimitiveValue + \"' is not a legal value for "
389: + lDatatypeName + ".\");");
390: pOutputWriter.println(" }");
391: pOutputWriter.println(" };");
392: pOutputWriter
393: .println(" XmlTextTranslator lXmlTranslator = new XmlTextTranslator()");
394: pOutputWriter.println(" {");
395: pOutputWriter
396: .println(" public String getXmlValue(DataType pDataTypeInstance) throws ClassCastException, DataTypeInvalidOperationForEmptyInstanceException, DataTypeInvalidOperationForConcealedInstanceException");
397: pOutputWriter.println(" {");
398: pOutputWriter.println(" " + lDatatypeName
399: + " lInstance = (" + lDatatypeName
400: + ")pDataTypeInstance;");
401: pOutputWriter
402: .println(" if (lInstance.isConcealed())");
403: pOutputWriter
404: .println(" throw new DataTypeInvalidOperationForConcealedInstanceException();");
405: pOutputWriter
406: .println(" if (lInstance.isEmpty())");
407: pOutputWriter
408: .println(" throw new DataTypeInvalidOperationForEmptyInstanceException();");
409: pOutputWriter
410: .println(" return lInstance.mValue;");
411: pOutputWriter.println(" }");
412: pOutputWriter
413: .println(" public DataType createFromXmlValue(String pXmlValue) throws DataTypeInstanceCreationFailureException");
414: pOutputWriter.println(" {");
415: pOutputWriter.println(" if (pXmlValue == null)");
416: pOutputWriter
417: .println(" throw new DataTypeInstanceCreationFailureException(\"Supplied Xml value is null.\");");
418: {
419: Iterator lStatesIterator = lStateVariables.values()
420: .iterator();
421: while (lStatesIterator.hasNext()) {
422: StateVariables lVariables = (StateVariables) lStatesIterator
423: .next();
424: pOutputWriter
425: .println(" if (pXmlValue.equals("
426: + lVariables.VariableName + ".mValue))");
427: pOutputWriter.println(" return "
428: + lVariables.VariableName + ";");
429: }
430: }
431: pOutputWriter
432: .println(" throw new DataTypeInstanceCreationFailureException(\"'\" + pXmlValue + \"' is not a legal value for "
433: + lDatatypeName + ".\");");
434: pOutputWriter.println(" }");
435: pOutputWriter.println(" };");
436: pOutputWriter
437: .println(" java.util.Properties lProperties = new java.util.Properties();");
438: pOutputWriter
439: .println(" lProperties.setProperty(\"maxsize\",\""
440: + lMaxValueLength + "\");");
441: pOutputWriter
442: .println(" sTranslationMetadata = new DefaultDataTypeTranslationMetadataImplementation(DataTypeTranslationMetadata.SQL_VARCHAR, lProperties, lSqlTranslator, DataTypeTranslationMetadata.PRIMITIVE_STRING, null, lPrimitiveTranslator, DataTypeTranslationMetadata.XML_TEXT, null, lXmlTranslator);");
443: pOutputWriter.println(" }");
444:
445: pOutputWriter
446: .println(" /** Returns this datatype's metadata.");
447: pOutputWriter
448: .println(" * See {@link com.metaboss.enterprise.datatypes.DataType DataType} for more details */");
449: pOutputWriter
450: .println(" public static DataTypeTranslationMetadata getTranslationMetadata()");
451: pOutputWriter.println(" {");
452: pOutputWriter.println(" return sTranslationMetadata;");
453: pOutputWriter.println(" }");
454:
455: pOutputWriter
456: .println(" /** Returns string used to represent empty value in a toString() / createFromString() methods */");
457: pOutputWriter
458: .println(" public static String getEmptyString()");
459: pOutputWriter.println(" {");
460: pOutputWriter.println(" return sEmptyString;");
461: pOutputWriter.println(" }");
462:
463: pOutputWriter
464: .println(" /** Returns string used to represent concealed value in a toString() / createFromString() methods */");
465: pOutputWriter
466: .println(" public static String getConcealedString()");
467: pOutputWriter.println(" {");
468: pOutputWriter.println(" return sConcealedString;");
469: pOutputWriter.println(" }");
470:
471: pOutputWriter
472: .println(" /** Returns array of all valid value strings in a toString() / createFromString() methods, except empty and concealed. */");
473: pOutputWriter
474: .println(" public static String[] getAllStrings()");
475: pOutputWriter.println(" {");
476: pOutputWriter.println(" return sAllStrings;");
477: pOutputWriter.println(" }");
478:
479: pOutputWriter
480: .println(" /** Creates an instance of the datatype carrying an empty value */");
481: pOutputWriter.println(" public static " + lDatatypeName
482: + " createEmpty()");
483: pOutputWriter.println(" {");
484: pOutputWriter.println(" return sEmptyInstance;");
485: pOutputWriter.println(" }");
486:
487: pOutputWriter
488: .println(" /** Creates an instance of the datatype carrying concealed value */");
489: pOutputWriter.println(" public static " + lDatatypeName
490: + " createConcealed()");
491: pOutputWriter.println(" {");
492: pOutputWriter.println(" return sConcealedInstance;");
493: pOutputWriter.println(" }");
494:
495: pOutputWriter
496: .println(" /** Creates an instance of the datatype carrying initial state value */");
497: pOutputWriter.println(" public static " + lDatatypeName
498: + " createInitial()");
499: pOutputWriter.println(" {");
500: pOutputWriter.println(" return "
501: + lInitialState.VariableName + ";");
502: pOutputWriter.println(" }");
503:
504: pOutputWriter
505: .println(" /** Checks if this state can be transitioned to proposed state.");
506: pOutputWriter
507: .println(" * @param pProposedState the state caller wants to check");
508: pOutputWriter
509: .println(" * @return true if proposed state can be reached from this state in one transition");
510: pOutputWriter
511: .println(" * false if transition is illegal or either instance is empty or concealed */");
512: pOutputWriter.println(" public boolean canTransition( "
513: + lDatatypeName + " pProposedState)");
514: pOutputWriter.println(" {");
515: pOutputWriter.println(" if (pProposedState == null)");
516: pOutputWriter.println(" return false;");
517: pOutputWriter.println(" if (((" + lDatatypeName
518: + ")pProposedState).isConcealed() || isConcealed())");
519: pOutputWriter
520: .println(" return false; // One of the instances is concealed");
521: pOutputWriter.println(" if (((" + lDatatypeName
522: + ")pProposedState).isEmpty() || isEmpty())");
523: pOutputWriter
524: .println(" return false; // One of the instance is empty.");
525: pOutputWriter
526: .println(" if (mTransitions == null || mTransitions.length == 0)");
527: pOutputWriter
528: .println(" return false; // No valid transitions from this state.");
529: pOutputWriter
530: .println(" for (int i = 0; i < mTransitions.length; i++)");
531: pOutputWriter.println(" {");
532: pOutputWriter
533: .println(" if (mTransitions[i].equals(pProposedState.mValue))");
534: pOutputWriter
535: .println(" return true; // Found match.");
536: pOutputWriter.println(" }");
537: pOutputWriter
538: .println(" return false; // No match on valid transitions.");
539: pOutputWriter.println(" }");
540:
541: pOutputWriter
542: .println(" /** Returns array of strings populated with Strings corresponding to transitions valid from this one.");
543: pOutputWriter
544: .println(" * This array might for example be used to populate choices in the gui state editing field.");
545: pOutputWriter
546: .println(" * @return Array of strings or zero-length array if there are no valid transitions from contained state */");
547: pOutputWriter
548: .println(" public String[] getValidTransitionStrings()");
549: pOutputWriter.println(" {");
550: pOutputWriter
551: .println(" if (isEmpty() || isConcealed() || mTransitions == null || mTransitions.length == 0)");
552: pOutputWriter
553: .println(" return new String[0]; // No known valid transitions");
554: pOutputWriter
555: .println(" return mTransitions; // mTransitions has all valid strings");
556: pOutputWriter.println(" }");
557:
558: pOutputWriter
559: .println(" /** Returns array of states which can be transitioned to from this one.");
560: pOutputWriter
561: .println(" * @return Array of states or zero-length array if there are no valid transitions from contained state */");
562: pOutputWriter.println(" public " + lDatatypeName
563: + "[] getValidTransitionStates()");
564: pOutputWriter.println(" {");
565: pOutputWriter
566: .println(" if (isEmpty() || isConcealed() || mTransitions == null || mTransitions.length == 0)");
567: pOutputWriter.println(" return new " + lDatatypeName
568: + "[0]; // No known valid transitions");
569: pOutputWriter.println(" " + lDatatypeName
570: + "[] lReturn = new " + lDatatypeName
571: + "[mTransitions.length];");
572: pOutputWriter
573: .println(" for (int i = 0; i < mTransitions.length; i++)");
574: pOutputWriter.println(" {");
575: pOutputWriter
576: .println(" String lValidTransitionName = mTransitions[i];");
577: {
578: Iterator lStatesIterator = lStateVariables.values()
579: .iterator();
580: while (lStatesIterator.hasNext()) {
581: StateVariables lVariables = (StateVariables) lStatesIterator
582: .next();
583: pOutputWriter
584: .println(" if (lValidTransitionName.equals("
585: + lVariables.VariableName + ".mValue))");
586: pOutputWriter.println(" lReturn[i] = "
587: + lVariables.VariableName + ";");
588: pOutputWriter.println(" else");
589: }
590: pOutputWriter
591: .println(" throw new DataTypeRuntimeException(\"Unexpected program condition. mTransitions is initialised with unknown string.\");");
592: }
593: pOutputWriter.println(" }");
594: pOutputWriter
595: .println(" return lReturn; // mTransitions has all valid strings");
596: pOutputWriter.println(" }");
597:
598: pOutputWriter
599: .println(" /** Creates an instance of the datatype from given readable value */");
600: pOutputWriter
601: .println(" public static "
602: + lDatatypeName
603: + " createFromString( String pSourceString) throws DataTypeValidationException");
604: pOutputWriter.println(" {");
605: pOutputWriter
606: .println(" // No need to specially validate - we will either return appropriate constant or throw exception at the end");
607: pOutputWriter.println(" // Create instance");
608: pOutputWriter
609: .println(" if (pSourceString.equals(sEmptyString))");
610: pOutputWriter.println(" return sEmptyInstance;");
611: pOutputWriter
612: .println(" if (pSourceString.equals(sConcealedString))");
613: pOutputWriter.println(" return sConcealedInstance;");
614: {
615: Iterator lStatesIterator = lStateVariables.values()
616: .iterator();
617: while (lStatesIterator.hasNext()) {
618: StateVariables lVariables = (StateVariables) lStatesIterator
619: .next();
620: pOutputWriter
621: .println(" if (pSourceString.equals("
622: + lVariables.VariableName + ".mValue))");
623: pOutputWriter.println(" return "
624: + lVariables.VariableName + ";");
625: }
626: }
627: pOutputWriter
628: .println(" throw new DataTypeValidationException(\"'\" + pSourceString + \"' is not a legal value for "
629: + lDatatypeName + ".\");");
630: pOutputWriter.println(" }");
631:
632: pOutputWriter
633: .println(" /** Validates proposed readable value */");
634: pOutputWriter
635: .println(" public static void validateString( String pProposedString) throws DataTypeValidationException");
636: pOutputWriter.println(" {");
637: pOutputWriter.println(" if (pProposedString == null)");
638: pOutputWriter
639: .println(" throw new DataTypeValidationException(\"Null initialisation string is not allowed for "
640: + lDatatypeName
641: + ". Use createEmpty() method to create an empty "
642: + lDatatypeName + "\");");
643: pOutputWriter
644: .println(" if (pProposedString.equals(sEmptyString))");
645: pOutputWriter.println(" return; // Done validation");
646: pOutputWriter
647: .println(" if (pProposedString.equals(sConcealedString))");
648: pOutputWriter
649: .println(" return; // Done validation");
650: {
651: Iterator lStatesIterator = lStateVariables.values()
652: .iterator();
653: while (lStatesIterator.hasNext()) {
654: StateVariables lVariables = (StateVariables) lStatesIterator
655: .next();
656: pOutputWriter
657: .println(" if (pProposedString.equals("
658: + lVariables.VariableName + ".mValue))");
659: pOutputWriter
660: .println(" return; // Done validation");
661: }
662: }
663: pOutputWriter
664: .println(" throw new DataTypeValidationException(\"'\" + pProposedString + \"' is not a legal value for "
665: + lDatatypeName + ".\");");
666: pOutputWriter.println(" }");
667:
668: pOutputWriter
669: .println(" /** Returns the value inside this instance of "
670: + lDatatypeName + " as readable string */");
671: pOutputWriter.println(" public String toString()");
672: pOutputWriter.println(" {");
673: pOutputWriter.println(" if (isEmpty())");
674: pOutputWriter.println(" return sEmptyString;");
675: pOutputWriter.println(" if (isConcealed())");
676: pOutputWriter.println(" return sConcealedString;");
677: pOutputWriter.println(" return mValue;");
678: pOutputWriter.println(" }");
679:
680: pOutputWriter
681: .println(" /** Indicates whether some other object is \"equal to\" this one");
682: pOutputWriter
683: .println(" * @return true if this object is the same as the obj argument; false otherwise. */");
684: pOutputWriter
685: .println(" public boolean equals(Object pOtherObject)");
686: pOutputWriter.println(" {");
687: pOutputWriter.println(" if (pOtherObject == null)");
688: pOutputWriter.println(" return false;");
689: pOutputWriter.println(" if ((pOtherObject instanceof "
690: + lDatatypeName + ") == false)");
691: pOutputWriter.println(" return false;");
692: pOutputWriter.println(" if (((" + lDatatypeName
693: + ")pOtherObject).isConcealed() || isConcealed())");
694: pOutputWriter
695: .println(" return false; // One of the instances is concealed");
696: pOutputWriter.println(" if (((" + lDatatypeName
697: + ")pOtherObject).isEmpty() && isEmpty())");
698: pOutputWriter
699: .println(" return true; // Both instances are empty.");
700: pOutputWriter.println(" if (((" + lDatatypeName
701: + ")pOtherObject).isEmpty() != isEmpty())");
702: pOutputWriter
703: .println(" return false; // One of the instances is empty, the other one is not");
704: pOutputWriter.println(" return ((" + lDatatypeName
705: + ")pOtherObject).mValue.equals(mValue);");
706: pOutputWriter.println(" }");
707:
708: pOutputWriter
709: .println(" /** Returns a hash code value for the object. This method is supported for the benefit of hashtables");
710: pOutputWriter
711: .println(" * @return instance's hash code or zero if this instance is empty or concealed */");
712: pOutputWriter.println(" public int hashCode()");
713: pOutputWriter.println(" {");
714: pOutputWriter
715: .println(" if (isEmpty() || isConcealed())");
716: pOutputWriter.println(" return 0;");
717: pOutputWriter.println(" return mValue.hashCode();");
718: pOutputWriter.println(" }");
719:
720: pOutputWriter
721: .println(" /** Returns true if the instance contains an empty value */");
722: pOutputWriter.println(" public boolean isEmpty()");
723: pOutputWriter.println(" {");
724: pOutputWriter.println(" return mState == 1;");
725: pOutputWriter.println(" }");
726:
727: pOutputWriter
728: .println(" /** Returns true if the instance contains concealed value */");
729: pOutputWriter.println(" public boolean isConcealed()");
730: pOutputWriter.println(" {");
731: pOutputWriter.println(" return mState == 2;");
732: pOutputWriter.println(" }");
733:
734: pOutputWriter
735: .println(" /** Returns true if the instance contains the initial state */");
736: pOutputWriter.println(" public boolean isInitial()");
737: pOutputWriter.println(" {");
738: pOutputWriter.println(" return equals("
739: + lInitialState.VariableName + ");");
740: pOutputWriter.println(" }");
741:
742: pOutputWriter
743: .println(" // Private access. External callers must use one of the static creators");
744: pOutputWriter
745: .println(" // Note that pState has nothing to do with the state of the entity this data type represents");
746: pOutputWriter
747: .println(" // it is used to keep internal state of the data type object - empty, concealed etc");
748: pOutputWriter
749: .println(" private "
750: + lDatatypeName
751: + "( byte pState, String pValue, String[] pTransitions)");
752: pOutputWriter.println(" {");
753: pOutputWriter.println(" mState = pState;");
754: pOutputWriter.println(" mValue = pValue;");
755: pOutputWriter.println(" mTransitions = pTransitions;");
756: pOutputWriter.println(" }");
757: pOutputWriter.println("}");
758: }
759: }
|