Java tutorial
/* * Copyright (C) 2012 NS Solutions Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.htmlhifive.tools.rhino.comment.js; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import com.htmlhifive.tools.rhino.Constants; import com.htmlhifive.tools.rhino.comment.RelationNodeType; import com.htmlhifive.tools.rhino.comment.TagType; import com.htmlhifive.tools.rhino.comment.Token; import com.htmlhifive.tools.rhino.comment.TokenType; import com.htmlhifive.tools.rhino.comment.TokenUtil; public class JSDocCommentNodeParser { private RelationNodeType docType; private List<Token> tokenList; public JSDocCommentNodeParser(RelationNodeType docType) { this.docType = docType; tokenList = new ArrayList<Token>(); } public JSDocRoot parse(String comment) { StringTokenizer lineSeparator = new StringTokenizer(comment, "\n\r"); int currentLineNum = 0; int currentIndexNum = 0; tokenList = new ArrayList<Token>(); while (lineSeparator.hasMoreTokens()) { // ? String lineStr = lineSeparator.nextToken(); // ? StringTokenizer tokenSeparator = new StringTokenizer(lineStr); while (tokenSeparator.hasMoreTokens()) { // token? String tokenStr = tokenSeparator.nextToken(); Token token = new Token(TokenUtil.resolveType(tokenStr), tokenStr); // token?? token.setLineNum(currentLineNum); // token???? token.setIndexNum(currentIndexNum); tokenList.add(token); currentIndexNum = currentIndexNum + tokenStr.length() + 1; } currentIndexNum = 0; currentLineNum++; } return resolveJsDoc(); } private JSDocRoot resolveJsDoc() { // ?????(@~~) JSTag currentTag = JSTag.ROOT; // ??Token? TokenType previousTokenType = TokenType.START; JSDocRoot root = new JSDocRoot(docType); // ?.?????. JSTagNode tempNode = root; int currentLineNum = 0; // ??StringBuilder StringBuilder currentDesc = new StringBuilder(); // JsDoc?. String desc = null; for (Token token : tokenList) { if (currentDesc.length() != 0 && !TokenUtil.isSymbolType(token.getType())) { if (token.getLineNum() != currentLineNum) { // ?????? currentDesc.append(Constants.LINE_SEPARATOR); currentLineNum = token.getLineNum(); } else { // ?????Token?. currentDesc.append(" "); } } switch (token.getType()) { case STRING_LITERAL: resolveStringLiteral(token, currentTag, previousTokenType, tempNode, currentDesc); break; case ANNOTATION: if (tempNode instanceof JSDocRoot) { // ??????desc?JSDoc????desc?? desc = currentDesc.toString(); } else if (tempNode instanceof JSSinglePartTagNode) { // ?????. ((JSSinglePartTagNode) tempNode).setValue(StringUtils.chomp(currentDesc.toString())); } if (tempNode != root) { root.addTagNode(tempNode); } currentDesc = new StringBuilder(); // ?????. JSTag temp = TokenUtil.resolveTagType(token); if (temp != null) { currentTag = temp; } // ?????. tempNode = resolveTagNode(currentTag); break; case TYPE: if (currentTag == null) { // ???????? currentDesc.append(token.getValue()); } if (tempNode instanceof JSTypePartNode) { // Type??????node? ((JSTypePartNode) tempNode).setType(StringUtils.strip(token.getValue(), "{}")); } break; case END: if (tempNode instanceof JSSinglePartTagNode) { // ?????. ((JSSinglePartTagNode) tempNode).setValue(currentDesc.toString()); } root.addTagNode(tempNode); break; case START: case SYMBOL: default: break; } previousTokenType = token.getType(); } // ?. root.setDescription(desc); return root; } /** * token???.??????????. * * @param token ??. * @param currentTag ????? * @param previousTokenType ?????. * @param tempNode . * @param desc . */ private void resolveStringLiteral(Token token, JSTag currentTag, TokenType previousTokenType, JSTagNode tempNode, StringBuilder desc) { switch (currentTag) { case PARAM: case PROPERTY: // ???????Param????tempNode?TypeNamePartNode switch (previousTokenType) { case TYPE: // ???????????????. if (tempNode instanceof JSTypeNamePartNode) { ((JSTypeNamePartNode) tempNode).setName(token.getValue()); } return; default: break; } default: // ????. desc.append(token.getValue()); break; } } private JSTagNode resolveTagNode(JSTag currentTag) { if (ArrayUtils.contains(TagType.NO_PART_TAG.getJsTag(), currentTag)) { return new JSNoPartTagNode(currentTag); } else if (ArrayUtils.contains(TagType.SINGLE_PART_TAG.getJsTag(), currentTag)) { return new JSSinglePartTagNode(currentTag); } else if (ArrayUtils.contains(TagType.OTHER_PARAM_TAG.getJsTag(), currentTag)) { switch (currentTag) { case PARAM: case PROPERTY: return new JSTypeNamePartNode(currentTag); case THROWS: case RETURNS: return new JSTypePartNode(currentTag); default: break; } // ??SinglePartTag? return new JSSinglePartTagNode(currentTag); } return null; } }