001package ezvcard.util; 002 003import java.lang.reflect.Field; 004import java.lang.reflect.Modifier; 005import java.util.Arrays; 006 007import ezvcard.SupportedVersions; 008import ezvcard.VCardVersion; 009 010/* 011 Copyright (c) 2012-2026, Michael Angstadt 012 All rights reserved. 013 014 Redistribution and use in source and binary forms, with or without 015 modification, are permitted provided that the following conditions are met: 016 017 1. Redistributions of source code must retain the above copyright notice, this 018 list of conditions and the following disclaimer. 019 2. Redistributions in binary form must reproduce the above copyright notice, 020 this list of conditions and the following disclaimer in the documentation 021 and/or other materials provided with the distribution. 022 023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 024 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 026 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 027 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 030 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 033 034 The views and conclusions contained in the software and documentation are those 035 of the authors and should not be interpreted as representing official policies, 036 either expressed or implied, of the FreeBSD Project. 037 */ 038 039/** 040 * Provides methods for getting the value of the {@link SupportedVersions} 041 * annotation for "public static" fields. 042 * @author Michael Angstadt 043 */ 044public class SupportedVersionsHelper { 045 /** 046 * Gets the vCard versions that are defined by the given object's 047 * {@link SupportedVersions} annotation. 048 * @param obj the object, must be "public static" 049 * @return the versions in the annotation, all versions if the annotation is 050 * not present, or all versions if the object is not a public static field 051 * of its class 052 */ 053 public static VCardVersion[] getSupportedVersions(Object obj) { 054 //@formatter:off 055 return Arrays.stream(obj.getClass().getFields()) 056 .filter(SupportedVersionsHelper::isFieldStatic) 057 .filter(field -> isFieldMe(field, obj)) 058 .map(field -> field.getAnnotation(SupportedVersions.class)) 059 .map(annotation -> (annotation == null) ? VCardVersion.values() : annotation.value()) 060 .findFirst().orElseGet(VCardVersion::values); 061 //@formatter:on 062 } 063 064 private static boolean isFieldStatic(Field field) { 065 return Modifier.isStatic(field.getModifiers()); 066 } 067 068 private static boolean isFieldMe(Field field, Object obj) { 069 Object fieldValue; 070 try { 071 fieldValue = field.get(null); 072 } catch (IllegalArgumentException e) { 073 //should never be thrown because we check for the static modified 074 return false; 075 } catch (IllegalAccessException e) { 076 //if the field is not accessible 077 return false; 078 } 079 080 return fieldValue == obj; 081 } 082 083 /** 084 * Determines if this object is supported by the given vCard version. Uses 085 * the object's {@link SupportedVersions} annotation. 086 * @param version the vCard version 087 * @param obj the object 088 * @return true if it is supported, false if not 089 */ 090 public static boolean isSupportedBy(VCardVersion version, Object obj) { 091 return Arrays.stream(getSupportedVersions(obj)).anyMatch(supportedVersion -> supportedVersion == version); 092 } 093 094 private SupportedVersionsHelper() { 095 //hide 096 } 097}