All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bimserver.shared.meta.SService Maven / Gradle / Ivy

package org.bimserver.shared.meta;

/******************************************************************************
 * Copyright (C) 2009-2017  BIMserver.org
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see {@literal}.
 *****************************************************************************/

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.jws.WebService;

import org.bimserver.shared.interfaces.PublicInterface;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SService {
	private static final Logger LOGGER = LoggerFactory.getLogger(SService.class);
	private final Map methods = new TreeMap();
	private final String fullName;
	private final Class interfaceClass;
	private boolean processJavaDoc = true;
	private SServicesMap servicesMap;
	private String simpleName;
	private SourceCodeFetcher sourceCodeFetcher;
	private String nameSpace;

	public SService(SServicesMap servicesMap, SourceCodeFetcher sourceCodeFetcher, Class interfaceClass) {
		this.servicesMap = servicesMap;
		this.sourceCodeFetcher = sourceCodeFetcher;
		this.interfaceClass = interfaceClass;
		this.nameSpace = interfaceClass.getAnnotation(WebService.class).targetNamespace();
		this.fullName = interfaceClass.getAnnotation(WebService.class).targetNamespace() + "." + interfaceClass.getAnnotation(WebService.class).name();
		this.simpleName = interfaceClass.getAnnotation(WebService.class).name();
	}
	
	private void processClass(Class clazz) {
		if (clazz == Class.class) {
			return;
		}
		for (Class x : clazz.getInterfaces()) {
			processClass(x);
		}
		// Parents first, subclasses their documentation have precedence
		extractJavaDoc(clazz);
	}

	private void extractJavaDoc(Class clazz) {
		ASTParser parser = ASTParser.newParser(AST.JLS4);
		parser.setSource(sourceCodeFetcher.get(clazz).toCharArray());
		parser.setKind(ASTParser.K_COMPILATION_UNIT);
		final CompilationUnit cu = (CompilationUnit) parser.createAST(null);
		cu.accept(new ASTVisitor() {
			MethodDeclaration currentMethod = null;

			public boolean visit(Javadoc javaDoc) {
				if (currentMethod != null) {
					SMethod method = getSMethod(currentMethod.getName().getIdentifier());
					if (method == null) {
						LOGGER.error("Method " + currentMethod.getName().getIdentifier() + " not found in class");
					} else {
						for (Object tag : javaDoc.tags()) {
							if (tag instanceof TagElement) {
								TagElement tagElement = (TagElement) tag;
								String tagName = tagElement.getTagName() == null ? null : tagElement.getTagName().trim();
								if ("@param".equals(tagName)) {
									SParameter parameter = null;
									for (int i = 0; i < tagElement.fragments().size(); i++) {
										Object fragment = tagElement.fragments().get(i);
										if (i == 0 && fragment instanceof SimpleName) {
											parameter = method.getParameter(((SimpleName) fragment).getIdentifier());
										} else if (i == 1 && parameter != null && fragment instanceof TextElement) {
											parameter.setDoc(((TextElement) fragment).getText());
										}
									}
								} else if ("@return".equals(tagName)) {
									method.setReturnDoc(extractFullText(tagElement));
								} else if ("@throws".equals(tagName)) {
								} else {
									method.setDoc(extractFullText(tagElement));
								}
							}
						}
					}
				}
				return super.visit(javaDoc);
			}

			@Override
			public boolean visit(MethodDeclaration node) {
				currentMethod = node;
				return super.visit(node);
			}

			@Override
			public void endVisit(MethodDeclaration node) {
				currentMethod = null;
				super.endVisit(node);
			}
		});
	}

	private String extractFullText(TagElement tagElement) {
		StringBuilder builder = new StringBuilder();
		for (Object fragment : tagElement.fragments()) {
			if (fragment instanceof TextElement) {
				TextElement textElement = (TextElement) fragment;
				builder.append(textElement.getText() + " ");
			}
		}
		return builder.toString().trim();
	}

	public void init() {
		for (Method method : interfaceClass.getMethods()) {
			getServicesMap().addType(method.getReturnType());
			if (getGenericType(method) != null) {
				getServicesMap().addType(getGenericType(method));
			}
			for (Class paramType : method.getParameterTypes()) {
				getServicesMap().addType(paramType);
			}
		}
		for (SClass sType : getServicesMap().getTypes()) {
			sType.init();
		}
		for (Method method : interfaceClass.getMethods()) {
			methods.put(method.getName(), new SMethod(this, method));
		}
		if (processJavaDoc && sourceCodeFetcher != null) {
			processClass(interfaceClass);
		}
	}

	private Class getGenericType(Method method) {
		Type genericReturnType = method.getGenericReturnType();
		if (method.getGenericReturnType() instanceof ParameterizedType) {
			ParameterizedType parameterizedTypeImpl = (ParameterizedType) genericReturnType;
			if (parameterizedTypeImpl.getActualTypeArguments()[0] instanceof Class) {
				return (Class) parameterizedTypeImpl.getActualTypeArguments()[0];
			} else if (parameterizedTypeImpl.getActualTypeArguments()[0] instanceof GenericArrayType) {
//				GenericArrayType genericArrayType = (GenericArrayType)parameterizedTypeImpl.getActualTypeArguments()[0];
//				Type genericComponentType = genericArrayType.getGenericComponentType();
//				if (genericComponentType instanceof Class) {
//					return (Class)genericComponentType;
//				}
			}
		} else if (method.getGenericReturnType() instanceof TypeVariable) {
		} else if (method.getGenericReturnType() instanceof GenericArrayType) {
		} else {
			return (Class) method.getGenericReturnType();
		}
		return null;
	}

	public String getName() {
		return fullName;
	}

	public Set getMethods() {
		return new LinkedHashSet(methods.values());
	}

	public SMethod getSMethod(String name) {
		return methods.get(name);
	}

	public Class getInterfaceClass() {
		return interfaceClass;
	}

//	public void dump() {
//		System.out.println(getMethods().size());
//		for (SMethod method : getMethods()) {
//			System.out.println(method.getName() + ": " + method.getReturnType().getName() + " (" + method.getDoc() + ")");
//			for (SParameter parameter : method.getParameters()) {
//				System.out.println("\t" + parameter.getName() + " " + parameter.getType().getName() + " (" + parameter.getDoc() + ")");
//			}
//			System.out.println();
//		}
//		for (SClass type : getTypes()) {
//			System.out.println(type.getName());
//			for (SField sField : type.getAllFields()) {
//				SClass type2 = sField.getType();
//				if (type2 == null) {
//					System.err.println("type for " + sField.getName() + " = null");
//				} else {
//					System.out.println("\t" + sField.getName() + " " + type2.getName());
//				}
//			}
//			System.out.println();
//		}
//	}

	public SServicesMap getServicesMap() {
		return servicesMap;
	}

	public String getSimpleName() {
		return simpleName;
	}

	public SMethod getMethod(String methodName) {
		return methods.get(methodName);
	}

	public String getNameSpace() {
		return nameSpace;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy