blob: f0906b12a7a66e3d02d2f6f97da34cf8e07b55e4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.felix.schematizer.impl;
//import java.lang.annotation.Annotation;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.lang.reflect.Modifier;
//import java.lang.reflect.ParameterizedType;
//import java.lang.reflect.Type;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collection;
//import java.util.Collections;
//import java.util.Comparator;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.Map.Entry;
//import java.util.Optional;
//import java.util.Set;
//import java.util.function.Function;
//import java.util.stream.Collectors;
//
//import org.apache.felix.schematizer.Node;
//import org.apache.felix.schematizer.Node.CollectionType;
//import org.apache.felix.schematizer.Schema;
//import org.apache.felix.schematizer.Schematizer;
//import org.apache.felix.schematizer.TypeRule;
//import org.osgi.dto.DTO;
//import org.osgi.framework.Bundle;
//import org.osgi.framework.ServiceFactory;
//import org.osgi.framework.ServiceRegistration;
//import org.osgi.util.converter.StandardConverter;
//import org.osgi.util.converter.TypeReference;
//
//public class SchematizerImplOLD implements Schematizer, ServiceFactory<Schematizer> {
//
// private final Map<String, SchemaImpl> schemas = new HashMap<>();
// private volatile Map<String, Map<String, Object>> typeRules = new HashMap<>();
// private final List<ClassLoader> classloaders = new ArrayList<>();
//
// @Override
// public Schematizer getService( Bundle bundle, ServiceRegistration<Schematizer> registration ) {
// return this;
// }
//
// @Override
// public void ungetService(Bundle bundle, ServiceRegistration<Schematizer> registration, Schematizer service) {
// // For now, a brutish, simplistic version. If there is any change to the environment, just
// // wipe the state and start over.
// //
// // TODO: something more precise, which will remove only the classes that are no longer valid (if that is possible).
// schemas.clear();
// typeRules.clear();
// classloaders.clear();
// }
//
// @Override
// public Optional<Schema> get(String name) {
// if (!schemas.containsKey(name)) {
// SchemaImpl schema = schematize(name, "");
// schemas.put(name, schema);
// }
//
// return Optional.ofNullable(schemas.get(name));
// }
//
// @Override
// public Optional<Schema> from(String name, Map<String, Node.DTO> map) {
// try {
// // TODO: some validation of the Map here would be good
// SchemaImpl schema = new SchemaImpl(name);
// Object rootMap = map.get("/");
// Node.DTO rootDTO = new StandardConverter().convert(rootMap).to(Node.DTO.class);
// Map<String, NodeImpl> allNodes = new HashMap<>();
// NodeImpl root = new NodeImpl(rootDTO, "", new Instantiator(classloaders), allNodes);
// associateChildNodes(root);
// schema.add(root);
// schema.add(allNodes);
// return Optional.of(schema);
// } catch (Throwable t) {
// return Optional.empty();
// }
// }
//
// @Override
// public <T extends DTO> Schematizer rule(String name, TypeRule<T> rule) {
// Map<String, Object> rules = rulesFor(name);
// rules.put(rule.getPath(), rule.getType());
// return this;
// }
//
// @Override
// public <T extends DTO> Schematizer rule(String name, String path, TypeReference<T> type) {
// Map<String, Object> rules = rulesFor(name);
// rules.put(path, type);
// return this;
// }
//
// @Override
// public <T extends DTO> Schematizer rule(String name, TypeReference<T> type) {
// Map<String, Object> rules = rulesFor(name);
// rules.put("/", type);
// return this;
// }
//
// @Override
// public <T> Schematizer rule(String name, String path, Class<T> cls) {
// Map<String, Object> rules = rulesFor(name);
// rules.put(path, cls);
// return this;
// }
//
// private Map<String, Object> rulesFor(String name) {
// if (!typeRules.containsKey(name))
// typeRules.put(name, new HashMap<>());
//
// return typeRules.get(name);
// }
//
// @Override
// public Schematizer usingLookup( ClassLoader classloader ) {
// if (classloader != null)
// classloaders.add(classloader);
// return this;
// }
//
// /**
// * Top-level entry point for schematizing a DTO. This is the starting point to set up the
// * parsing. All other methods make recursive calls.
// */
// private SchemaImpl schematize(String name, String contextPath) {
// Map<String, Object> rules = typeRules.get(name);
// rules = ( rules != null ) ? rules : Collections.emptyMap();
// return SchematizerImplOLD.internalSchematize(name, contextPath, rules, false, this);
// }
//
// @SuppressWarnings( { "unchecked", "rawtypes" } )
// /**
// * Schematize any node, without knowing in advance its type.
// */
// private static SchemaImpl internalSchematize(
// String name,
// String contextPath,
// Map<String, Object> rules,
// boolean isCollection,
// SchematizerImplOLD schematizer) {
// Class<?> cls = null;
// TypeReference<? extends DTO> ref = null;
// if (contextPath.isEmpty() && rules.containsKey("/")) {
// ref = (TypeReference)typeReferenceOf(rules.get("/"));
// if (ref == null )
// cls = rawClassOf(rules.get("/"));
// }
//
// if (rules.containsKey(contextPath)) {
// ref = (TypeReference)(typeReferenceOf(rules.get(contextPath)));
// if (ref == null )
// cls = rawClassOf(rules.get(contextPath));
// }
//
// if (ref != null )
// cls = rawClassOf(ref);
//
// if (cls == null)
// return handleInvalid();
//
// if (DTO.class.isAssignableFrom(cls)) {
// Class<? extends DTO> targetCls = (Class<DTO>)cls;
// return schematizeDTO(name, targetCls, ref, contextPath, rules, isCollection, schematizer);
// }
//
// return schematizeObject( name, cls, contextPath, rules, isCollection, schematizer);
// }
//
// private static SchemaImpl schematizeDTO(
// String name,
// Class<? extends DTO> targetCls,
// TypeReference<? extends DTO> ref,
// String contextPath,
// Map<String, Object> rules,
// boolean isCollection,
// SchematizerImplOLD schematizer) {
//
// SchemaImpl schema = new SchemaImpl(name);
// NodeImpl rootNode;
// if (ref != null)
// rootNode = new NodeImpl(contextPath, ref, false, contextPath + "/");
// else
// rootNode = new NodeImpl(contextPath, targetCls, false, contextPath + "/");
// schema.add(rootNode);
// Map<String, NodeImpl> m = createMapFromDTO(name, targetCls, ref, contextPath, rules, schematizer);
// m.values().stream().filter(v -> v.absolutePath().equals(rootNode.absolutePath() + v.name())).forEach(v -> rootNode.add(v));
// associateChildNodes( rootNode );
// schema.add(m);
// return schema;
// }
//
// private static SchemaImpl schematizeObject(
// String name,
// Class<?> targetCls,
// String contextPath,
// Map<String, Object> rules,
// boolean isCollection,
// SchematizerImplOLD schematizer) {
//
// SchemaImpl schema = new SchemaImpl(name);
// NodeImpl node = new NodeImpl(contextPath, targetCls, isCollection, contextPath + "/");
// schema.add(node);
// return schema;
// }
//
// private static final Comparator<Entry<String, NodeImpl>> byPath = (e1, e2) -> e1.getValue().absolutePath().compareTo(e2.getValue().absolutePath());
// private static Map<String, NodeImpl> createMapFromDTO(
// String name,
// Class<?> targetCls,
// TypeReference<? extends DTO> ref,
// String contextPath,
// Map<String, Object> typeRules,
// SchematizerImplOLD schematizer) {
// Set<String> handledFields = new HashSet<>();
//
// Map<String, NodeImpl> result = new HashMap<>();
// for (Field f : targetCls.getDeclaredFields()) {
// handleField(name, f, handledFields, result, targetCls, ref, contextPath, typeRules, schematizer);
// }
// for (Field f : targetCls.getFields()) {
// handleField(name, f, handledFields, result, targetCls, ref, contextPath, typeRules, schematizer);
// }
//
// return result.entrySet().stream().sorted(byPath).collect(Collectors.toMap(Entry::getKey, Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
// }
//
// @SuppressWarnings( { "rawtypes", "unchecked" } )
// private static void handleField(
// String name,
// Field field,
// Set<String> handledFields,
// Map<String, NodeImpl> result,
// Class<?> targetCls,
// TypeReference<?> ref,
// String contextPath,
// Map<String, Object> rules,
// SchematizerImplOLD schematizer) {
// if (Modifier.isStatic(field.getModifiers()))
// return;
//
// String fieldName = field.getName();
// if (handledFields.contains(fieldName))
// return; // Field with this name was already handled
//
// try {
// String path = contextPath + "/" + fieldName;
// NodeImpl node;
// if (rules.containsKey(path)) {
// // The actual field. Since the type for this node is provided as a rule, we
// // only need it to test whether or not it is a collection.
// Class<?> actualFieldType = field.getType();
// boolean isCollection = Collection.class.isAssignableFrom(actualFieldType);
// Class<?> rawClass = rawClassOf(rules.get(path));
// // This is the type we will persist in the Schema (as provided by the rules), NOT the "actual" field type.
// SchemaImpl embedded = SchematizerImplOLD.internalSchematize(name, path, rules, isCollection, schematizer);
// Class<?> fieldClass = Util.primitiveToBoxed(rawClass);
// TypeReference fieldRef = typeReferenceOf(rules.get(path));
// if (isCollection)
// node = new CollectionNode(
// field.getName(),
// fieldRef,
// path,
// (Class)actualFieldType);
// else if (fieldRef != null )
// node = new NodeImpl(fieldName, fieldRef, false, path);
// else
// node = new NodeImpl(fieldName, fieldClass, false, path);
// Map<String, NodeImpl> allNodes = embedded.toMapInternal();
// allNodes.remove(path + "/");
// result.putAll(allNodes);
// Map<String, NodeImpl> childNodes = extractChildren(path, allNodes);
// node.add(childNodes);
// } else {
// Type fieldType = field.getType();
// Class<?> rawClass = rawClassOf(fieldType);
// Class<?> fieldClass = Util.primitiveToBoxed(rawClass);
//
// if (Collection.class.isAssignableFrom(fieldClass)) {
// CollectionType collectionTypeAnnotation = field.getAnnotation( CollectionType.class );
// Class<?> collectionType;
// if (collectionTypeAnnotation != null)
// collectionType = collectionTypeAnnotation.value();
// else if (hasCollectionTypeAnnotation(field))
// collectionType = collectionTypeOf(field);
// else
// collectionType = Object.class;
// node = new CollectionNode(
// field.getName(),
// collectionType,
// path,
// (Class)fieldClass);
//
// if (DTO.class.isAssignableFrom(collectionType)) {
// SchematizerImplOLD newSchematizer = new SchematizerImplOLD();
// newSchematizer.typeRules.put(path, rules);
// if (!rules.containsKey(path))
// newSchematizer.rule(path, path, collectionType);
// SchemaImpl embedded = newSchematizer.schematize(path, path);
// Map<String, NodeImpl> allNodes = embedded.toMapInternal();
// allNodes.remove(path + "/");
// result.putAll(allNodes);
// Map<String, NodeImpl> childNodes = extractChildren(path, allNodes);
// node.add(childNodes);
// }
// }
// else if (DTO.class.isAssignableFrom(fieldClass)) {
// SchematizerImplOLD newSchematizer = new SchematizerImplOLD();
// newSchematizer.typeRules.put(path, rules);
// if (!rules.containsKey(path))
// newSchematizer.rule(path, path, fieldClass);
// SchemaImpl embedded = newSchematizer.schematize(path, path);
// node = new NodeImpl(
// field.getName(),
// fieldClass,
// false,
// path);
// Map<String, NodeImpl> allNodes = embedded.toMapInternal();
// allNodes.remove(path + "/");
// result.putAll(allNodes);
// Map<String, NodeImpl> childNodes = extractChildren(path, allNodes);
// node.add(childNodes);
// } else {
// node = new NodeImpl(
// field.getName(),
// fieldClass,
// false,
// path);
// }
// }
//
// result.put(node.absolutePath(), node);
// handledFields.add(fieldName);
// } catch (Exception e) {
// // Ignore this field
// // TODO print warning??
// return;
// }
// }
//
// private static Map<String, NodeImpl> extractChildren( String path, Map<String, NodeImpl> allNodes ) {
// final Map<String, NodeImpl> children = new HashMap<>();
// for (String key : allNodes.keySet()) {
// String newKey = key.replace(path, "");
// if (!newKey.substring(1).contains("/"))
// children.put( newKey, allNodes.get(key));
// }
//
// return children;
// }
//
// private static SchemaImpl handleInvalid() {
// // TODO
// return null;
// }
//
// private static Class<?> rawClassOf(Object type) {
// Class<?> rawClass = null;
// if (type instanceof Class) {
// rawClass = (Class<?>)type;
// } else if (type instanceof ParameterizedType) {
// ParameterizedType paramType = (ParameterizedType) type;
// Type rawType = paramType.getRawType();
// if (rawType instanceof Class)
// rawClass = (Class<?>)rawType;
// } else if (type instanceof TypeReference) {
// return rawClassOf(((TypeReference<?>)type).getType());
// }
//
// return rawClass;
// }
//
// private static TypeReference<?> typeReferenceOf(Object type) {
// TypeReference<?> typeRef = null;
// if (type instanceof TypeReference)
// typeRef = (TypeReference<?>)type;
// return typeRef;
// }
//
// public static class Instantiator implements Function<String, Type> {
// private final List<ClassLoader> classloaders = new ArrayList<>();
//
// public Instantiator(List<ClassLoader> aClassLoadersList) {
// classloaders.addAll( aClassLoadersList );
// }
//
// @Override
// public Type apply(String className) {
// for (ClassLoader cl : classloaders) {
// try {
// return cl.loadClass(className);
// } catch (ClassNotFoundException e) {
// // Try next
// }
// }
//
// // Could not find the class. Try "this" ClassLoader
// try {
// return getClass().getClassLoader().loadClass(className);
// } catch (ClassNotFoundException e) {
// // Too bad
// }
//
// // Nothing to do. Return Object.class as the fallback
// return Object.class;
// }
// }
//
// static private void associateChildNodes(NodeImpl rootNode) {
// for (NodeImpl child: rootNode.childrenInternal().values()) {
// child.parent(rootNode);
// String fieldName = child.name();
// Class<?> parentClass = rawClassOf(rootNode.type());
// try {
// Field field = parentClass.getField(fieldName);
// child.field(field);
// } catch ( NoSuchFieldException e ) {
// e.printStackTrace();
// }
//
// associateChildNodes(child);
// }
// }
//
// static private boolean hasCollectionTypeAnnotation(Field field) {
// if (field == null)
// return false;
//
// Annotation[] annotations = field.getAnnotations();
// if (annotations.length == 0)
// return false;
//
// return Arrays.stream(annotations)
// .map(a -> a.annotationType().getName())
// .anyMatch(a -> "CollectionType".equals(a.substring(a.lastIndexOf(".") + 1) ));
// }
//
// static private Class<?> collectionTypeOf(Field field) {
// Annotation[] annotations = field.getAnnotations();
//
// Annotation annotation = Arrays.stream(annotations)
// .filter(a -> "CollectionType".equals(a.annotationType().getName().substring(a.annotationType().getName().lastIndexOf(".") + 1) ))
// .findFirst()
// .get();
//
// try {
// Method m = annotation.annotationType().getMethod("value");
// Class<?> value = (Class<?>)m.invoke(annotation, (Object[])null);
// return value;
// } catch ( Exception e ) {
// return null;
// }
// }
//}