/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.
*/
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.ArrayList;
/**
* Class that represents what you see in an link or see tag. This is
* factored out of SeeTagInfo so it can be used elsewhere (like AttrTagInfo).
*/
public class LinkReference {
/** The original text. */
public String text;
/** The kind of this tag, if we have a new suggestion after parsing. */
public String kind;
/** The user visible text. */
public String label;
/** The link. */
public String href;
/** The {@link PackageInfo} if any. */
public PackageInfo packageInfo;
/** The {@link ClassInfo} if any. */
public ClassInfo classInfo;
/** The {@link MemberInfo} if any. */
public MemberInfo memberInfo;
/** The name of the referenced member PackageInfo} if any. */
public String referencedMemberName;
/** Set to true if everything is a-ok */
public boolean good;
/**
* regex pattern to use when matching explicit "([^<]*)[ \n\r\t]*$",
Pattern.CASE_INSENSITIVE);
/**
* regex pattern to use when matching double-quoted reference text
*/
private static final Pattern QUOTE_PATTERN
= Pattern.compile("^\"([^\"]*)\"[ \n\r\t]*$");
/**
* Parse and resolve a link string.
*
* @param text the original text
* @param base the class or whatever that this link is on
* @param pos the original position in the source document
* @return a new link reference. It always returns something. If there was an
* error, it logs it and fills in href and label with error text.
*/
public static LinkReference parse(String text, ContainerInfo base, SourcePositionInfo pos,
boolean printOnErrors) {
LinkReference result = new LinkReference();
result.text = text;
int index;
int len = text.length();
int pairs = 0;
int pound = -1;
// split the string
done: {
for (index=0; index 0) {
ref = text.substring(0, pound);
mem = text.substring(pound+1, linkend);
}
else {
ref = text.substring(0, linkend);
mem = null;
}
// parse parameters, if any
String[] params = null;
String[] paramDimensions = null;
if (mem != null) {
index = mem.indexOf('(');
if (index > 0) {
ArrayList paramList = new ArrayList();
ArrayList paramDimensionList = new ArrayList();
len = mem.length();
int start = index+1;
final int START = 0;
final int TYPE = 1;
final int NAME = 2;
int dimension = 0;
int arraypair = 0;
int state = START;
int typestart = 0;
int typeend = -1;
for (int i=start; i= 0 || c == ')' || c == ',') {
if (typeend < 0) {
typeend = i;
}
String s = mem.substring(typestart, typeend);
paramList.add(s);
s = "";
for (int j=0; j 0) {
len--;
for (int i=0; i link/see tag: " + text.trim());
result.makeError();
return result;
}
result.href = matcher.group(1);
result.label = matcher.group(2);
result.kind = "@seeHref";
}
else if (result.packageInfo != null) {
result.href = result.packageInfo.htmlPage();
if (result.label.length() == 0) {
result.href = result.packageInfo.htmlPage();
result.label = result.packageInfo.name();
}
}
else if (result.classInfo != null && result.referencedMemberName == null) {
// class reference
if (result.label.length() == 0) {
result.label = result.classInfo.name();
}
result.href = result.classInfo.htmlPage();
}
else if (result.memberInfo != null) {
// member reference
ClassInfo containing = result.memberInfo.containingClass();
if (result.memberInfo.isExecutable()) {
if (result.referencedMemberName.indexOf('(') < 0) {
result.referencedMemberName += method.flatSignature();
}
}
if (result.label.length() == 0) {
result.label = result.referencedMemberName;
}
result.href = containing.htmlPage() + '#' + result.memberInfo.anchor();
}
if (result.href == null && !skipHref) {
if (printOnErrors && (base == null || base.checkLevel())) {
Errors.error(Errors.UNRESOLVED_LINK, pos,
"Unresolved link/see tag \"" + text.trim()
+ "\" in " + ((base != null) ? base.qualifiedName() : "[null]"));
}
result.makeError();
}
else if (result.memberInfo != null && !result.memberInfo.checkLevel()) {
if (printOnErrors && (base == null || base.checkLevel())) {
Errors.error(Errors.HIDDEN_LINK, pos,
"Link to hidden member: " + text.trim());
result.href = null;
}
result.kind = "@seeJustLabel";
}
else if (result.classInfo != null && !result.classInfo.checkLevel()) {
if (printOnErrors && (base == null || base.checkLevel())) {
Errors.error(Errors.HIDDEN_LINK, pos,
"Link to hidden class: " + text.trim() + " label=" + result.label);
result.href = null;
}
result.kind = "@seeJustLabel";
}
else if (result.packageInfo != null && !result.packageInfo.checkLevel()) {
if (printOnErrors && (base == null || base.checkLevel())) {
Errors.error(Errors.HIDDEN_LINK, pos,
"Link to hidden package: " + text.trim());
result.href = null;
}
result.kind = "@seeJustLabel";
}
result.good = true;
return result;
}
public boolean checkLevel() {
if (memberInfo != null) {
return memberInfo.checkLevel();
}
if (classInfo != null) {
return classInfo.checkLevel();
}
if (packageInfo != null) {
return packageInfo.checkLevel();
}
return false;
}
/** turn this LinkReference into one with an error message */
private void makeError() {
//this.href = "ERROR(" + this.text.trim() + ")";
this.href = null;
if (this.label == null) {
this.label = "";
}
this.label = "ERROR(" + this.label + "/" + text.trim() + ")";
}
/** private. **/
private LinkReference() {
}
}