/*
* Copyright 2013 Google Inc.
*
* 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.google.gwt.core.ext.soyc.coderef;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.util.Util;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
/**
* A succinct code representation for classes.
*
*/
public class ClassDescriptor extends EntityDescriptor {
/**
* Creates a class descriptor from a JDeclaredType.
*/
public static ClassDescriptor from(JDeclaredType classType) {
return new ClassDescriptor(Util.getClassName(classType.getName()),
Util.getPackageName(classType.getName()),
classType);
}
private final String packageName;
private final Map<String, MethodDescriptor> methodsByJsniSignature = Maps.newTreeMap();
private final Map<String, FieldDescriptor> fieldsByName = Maps.newTreeMap();
private final JDeclaredType typeReference;
/* TODO(ocallau) for storing hierarchy information, but supporting this has been delayed
protected int id;
protected ClassDescriptor superClass;
protected Collection<ClassDescriptor> interfaces;*/
private ClassDescriptor(String className, String packageName, JDeclaredType classType) {
super(className);
this.packageName = packageName;
typeReference = classType;
}
public ClassDescriptor(String className, String packageName) {
this(className, packageName, null);
}
public void addField(FieldDescriptor fieldDescriptor) {
this.fieldsByName.put(fieldDescriptor.getName(), fieldDescriptor);
}
public void addMethod(MethodDescriptor methodDescriptor) {
this.methodsByJsniSignature.put(methodDescriptor.getJsniSignature(), methodDescriptor);
}
/**
* Returns a field descriptor from a JField. If the field descriptor is not in the current class
* descriptor, it will be added.
*/
public FieldDescriptor fieldFrom(JField field) {
FieldDescriptor descriptor = this.fieldsByName.get(field.getName());
if (descriptor == null) {
descriptor = FieldDescriptor.from(this, field);
fieldsByName.put(field.getName(), descriptor);
}
return descriptor;
}
/**
* Returns the field descriptor associated to the given field name.
*/
public FieldDescriptor getField(String fieldName) {
return fieldsByName.get(fieldName);
}
public Collection<FieldDescriptor> getFields() {
return Collections.unmodifiableCollection(fieldsByName.values());
}
@Override
public String getFullName() {
if (packageName.isEmpty()) {
return name;
}
return packageName + "." + name;
}
/**
* Returns the method descriptor associated to the given original method signature.
*/
public MethodDescriptor getMethod(String methodSignature) {
methodSignature = MethodDescriptor.normalizeMethodSignature(methodSignature);
return methodsByJsniSignature.get(methodSignature);
}
public Collection<MethodDescriptor> getMethods() {
return Collections.unmodifiableCollection(methodsByJsniSignature.values());
}
public String getPackageName() {
return packageName;
}
public JDeclaredType getTypeReference() {
return typeReference;
}
/**
* Returns a method descriptor from a JMethod and its original signature (prior any modifications).
* If the method descriptor is not in the current class descriptor, it will be added.
*/
public MethodDescriptor methodFrom(JMethod method, String signature) {
signature = MethodDescriptor.normalizeMethodSignature(signature);
MethodDescriptor methodDescriptor = this.methodsByJsniSignature.get(signature);
if (methodDescriptor == null) {
methodDescriptor = MethodDescriptor.from(this, method, signature);
methodsByJsniSignature.put(signature, methodDescriptor);
} else {
methodDescriptor.addReference(method);
}
return methodDescriptor;
}
}