diff --git a/Plan/common/build.gradle b/Plan/common/build.gradle
index 1cbf02fc8..d5ebebb63 100644
--- a/Plan/common/build.gradle
+++ b/Plan/common/build.gradle
@@ -1,5 +1,6 @@
dependencies {
compile "com.djrapitops:AbstractPluginFramework-api:$abstractPluginFrameworkVersion"
+ compile project(path: ":api", configuration: 'shadow')
compile "com.djrapitops:PlanPluginBridge:$planPluginBridgeVersion"
compile "org.apache.httpcomponents:httpclient:$httpClientVersion"
compile "org.apache.commons:commons-text:$commonsTextVersion"
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/DataProviderExtractor.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/DataProviderExtractor.java
new file mode 100644
index 000000000..b9c90a247
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/DataProviderExtractor.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.extension.implementation;
+
+import com.djrapitops.plan.extension.DataExtension;
+import com.djrapitops.plan.extension.annotation.PluginInfo;
+import com.djrapitops.plan.extension.annotation.Tab;
+import com.djrapitops.plan.extension.annotation.TabInfo;
+import com.djrapitops.plan.extension.annotation.TabOrder;
+import com.djrapitops.plan.extension.extractor.ExtensionExtractor;
+import com.djrapitops.plan.extension.icon.Color;
+import com.djrapitops.plan.extension.icon.Icon;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * Extracts objects that can be used to obtain data to store in the database.
+ *
+ * Goal of this class is to abstract away DataExtension API annotations so that they will not be needed outside when calling methods.
+ *
+ * @author Rsl1122
+ */
+public class DataProviderExtractor {
+
+ private final DataExtension extension;
+ private ExtensionExtractor extensionExtractor;
+
+ /**
+ * Create a DataProviderExtractor.
+ *
+ * @param extension DataExtension to extract information from.
+ * @throws IllegalArgumentException If something is badly wrong with the specified extension class annotations.
+ */
+ public DataProviderExtractor(DataExtension extension) {
+ this.extension = extension;
+ extensionExtractor = new ExtensionExtractor(extension);
+
+ extensionExtractor.extractAnnotationInformation();
+ }
+
+ public String getPluginName() {
+ return extensionExtractor.getPluginInfo().name();
+ }
+
+ public Icon getPluginIcon() {
+ PluginInfo pluginInfo = extensionExtractor.getPluginInfo();
+ return new Icon(pluginInfo.iconFamily(), pluginInfo.iconName(), pluginInfo.color());
+ }
+
+ public Collection getPluginTabs() {
+ Map tabInformation = extensionExtractor.getTabInformation()
+ .stream().collect(Collectors.toMap(TabInfo::tab, Function.identity(), (one, two) -> one));
+
+ return extensionExtractor.getMethodAnnotations().getAnnotations(Tab.class).stream()
+ .map(Tab::value)
+ .distinct()
+ .map(tabName -> {
+ Optional tabInfo = Optional.ofNullable(tabInformation.get(tabName));
+ return new PluginTab(
+ tabName,
+ tabInfo.map(info -> new Icon(info.iconFamily(), info.iconName(), Color.NONE)).orElse(null),
+ tabInfo.map(TabInfo::elementOrder).orElse(null)
+ );
+ }).collect(Collectors.toList());
+ }
+
+ public Optional getTabOrder() {
+ return extensionExtractor.getTabOrder().map(TabOrder::value);
+ }
+}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/PluginTab.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/PluginTab.java
new file mode 100644
index 000000000..991c685cb
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/PluginTab.java
@@ -0,0 +1,72 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.extension.implementation;
+
+import com.djrapitops.plan.extension.ElementOrder;
+import com.djrapitops.plan.extension.icon.Icon;
+import com.djrapitops.plugin.utilities.ArrayUtil;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Represents a tab of {@link com.djrapitops.plan.extension.DataExtension} defined by {@link com.djrapitops.plan.extension.annotation.Tab} and
+ * {@link com.djrapitops.plan.extension.annotation.TabInfo} annotations.
+ *
+ * @author Rsl1122
+ */
+public class PluginTab {
+
+ private final String tabName;
+ private final Icon icon; // can be null
+ private ElementOrder[] elementOrder; // can be null / miss values
+
+ public PluginTab(String tabName, Icon icon, ElementOrder[] elementOrder) {
+ this.tabName = tabName;
+ this.icon = icon;
+ this.elementOrder = elementOrder;
+ }
+
+ public String getTabName() {
+ return tabName;
+ }
+
+ public Optional getTabIcon() {
+ return Optional.ofNullable(icon);
+ }
+
+ public Optional getTabElementOrder() {
+ if (elementOrder == null) {
+ return Optional.empty();
+ }
+
+ ElementOrder[] possibleValues = ElementOrder.values();
+ if (elementOrder.length < possibleValues.length) {
+ addMissingElements(possibleValues);
+ }
+
+ return Optional.of(elementOrder);
+ }
+
+ private void addMissingElements(ElementOrder[] possibleValues) {
+ for (ElementOrder possibleValue : possibleValues) {
+ if (Arrays.binarySearch(elementOrder, possibleValue) < 0) {
+ elementOrder = ArrayUtil.merge(elementOrder, new ElementOrder[]{possibleValue});
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProvider.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProvider.java
new file mode 100644
index 000000000..115c92e42
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProvider.java
@@ -0,0 +1,92 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.extension.implementation.providers;
+
+import com.djrapitops.plan.extension.icon.Icon;
+
+import java.util.Optional;
+
+/**
+ * Abstract representation of all values a Provider annotation provides.
+ *
+ * @author Rsl1122
+ */
+public abstract class DataProvider {
+
+ private final String plugin;
+ private final String condition; // can be null
+ private final String tab; // can be null
+ private final int priority;
+
+ private final Icon icon;
+ private final String text;
+ private final String description;
+
+ private final MethodWrapper method;
+
+ public DataProvider(
+ String plugin,
+ String condition,
+ String tab,
+ int priority,
+ Icon icon,
+ String text,
+ String description,
+ MethodWrapper method
+ ) {
+ this.plugin = plugin;
+ this.condition = condition;
+ this.tab = tab;
+ this.priority = priority;
+ this.icon = icon;
+ this.text = text;
+ this.description = description;
+ this.method = method;
+ }
+
+ public String getPlugin() {
+ return plugin;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public Icon getIcon() {
+ return icon;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Optional getCondition() {
+ return Optional.ofNullable(condition);
+ }
+
+ public Optional getTab() {
+ return Optional.ofNullable(tab);
+ }
+
+ public MethodWrapper getMethod() {
+ return method;
+ }
+}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java
new file mode 100644
index 000000000..657748811
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/DataProviders.java
@@ -0,0 +1,51 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.extension.implementation.providers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Group class for handling multiple different types of {@link DataProvider}s.
+ *
+ * @author Rsl1122
+ */
+public class DataProviders {
+
+ // Return type, Parameter type, DataProvider
+ private Map>> providers;
+
+ public DataProviders() {
+ providers = new HashMap<>();
+ }
+
+ public void put(Class parameterType, Class returnType, DataProvider provider) {
+ Map> byParameterType = providers.getOrDefault(returnType, new HashMap<>());
+ List dataProviders = byParameterType.getOrDefault(parameterType, new ArrayList<>());
+
+ dataProviders.add(provider);
+
+ byParameterType.put(parameterType, dataProviders);
+ providers.put(returnType, byParameterType);
+ }
+
+ public List get(Class parameterType, Class returnType) {
+ return this.providers.getOrDefault(returnType, new HashMap<>()).getOrDefault(parameterType, new ArrayList<>());
+ }
+}
\ No newline at end of file
diff --git a/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java
new file mode 100644
index 000000000..b6759dd4f
--- /dev/null
+++ b/Plan/common/src/main/java/com/djrapitops/plan/extension/implementation/providers/MethodWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Player Analytics (Plan).
+ *
+ * Plan is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License v3 as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Plan 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Plan. If not, see .
+ */
+package com.djrapitops.plan.extension.implementation.providers;
+
+import com.djrapitops.plan.extension.DataExtension;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Wrap a Method so that it is easier to call.
+ *
+ * @author Rsl1122
+ */
+public class MethodWrapper {
+
+ private final Method method;
+ private final Class result;
+
+ public MethodWrapper(Method method, Class parameter, Class result) {
+ this.method = method;
+ this.result = result;
+ }
+
+ public K callMethod(DataExtension extension, T parameter) throws InvocationTargetException, IllegalAccessException {
+ return result.cast(method.invoke(extension, parameter));
+ }
+
+ public String getMethodName() {
+ return method.getName();
+ }
+}
\ No newline at end of file