/** * Copyright (C) 2015 drrb * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program 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 General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package com.github.drrb.rust.netbeans.indexing; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.netbeans.modules.parsing.spi.indexing.support.IndexDocument; import org.netbeans.modules.parsing.spi.indexing.support.IndexResult; /** * */ public class IndexItemSerializer { private static final Logger LOGGER = Logger.getLogger(IndexItemSerializer.class.getName()); public <T> T deserialize(IndexResult indexResult, Class<T> type) { Map<Field, IndexedString> annotatedStringFields = getAnnotatedFields(type, IndexedString.class); Map<Field, IndexedFile> annotatedFileFields = getAnnotatedFields(type, IndexedFile.class); T object = instantiate(type); for (Map.Entry<Field, IndexedString> entry : annotatedStringFields.entrySet()) { Field field = entry.getKey(); IndexedString mapping = entry.getValue(); String value = indexResult.getValue(mapping.value()); setValueAsString(field, object, value); } for (Map.Entry<Field, IndexedFile> entry : annotatedFileFields.entrySet()) { Field field = entry.getKey(); setValue(field, object, indexResult.getFile()); } return object; } public void serialize(IndexDocument document, Object object) { Class<? extends Object> type = object.getClass(); Map<Field, IndexedString> annotatedFields = getAnnotatedFields(type, IndexedString.class); for (Map.Entry<Field, IndexedString> entry : annotatedFields.entrySet()) { Field field = entry.getKey(); IndexedString mapping = entry.getValue(); String fieldValue = getFieldValueAsString(field, object); LOGGER.log(Level.WARNING, "Adding ''{0}'' = ''{1}'' to index", new Object[]{mapping.value(), fieldValue}); document.addPair(mapping.value(), fieldValue, true, true); } } private String getFieldValueAsString(Field field, Object object) { try { Object value = field.get(object); return value.toString(); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(String.format("Couldn't serialize class '%s' to index. (Couldn't get value of field '%s')", object.getClass().getName(), field.getName()), ex); } } private void setValueAsString(Field field, Object object, String valueString) { try { Class<?> type = field.getType(); Object value = coerceStringToType(valueString, type); field.set(object, value); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(String.format("Couldn't deserialize class '%s' from index. (Couldn't set value of field '%s' to '%s')", object.getClass().getName(), field.getName(), valueString), ex); } } private void setValue(Field field, Object object, Object value) { try { field.set(object, value); } catch (IllegalArgumentException | IllegalAccessException ex) { throw new RuntimeException(String.format("Couldn't deserialize class '%s' from index. (Couldn't set value of field '%s' to '%s')", object.getClass().getName(), field.getName(), value), ex); } } private Object coerceStringToType(String string, Class<?> type) { if (type == String.class) { return string; } else if (type == int.class || type == Integer.class) { return Integer.valueOf(string); } else { throw new IllegalArgumentException(String.format("Couldn't coerce '%s' to a '%s'", string, type.getName())); } } private <T> T instantiate(Class<T> type) { try { return type.newInstance(); } catch (InstantiationException | IllegalAccessException ex) { throw new RuntimeException(String.format("Couldn't deserialize class '%s'. (Couldn't instantiated class)", type.getName()), ex); } } private <T extends Annotation> Map<Field, T> getAnnotatedFields(Class<?> type, Class<T> annotationType) { Field[] fields = type.getDeclaredFields(); Map<Field, T> annotatedFields = new HashMap<>(fields.length); for (Field field : fields) { if (field.isAnnotationPresent(annotationType)) { if (!field.isAccessible()) { field.setAccessible(true); } annotatedFields.put(field, field.getAnnotation(annotationType)); } } return annotatedFields; } public String[] getKeys(Class<?> indexedType) { Map<Field, IndexedString> annotatedFields = getAnnotatedFields(indexedType, IndexedString.class); String[] keys = new String[annotatedFields.size()]; Collection<IndexedString> keyMappings = annotatedFields.values(); int i = 0; for (Iterator<IndexedString> it = keyMappings.iterator(); it.hasNext();) { IndexedString keyMapping = it.next(); keys[i] = keyMapping.value(); i++; } return keys; } }