
org.bimserver.shared.meta.SServicesMap Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of PluginBase Show documentation
Show all versions of PluginBase Show documentation
Base project for BIMserver plugin development. Some plugins mights also need the Shared library
package org.bimserver.shared.meta;
/******************************************************************************
* Copyright (C) 2009-2016 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.GenericDeclaration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.xml.bind.annotation.XmlSeeAlso;
import org.bimserver.shared.interfaces.PublicInterface;
import org.bimserver.shared.reflector.ReflectorFactory;
import org.bimserver.utils.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class SServicesMap {
// Must be LinkedHashMap because order IS important for dependencies
private final Map servicesByName = new LinkedHashMap();
private final Map servicesBySimpleName = new LinkedHashMap();
private final Map types = new TreeMap();
private ReflectorFactory reflectorFactory;
public void add(SService sService) {
servicesByName.put(sService.getName(), sService);
servicesBySimpleName.put(sService.getSimpleName(), sService);
}
public SService getByName(String name) {
return servicesByName.get(name);
}
public Collection list() {
return servicesByName.values();
}
public SService getBySimpleName(String name) {
return servicesBySimpleName.get(name);
}
public SClass getType(String name) {
for (SService sService : servicesByName.values()) {
SClass type = sService.getServicesMap().getSType(name);
if (type != null) {
return type;
}
}
return null;
}
public Set keySetName() {
return servicesByName.keySet();
}
public Set keySetSimpleName() {
return servicesBySimpleName.keySet();
}
public void addType(final Class> type) {
if (!types.containsKey(type.getSimpleName())) {
// TODO reflective constructor use can be slow
SClass sClass = new SClass(this, type, new SConstructor(){
@Override
public Object newInstance() {
try {
return type.getConstructors()[0].newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}});
types.put(sClass.getSimpleName(), sClass);
types.put(sClass.getName(), sClass);
addRelatedTypes(type);
}
}
public void addType(SClass type) {
types.put(type.getSimpleName(), type);
types.put(type.getName(), type);
addRelatedTypes(type.getInstanceClass());
}
private void addRelatedTypes(Class> type) {
for (Method method : type.getMethods()) {
if (method.getName().startsWith("get") && method.getName().length() > 3 && !method.getName().equals("getSClass")) {
if (type.getAnnotation(XmlSeeAlso.class) != null) {
XmlSeeAlso xmlSeeAlso = type.getAnnotation(XmlSeeAlso.class);
for (Class> c : xmlSeeAlso.value()) {
addType(c);
}
}
if (type.getSuperclass() != null) {
addType(type.getSuperclass());
}
String fieldName = StringUtils.firstLowerCase(method.getName().substring(3));
try {
if (type.getMethod("set" + StringUtils.firstUpperCase(fieldName), method.getReturnType()) != null) {
addType(method.getReturnType());
}
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
if (getGenericType(method) != null) {
addType(getGenericType(method));
}
for (Class> pt : method.getParameterTypes()) {
addType(pt);
}
}
}
}
@SuppressWarnings("restriction")
public Class> getGenericType(Method method) {
Type genericReturnType = method.getGenericReturnType();
if (method.getGenericReturnType() instanceof ParameterizedType) {
ParameterizedType parameterizedTypeImpl = (ParameterizedType)genericReturnType;
Type first = parameterizedTypeImpl.getActualTypeArguments()[0];
if (first instanceof WildcardType) {
return null;
} else if (first instanceof ParameterizedType) {
return null;
} else if (first instanceof sun.reflect.generics.reflectiveObjects.TypeVariableImpl) {
sun.reflect.generics.reflectiveObjects.TypeVariableImpl> typeVariableImpl = (sun.reflect.generics.reflectiveObjects.TypeVariableImpl>)first;
GenericDeclaration genericDeclaration = typeVariableImpl.getGenericDeclaration();
if (genericDeclaration instanceof Class) {
return (Class>) genericDeclaration;
}
} else {
return (Class>) first;
}
}
return (Class>) method.getGenericReturnType();
}
public Set getTypes() {
return new HashSet(types.values());
}
// public SClass getSType(String name, Set checked) {
// checked.add(this);
// SClass sType = types.get(name);
// if (sType == null) {
// if (name.contains(".")) {
// name = name.substring(name.lastIndexOf(".") + 1);
// return getSType(name, checked);
// }
// }
// if (sType == null) {
// for (SService other : others) {
// if (!checked.contains(other)) {
// SClass otherClass = other.getSType(name, checked);
// if (otherClass != null) {
// return otherClass;
// }
// }
// }
// }
// return sType;
// }
public SClass getSType(String name) {
return types.get(name);
// return getSType(name, new HashSet());
}
public Set> getInterfaceClasses() {
Set> result = new LinkedHashSet>();
for (SService sService : servicesByName.values()) {
result.add((Class extends PublicInterface>) sService.getInterfaceClass());
}
return result;
}
public void setReflectorFactory(ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
}
public ReflectorFactory getReflectorFactory() {
return reflectorFactory;
}
/**
* Inefficient method of getting a SMethod
*
* @param methodName
* @return
*/
public SMethod findMethod(String methodName) {
for (SService sService : servicesByName.values()) {
SMethod method = sService.getSMethod(methodName);
if (method != null) {
return method;
}
}
return null;
}
public ObjectNode toJson(ObjectMapper objectMapper) {
ObjectNode result = objectMapper.createObjectNode();
ArrayNode servicesJson = objectMapper.createArrayNode();
result.set("services", servicesJson);
for (SService sService : servicesByName.values()) {
ObjectNode serviceJson = objectMapper.createObjectNode();
serviceJson.put("name", sService.getName());
serviceJson.put("simpleName", sService.getSimpleName());
servicesJson.add(serviceJson);
ArrayNode methodsJson = objectMapper.createArrayNode();
serviceJson.set("methods", methodsJson);
for (SMethod method : sService.getMethods()) {
methodsJson.add(method.toJson(objectMapper));
}
}
return result;
}
public void initialize() {
for (SService sService : servicesByName.values()) {
sService.init();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy