001/**
002 *
003 * Copyright 2019-2021 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smack.provider;
018
019import java.lang.reflect.ParameterizedType;
020import java.lang.reflect.Type;
021import java.lang.reflect.TypeVariable;
022
023import org.jivesoftware.smack.packet.Element;
024
025public class AbstractProvider<E extends Element> {
026
027    private final Class<E> elementClass;
028
029    @SuppressWarnings("unchecked")
030    protected AbstractProvider() {
031        Type currentType = getClass().getGenericSuperclass();
032        while (!(currentType instanceof ParameterizedType)) {
033            Class<?> currentClass = (Class<?>) currentType;
034            currentType = currentClass.getGenericSuperclass();
035        }
036        ParameterizedType parameterizedGenericSuperclass = (ParameterizedType) currentType;
037        Type[] actualTypeArguments = parameterizedGenericSuperclass.getActualTypeArguments();
038        Type elementType = actualTypeArguments[0];
039
040
041        if (elementType instanceof Class) {
042            elementClass = (Class<E>) elementType;
043        } else if (elementType instanceof ParameterizedType) {
044            ParameterizedType parameteriezedElementType = (ParameterizedType) elementType;
045            elementClass = (Class<E>) parameteriezedElementType.getRawType();
046        } else if (elementType instanceof TypeVariable) {
047            TypeVariable<?> typeVariableElementType = (TypeVariable<?>) elementType;
048            elementClass = (Class<E>) typeVariableElementType.getClass();
049        } else {
050            throw new AssertionError("Element type '" + elementType + "' (" + elementType.getClass()
051                            + ") is neither of type Class, ParameterizedType or TypeVariable");
052        }
053    }
054
055    public final Class<E> getElementClass() {
056        return elementClass;
057    }
058}