duke@1: /* jjg@1359: * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.javadoc; duke@1: duke@1: import com.sun.javadoc.*; duke@1: duke@1: /** duke@1: * Documents a Serializable field defined by an ObjectStreamField. duke@1: *
duke@1:  * The class parses and stores the three serialField tag parameters:
duke@1:  *
duke@1:  * - field name
duke@1:  * - field type name
duke@1:  *      (fully-qualified or visible from the current import context)
duke@1:  * - description of the valid values for the field
duke@1: 
duke@1:  * 
duke@1: * This tag is only allowed in the javadoc for the special member duke@1: * serialPersistentFields. duke@1: * jjg@1359: *

This is NOT part of any supported API. jjg@1359: * If you write code that depends on this, you do so at your own risk. jjg@1359: * This code and its internal interfaces are subject to change or jjg@1359: * deletion without notice. jjg@1359: * duke@1: * @author Joe Fialli duke@1: * @author Neal Gafter duke@1: * duke@1: * @see java.io.ObjectStreamField duke@1: */ duke@1: class SerialFieldTagImpl duke@1: extends TagImpl duke@1: implements SerialFieldTag, Comparable duke@1: { duke@1: //### These could be final, except that the constructor duke@1: //### does not set them directly. duke@1: duke@1: private String fieldName; // Required Argument 1 of serialField duke@1: private String fieldType; // Required Argument 2 of serialField duke@1: private String description; // Optional Remaining Arguments of serialField duke@1: duke@1: private ClassDoc containingClass; // Class containing serialPersistentField member duke@1: private ClassDoc fieldTypeDoc; // ClassDocImpl of fieldType duke@1: private FieldDocImpl matchingField; // FieldDocImpl with same name as fieldName duke@1: duke@1: /* Constructor. */ duke@1: SerialFieldTagImpl(DocImpl holder, String name, String text) { duke@1: super(holder, name, text); duke@1: parseSerialFieldString(); duke@1: if (holder instanceof MemberDoc) { duke@1: containingClass = ((MemberDocImpl)holder).containingClass(); duke@1: } duke@1: } duke@1: duke@1: /* duke@1: * The serialField tag is composed of three entities. duke@1: * duke@1: * serialField serializableFieldName serisliableFieldType duke@1: * description of field. duke@1: * duke@1: * The fieldName and fieldType must be legal Java Identifiers. duke@1: */ duke@1: private void parseSerialFieldString() { duke@1: int len = text.length(); ksrini@1052: if (len == 0) { ksrini@1052: return; ksrini@1052: } duke@1: duke@1: // if no white space found duke@1: /* Skip white space. */ duke@1: int inx = 0; duke@1: int cp; duke@1: for (; inx < len; inx += Character.charCount(cp)) { duke@1: cp = text.codePointAt(inx); duke@1: if (!Character.isWhitespace(cp)) { duke@1: break; duke@1: } duke@1: } duke@1: duke@1: /* find first word. */ duke@1: int first = inx; duke@1: int last = inx; duke@1: cp = text.codePointAt(inx); duke@1: if (! Character.isJavaIdentifierStart(cp)) { duke@1: docenv().warning(holder, duke@1: "tag.serialField.illegal_character", duke@1: new String(Character.toChars(cp)), text); duke@1: return; duke@1: } duke@1: duke@1: for (inx += Character.charCount(cp); inx < len; inx += Character.charCount(cp)) { duke@1: cp = text.codePointAt(inx); duke@1: if (!Character.isJavaIdentifierPart(cp)) { duke@1: break; duke@1: } duke@1: } duke@1: duke@1: if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) { duke@1: docenv().warning(holder, duke@1: "tag.serialField.illegal_character", duke@1: new String(Character.toChars(cp)), text); duke@1: return; duke@1: } duke@1: duke@1: last = inx; duke@1: fieldName = text.substring(first, last); duke@1: duke@1: /* Skip white space. */ duke@1: for (; inx < len; inx += Character.charCount(cp)) { duke@1: cp = text.codePointAt(inx); duke@1: if (!Character.isWhitespace(cp)) { duke@1: break; duke@1: } duke@1: } duke@1: duke@1: /* find second word. */ duke@1: first = inx; duke@1: last = inx; duke@1: duke@1: for (; inx < len; inx += Character.charCount(cp)) { duke@1: cp = text.codePointAt(inx); duke@1: if (Character.isWhitespace(cp)) { duke@1: break; duke@1: } duke@1: } duke@1: if (inx < len && ! Character.isWhitespace(cp = text.codePointAt(inx))) { duke@1: docenv().warning(holder, duke@1: "tag.serialField.illegal_character", duke@1: new String(Character.toChars(cp)), text); duke@1: return; duke@1: } duke@1: last = inx; duke@1: fieldType = text.substring(first, last); duke@1: duke@1: /* Skip leading white space. Rest of string is description for serialField.*/ duke@1: for (; inx < len; inx += Character.charCount(cp)) { duke@1: cp = text.codePointAt(inx); duke@1: if (!Character.isWhitespace(cp)) { duke@1: break; duke@1: } duke@1: } duke@1: description = text.substring(inx); duke@1: } duke@1: duke@1: /** duke@1: * return a key for sorting. duke@1: */ duke@1: String key() { duke@1: return fieldName; duke@1: } duke@1: duke@1: /* duke@1: * Optional. Link this serialField tag to its corrsponding duke@1: * field in the class. Note: there is no requirement that duke@1: * there be a field in the class that matches serialField tag. duke@1: */ duke@1: void mapToFieldDocImpl(FieldDocImpl fd) { duke@1: matchingField = fd; duke@1: } duke@1: duke@1: /** duke@1: * Return the serialziable field name. duke@1: */ duke@1: public String fieldName() { duke@1: return fieldName; duke@1: } duke@1: duke@1: /** duke@1: * Return the field type string. duke@1: */ duke@1: public String fieldType() { duke@1: return fieldType; duke@1: } duke@1: duke@1: /** duke@1: * Return the ClassDocImpl for field type. duke@1: * duke@1: * @returns null if no ClassDocImpl for field type is visible from duke@1: * containingClass context. duke@1: */ duke@1: public ClassDoc fieldTypeDoc() { duke@1: if (fieldTypeDoc == null && containingClass != null) { duke@1: fieldTypeDoc = containingClass.findClass(fieldType); duke@1: } duke@1: return fieldTypeDoc; duke@1: } duke@1: duke@1: /** duke@1: * Return the corresponding FieldDocImpl for this SerialFieldTagImpl. duke@1: * duke@1: * @returns null if no matching FieldDocImpl. duke@1: */ duke@1: FieldDocImpl getMatchingField() { duke@1: return matchingField; duke@1: } duke@1: duke@1: /** duke@1: * Return the field comment. If there is no serialField comment, return duke@1: * javadoc comment of corresponding FieldDocImpl. duke@1: */ duke@1: public String description() { duke@1: if (description.length() == 0 && matchingField != null) { duke@1: duke@1: //check for javadoc comment of corresponding field. duke@1: Comment comment = matchingField.comment(); duke@1: if (comment != null) { duke@1: return comment.commentText(); duke@1: } duke@1: } duke@1: return description; duke@1: } duke@1: duke@1: /** duke@1: * Return the kind of this tag. duke@1: */ duke@1: public String kind() { duke@1: return "@serialField"; duke@1: } duke@1: duke@1: /** duke@1: * Convert this object to a string. duke@1: */ duke@1: public String toString() { duke@1: return name + ":" + text; duke@1: } duke@1: duke@1: /** duke@1: * Compares this Object with the specified Object for order. Returns a duke@1: * negative integer, zero, or a positive integer as this Object is less duke@1: * than, equal to, or greater than the given Object. duke@1: *

duke@1: * Included to make SerialFieldTagImpl items java.lang.Comparable. duke@1: * duke@1: * @param obj the Object to be compared. duke@1: * @return a negative integer, zero, or a positive integer as this Object duke@1: * is less than, equal to, or greater than the given Object. duke@1: * @exception ClassCastException the specified Object's type prevents it duke@1: * from being compared to this Object. duke@1: * @since 1.2 duke@1: */ duke@1: public int compareTo(Object obj) { duke@1: return key().compareTo(((SerialFieldTagImpl)obj).key()); duke@1: } duke@1: }