Пожалуйста, избегайте давать ответы только на Kotlin и выше, чем Android 21.
Я пытаюсь создать синтаксический анализатор API, который использует логику иерархии классов для представления самой иерархии API.С этой структурой я могу анализировать API несложным способом, и я уже смог достичь этого, но я хотел бы улучшить его дальше.
Я начну объяснять, что я уже реализовал.
Это пример URL, который мое приложение будет получать через GET
, анализировать и отправлять его внутренне:
http://www.example.com/news/article/1105
В приложении базовый домен не имеет значения, но послеСтруктура API.
В этом случае мы имеем смесь команд и переменных:
- news (команда)
- article (команда)
- 1105 (переменная)
Чтобы установить, что такое команда и что такое переменная, я построил следующие структуры классов:
public class API {
public static final News extends AbstractNews {}
}
public class AbstractNews {
public static final Article extends AbstractArticle {}
}
public class Article {
public static void GET(String articleId) {
// ...
}
}
И я перебираю каждый класс после разделения URLсопоставляя каждую команду с каждым классом (или подклассом), начиная с класса API.До тех пор, пока я не достигну конца разделенного URL-адреса, любые несоответствия сохраняются в отдельном списке как переменные.
Для приведенного выше примера процесс выглядит следующим образом:
Разделение URL-адреса каждый слеш(игнорируя базовый домен)
/news/article/1105
List<String> stringList = [
news,
article,
1105
];
Выполните итерацию каждого элемента в разделенном списке и сопоставьте вновь структурированные классы API (ниже приведен лишь пример примера, это не 100% от того, что я в настоящее время реализую):
List<String> variableList = new ArrayList<>();
Class lastClass = API.class;
for (String stringItem : stringList) {
if ((lastClass = classHasSubClass(lastClass, stringItem)) != null) {
continue;
}
variableList.add(stringItem);
}
Как только достигнут конец списка, я проверяю, содержит ли последний класс метод запроса (в данном случае GET
), и вызываю вместе со списком переменных.
Как я уже говорил ранее, это работает совершенно нормально, но при этом все классы становятся доступными напрямую, и в результате к ним могут обращаться напрямую и неправильно все, кто работает над проектом, поэтому я пытаюсь сделать иерархию более содержательной.
Я хочу сохранить возможность доступа к методам также через иерархию, поэтому все еще возможно следующее:
API.News.Article.GET(42334);
Хотя в то же время я не хочу, чтобы было возможно сделать также следующее:
AbstractArticle.GET(42334);
Я попытался превратить каждый подкласс в поле экземпляра класса вместо
public class API {
// this one is static on purpose to avoid having to instantiate
// the API class before accessing its fields
public static final AbstractNews News = new AbstractNews();
}
public class AbstractNews {
public final AbstractArticle Article = new AbstractArticle();
}
public class Article {
public void GET(String articleId) {
// ...
}
}
Это хорошо работает для двух моментов, которые я хотел достичь ранее, однако я не могу найти способ итерации полей класса таким образом, чтобы я мог правильно вызывать финальные методы.
Для предыдущей логики все, что мне нужно было повторить, было следующее:
private static Class classHasSubClass(Class<?> currentClass, String fieldName) {
Class[] classes;
classes = currentClass.getClasses();
for (final Class classItem : classes) {
if (classItem.getSimpleName().toLowerCase().equals(fieldName)) {
return classItem;
}
}
return null;
}
Но для второй логической попытки с полями я не смог правильно вызвать последний метод, вероятно, потому что полученная логика была вфакт, пытающийся сделать следующее:
AbstractArticle.GET(42334);
Вместо
API.News.Article.GET(42334);
Я подозреваю, что это потому, что первый параметр метода invoke
больше не может быть null
, как яделал раньше и должен быть правильным эквивалентом API.News.Article.GET(42334);
Есть ли способ сделать эту работу или есть лучший / другой способ сделать это?