/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package platform.independent.streamformat;
import avt.lang.table.*;
public service StreamFormatManager(Object)
{
public static MIMETypeInfo[] supportedMIMETypes() {
int storageLength = 0;
KeyValueTable storage = new KeyValueTable();
for(String packPrefix = "platform.independent.streamformat.", int packPrefixLength = packPrefix.length, Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0; )
{
Package pack = packs[packIndex];
String packName = pack.canonicalName;
if(packName != null && packName.startsWith(packPrefix))
{
int dotPosition = (packName = packName.substring(packPrefixLength)).indexOf('.');
if(dotPosition >= 0) packName = packName.substring(0, dotPosition);
for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
{
Class type = types[typeIndex];
if((type.isClass() && !type.isArray() || type.isService()) && !type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC)
{
boolean isCodec = DataCodec.class.isAssignableFrom(type);
boolean isEncoder = DataEncoder.class.isAssignableFrom(type);
boolean isDecoder = DataDecoder.class.isAssignableFrom(type);
if(isCodec || isEncoder || isDecoder)
{
String mimeType = (new StringBuilder() + packName + '/' + toSubtype(type.simpleName)).toString();
boolean[] supported = (boolean[]) storage[mimeType];
if(supported == null)
{
storage[mimeType] = new boolean[] { isDecoder, isEncoder, isCodec };
storageLength++;
} else
{
supported[0] |= isDecoder;
supported[1] |= isEncoder;
supported[2] |= isCodec;
}
}
}
}
}
}
MIMETypeInfo[] mimeTypes = new MIMETypeInfo[storageLength];
Enumeration kve = storage.enumerate();
if(kve != null)
{
int mimeTypeIndex = 0;
do
{
String mimeType = (String) kve.key;
boolean[] supported = (boolean[]) kve.value;
mimeTypes[mimeTypeIndex++] = new MIMETypeInfo(mimeType, supported[0], supported[1], supported[2]);
} while(kve.findNext());
}
return mimeTypes;
}
public static MIMETypeInfo getMIMETypeInfo(String mimeType) {
if(mimeType == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "mimeType" }));
}
int solidusPosition = mimeType.indexOf('/');
if(solidusPosition < 0)
{
throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.mime-type.solidus"), new Object[] { "mimeType" }));
}
boolean isCodec = false;
boolean isEncoder = false;
boolean isDecoder = false;
for(
String packPrefix = (new StringBuilder() + "platform.independent.streamformat." + mimeType.substring(0, solidusPosition) + '.').toString(), int packPrefixLength = packPrefix.length,
String subtype = mimeType.substring(solidusPosition + 1), Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0;
)
{
Package pack = packs[packIndex];
String packName = pack.canonicalName;
if(packName != null && packName.startsWith(packPrefix)) for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
{
Class type = types[typeIndex];
if((type.isClass() && !type.isArray() || type.isService()) && !type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC && toSubtype(type.simpleName).equals(subtype))
{
isCodec |= DataCodec.class.isAssignableFrom(type);
isEncoder |= DataEncoder.class.isAssignableFrom(type);
isDecoder |= DataDecoder.class.isAssignableFrom(type);
}
}
}
return !(isCodec || isEncoder || isDecoder) ? null : new MIMETypeInfo(mimeType, isDecoder, isEncoder, isCodec);
}
public static DataCodec createCodec(String mimeType) throws DataConverterNotFoundException, StreamFormatNotFoundException, InstantiationException, IllegalAccessException {
if(mimeType == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "mimeType" }));
}
int solidusPosition = mimeType.indexOf('/');
if(solidusPosition < 0)
{
throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.mime-type.solidus"), new Object[] { "mimeType" }));
}
boolean isCodec = false;
boolean isEncoder = false;
boolean isDecoder = false;
for(
String packPrefix = (new StringBuilder() + "platform.independent.streamformat." + mimeType.substring(0, solidusPosition) + '.').toString(), int packPrefixLength = packPrefix.length,
String subtype = mimeType.substring(solidusPosition + 1), Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0;
)
{
Package pack = packs[packIndex];
String packName = pack.canonicalName;
if(packName != null && packName.startsWith(packPrefix)) for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
{
Class type = types[typeIndex];
if((type.isClass() && !type.isArray() || type.isService()) && !type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC && toSubtype(type.simpleName).equals(subtype))
{
isCodec |= DataCodec.class.isAssignableFrom(type);
isEncoder |= DataEncoder.class.isAssignableFrom(type);
isDecoder |= DataDecoder.class.isAssignableFrom(type);
if(isCodec) return (DataCodec) type.newInstance();
}
}
}
if(!(isCodec || isEncoder || isDecoder))
{
throw new StreamFormatNotFoundException(String.format(package.getResourceString("not-found.stream-format"), new Object[] { mimeType }));
}
throw new DataConverterNotFoundException(package.getResourceString("not-found.data-converter.codec")) { mimeType = mimeType };
}
public static DataEncoder createEncoder(String mimeType) throws DataConverterNotFoundException, StreamFormatNotFoundException, InstantiationException, IllegalAccessException {
if(mimeType == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "mimeType" }));
}
int solidusPosition = mimeType.indexOf('/');
if(solidusPosition < 0)
{
throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.mime-type.solidus"), new Object[] { "mimeType" }));
}
boolean isCodec = false;
boolean isEncoder = false;
boolean isDecoder = false;
for(
String packPrefix = (new StringBuilder() + "platform.independent.streamformat." + mimeType.substring(0, solidusPosition) + '.').toString(), int packPrefixLength = packPrefix.length,
String subtype = mimeType.substring(solidusPosition + 1), Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0;
)
{
Package pack = packs[packIndex];
String packName = pack.canonicalName;
if(packName != null && packName.startsWith(packPrefix)) for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
{
Class type = types[typeIndex];
if((type.isClass() && !type.isArray() || type.isService()) && !type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC && toSubtype(type.simpleName).equals(subtype))
{
isCodec |= DataCodec.class.isAssignableFrom(type);
isEncoder |= DataEncoder.class.isAssignableFrom(type);
isDecoder |= DataDecoder.class.isAssignableFrom(type);
if(isEncoder) return (DataEncoder) type.newInstance();
}
}
}
if(!(isCodec || isEncoder || isDecoder))
{
throw new StreamFormatNotFoundException(String.format(package.getResourceString("not-found.stream-format"), new Object[] { mimeType }));
}
throw new DataConverterNotFoundException(package.getResourceString("not-found.data-converter.encoder")) { mimeType = mimeType };
}
public static DataDecoder createDecoder(String mimeType) throws DataConverterNotFoundException, StreamFormatNotFoundException, InstantiationException, IllegalAccessException {
if(mimeType == null)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "mimeType" }));
}
int solidusPosition = mimeType.indexOf('/');
if(solidusPosition < 0)
{
throw new IllegalArgumentException(String.format(package.getResourceString("illegal-argument.mime-type.solidus"), new Object[] { "mimeType" }));
}
boolean isCodec = false;
boolean isEncoder = false;
boolean isDecoder = false;
for(
String packPrefix = (new StringBuilder() + "platform.independent.streamformat." + mimeType.substring(0, solidusPosition) + '.').toString(), int packPrefixLength = packPrefix.length,
String subtype = mimeType.substring(solidusPosition + 1), Package[] packs = Package.enumerate(), int packIndex = packs.length; packIndex-- > 0;
)
{
Package pack = packs[packIndex];
String packName = pack.canonicalName;
if(packName != null && packName.startsWith(packPrefix)) for(Class[] types = pack.enumerateTypes(), int typeIndex = types.length; typeIndex-- > 0; )
{
Class type = types[typeIndex];
if((type.isClass() && !type.isArray() || type.isService()) && !type.isAbstract() && type.visibility >= ReflectiveObject.PUBLIC && toSubtype(type.simpleName).equals(subtype))
{
isCodec |= DataCodec.class.isAssignableFrom(type);
isEncoder |= DataEncoder.class.isAssignableFrom(type);
isDecoder |= DataDecoder.class.isAssignableFrom(type);
if(isDecoder) return (DataDecoder) type.newInstance();
}
}
}
if(!(isCodec || isEncoder || isDecoder))
{
throw new StreamFormatNotFoundException(String.format(package.getResourceString("not-found.stream-format"), new Object[] { mimeType }));
}
throw new DataConverterNotFoundException(package.getResourceString("not-found.data-converter.decoder")) { mimeType = mimeType };
}
private static String toSubtype(String simpleName) {
StringBuilder result = new StringBuilder();
for(int length = simpleName.length, String prev = null, int beginIndex = 0; beginIndex < length; )
{
int endIndex = beginIndex + 1;
for(char chr; endIndex < length && ((chr = simpleName[endIndex]) >= '0' && chr <= '9' || chr >= 'a' && chr <= 'z'); endIndex++);
String word = simpleName.substring(beginIndex, endIndex);
if(!("Encoder".equals(word) || "Decoder".equals(word) || "Codec".equals(word)))
{
if("Plus".equals(word))
{
result + '+';
}
else if("_".equals(word))
{
result + '.';
}
else
{
if(prev != null && !("Plus".equals(prev) || "_".equals(prev))) result + '-';
result + word.toLowerCase();
}
}
prev = word;
beginIndex = endIndex;
}
return result.toString();
}
}