Java tutorial
/** * * JabRef Bibsonomy Plug-in - Plugin for the reference management * software JabRef (http://jabref.sourceforge.net/) * to fetch, store and delete entries from BibSonomy. * * Copyright (C) 2008 - 2011 Knowledge & Data Engineering Group, * University of Kassel, Germany * http://www.kde.cs.uni-kassel.de/ * * 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** * */ package org.bibsonomy.plugin.jabref.util; import static org.bibsonomy.util.ValidationUtils.present; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import net.sf.jabref.BibtexEntry; import net.sf.jabref.BibtexEntryType; import net.sf.jabref.Globals; import net.sf.jabref.JabRefPreferences; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bibsonomy.model.BibTex; import org.bibsonomy.model.Group; import org.bibsonomy.model.Post; import org.bibsonomy.model.Resource; import org.bibsonomy.model.Tag; import org.bibsonomy.model.User; import org.bibsonomy.model.util.PersonNameParser.PersonListParserException; import org.bibsonomy.model.util.PersonNameUtils; import org.bibsonomy.util.ExceptionUtils; /** * Converts between BibSonomy's and JabRef's BibTeX model. * * @author Waldemar Biller <wbi@cs.uni-kassel.de> * @version $Id: JabRefModelConverter.java,v 1.4 2011-05-04 08:21:51 dbe Exp $ * */ public class JabRefModelConverter { private static final Log log = LogFactory.getLog(JabRefModelConverter.class); private static final Set<String> EXCLUDE_FIELDS = new HashSet<String>(Arrays.asList(new String[] { "abstract", // added // separately "bibtexAbstract", // added separately "bibtexkey", "entrytype", // added at beginning of entry "misc", // contains several fields; handled separately "month", // handled separately "openURL", // not added "simHash0", // not added "simHash1", // not added "simHash2", // not added "simHash3", // not added "description", "keywords", "comment", "id" })); /** * date's in JabRef are stored as strings, in BibSonomy as Date objects. We * have to supply two formats - the first is the one which exists when * having downloaded entries from BibSonomy, the second one when entries * were created from scratch within JabRef. */ private static final SimpleDateFormat bibsonomyDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); private static final SimpleDateFormat jabrefDateFormat = new SimpleDateFormat("yyyy.MM.dd"); /** * separates tags */ private static final String jabRefKeywordSeparator = JabRefPreferences.getInstance() .get("groupKeywordSeparator", ", "); /** * Converts a list of posts in BibSonomy's format into JabRef's format. * * @param posts * - a list of posts in BibSonomy's data model * @return A list of posts in JabRef's data model. */ public static List<BibtexEntry> convertPosts(final List<Post<? extends Resource>> posts) { final List<BibtexEntry> entries = new ArrayList<BibtexEntry>(); for (final Post<? extends Resource> post : posts) { entries.add(convertPost(post)); } return entries; } /** * Converts a BibSonomy post into a JabRef BibtexEntry * * @param post * @return */ public static BibtexEntry convertPost(final Post<? extends Resource> post) { try { // what we have final BibTex bibtex = (BibTex) post.getResource(); // what we want final BibtexEntry entry = new BibtexEntry(); /* * each entry needs an ID (otherwise we get a NPE) ... let JabRef * generate it */ copyStringProperties(entry, bibtex); entry.setField("author", PersonNameUtils.serializePersonNames(bibtex.getAuthor())); entry.setField("editor", PersonNameUtils.serializePersonNames(bibtex.getEditor())); /* * convert entry type (Is never null but getType() returns null for * unknown types and JabRef knows less types than we.) * * FIXME: a nicer solution would be to implement the corresponding * classes for the missing entrytypes. */ final BibtexEntryType entryType = BibtexEntryType.getType(bibtex.getEntrytype()); entry.setType(entryType == null ? BibtexEntryType.OTHER : entryType); copyMiscProperties(entry, bibtex); copyMonth(entry, bibtex); final String bibAbstract = bibtex.getAbstract(); if (present(bibAbstract)) entry.setField("abstract", bibAbstract); copyTags(entry, post); copyGroups(entry, post); // set comment + description final String description = post.getDescription(); if (present(description)) { entry.setField("description", post.getDescription()); entry.setField("comment", post.getDescription()); } if (present(post.getDate())) { entry.setField("timestamp", bibsonomyDateFormat.format(post.getDate())); } if (present(post.getUser())) entry.setField("username", post.getUser().getName()); return entry; } catch (final Exception e) { log.error("Could not convert BibSonomy post into a JabRef BibTeX entry.", e); } return null; } public static void copyGroups(final BibtexEntry entry, final Post<? extends Resource> post) { // set groups - will be used in jabref when exporting to bibsonomy if (present(post.getGroups())) { final Set<Group> groups = post.getGroups(); final StringBuffer groupsBuffer = new StringBuffer(); for (final Group group : groups) groupsBuffer.append(group.getName() + " "); final String groupsBufferString = groupsBuffer.toString().trim(); if (present(groupsBufferString)) entry.setField("groups", groupsBufferString); } } public static void copyTags(final BibtexEntry entry, final Post<? extends Resource> post) { /* * concatenate tags using the JabRef keyword separator */ final Set<Tag> tags = post.getTags(); final StringBuffer tagsBuffer = new StringBuffer(); for (final Tag tag : tags) { tagsBuffer.append(tag.getName() + jabRefKeywordSeparator); } /* * remove last separator */ if (!tags.isEmpty()) { tagsBuffer.delete(tagsBuffer.lastIndexOf(jabRefKeywordSeparator), tagsBuffer.length()); } final String tagsBufferString = tagsBuffer.toString(); if (present(tagsBufferString)) entry.setField("keywords", tagsBufferString); } public static void copyMonth(final BibtexEntry entry, final BibTex bibtex) { final String month = bibtex.getMonth(); if (present(month)) { /* * try to convert the month abbrev like JabRef does it */ final String longMonth = Globals.MONTH_STRINGS.get(month); if (present(longMonth)) { entry.setField("month", longMonth); } else { entry.setField("month", month); } } } public static void copyMiscProperties(final BibtexEntry entry, final BibTex bibtex) { if (present(bibtex.getMisc()) || present(bibtex.getMiscFields())) { // parse the misc fields and loop over them bibtex.parseMiscField(); /* * FIXME: if the misc field erroneously contains the intrahash, it * is overwriting the correct one, which is set above! */ if (bibtex.getMiscFields() != null) for (final String key : bibtex.getMiscFields().keySet()) { if ("id".equals(key)) { // id is used by jabref entry.setField("misc_id", bibtex.getMiscField(key)); continue; } if (key.startsWith("__")) // ignore fields starting with // __ - jabref uses them for // control continue; entry.setField(key, bibtex.getMiscField(key)); } } } protected static void copyStringProperties(BibtexEntry entry, BibTex bibtex) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { /* * we use introspection to get all fields ... */ final BeanInfo info = Introspector.getBeanInfo(bibtex.getClass()); final PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); /* * iterate over all properties */ for (final PropertyDescriptor pd : descriptors) { final Method getter = pd.getReadMethod(); // loop over all String attributes final Object o = getter.invoke(bibtex, (Object[]) null); if (String.class.equals(pd.getPropertyType()) && (o != null) && !JabRefModelConverter.EXCLUDE_FIELDS.contains(pd.getName())) { final String value = ((String) o); if (present(value)) { entry.setField(pd.getName().toLowerCase(), value); } } } } /** * Convert a JabRef BibtexEntry into a BibSonomy post * * @param entry * @return */ public static Post<BibTex> convertEntry(final BibtexEntry entry) { final Post<BibTex> post = new Post<BibTex>(); final BibTex bibtex = new BibTex(); post.setResource(bibtex); bibtex.setMisc(""); final List<String> knownFields = copyStringPropertiesToBibsonomyModel(bibtex, entry); try { bibtex.setAuthor(PersonNameUtils.discoverPersonNames(entry.getField("author"))); bibtex.setEditor(PersonNameUtils.discoverPersonNames(entry.getField("editor"))); } catch (PersonListParserException e) { ExceptionUtils.logErrorAndThrowRuntimeException(log, e, "Could not convert person names"); } knownFields.add("author"); knownFields.add("editor"); // add unknown Properties to misc for (final String field : entry.getAllFields()) { if (!knownFields.contains(field) && !JabRefModelConverter.EXCLUDE_FIELDS.contains(field) && !field.startsWith("__")) { bibtex.addMiscField(field, entry.getField(field)); } } bibtex.serializeMiscFields(); // set the key bibtex.setBibtexKey(StringUtil.toUTF8(entry.getCiteKey())); bibtex.setEntrytype(StringUtil.toUTF8(entry.getType().getName().toLowerCase())); // set the date of the post final String timestamp = StringUtil.toUTF8(entry.getField("timestamp")); if (present(timestamp)) { try { post.setDate(bibsonomyDateFormat.parse(timestamp)); } catch (ParseException ex) { log.debug("Could not parse BibSonomy date format - trying JabrefDateFormat..."); } try { post.setDate(jabrefDateFormat.parse(timestamp)); } catch (ParseException ex) { log.debug("Could not parse Jabref date format - set date to NULL"); post.setDate(null); // this is null anyway, but just to make // it clear } } final String abstractt = StringUtil.toUTF8(entry.getField("abstract")); if (present(abstractt)) bibtex.setAbstract(abstractt); final String keywords = StringUtil.toUTF8(entry.getField("keywords")); if (present(keywords)) { for (String keyword : keywords.split(jabRefKeywordSeparator)) { post.addTag(keyword); } } if (present(entry.getField("username"))) post.setUser(new User(StringUtil.toUTF8(entry.getField("username")))); // Set the groups if (present(entry.getField("groups"))) { final String[] groupsArray = entry.getField("groups").split(" "); final Set<Group> groups = new HashSet<Group>(); for (final String group : groupsArray) groups.add(new Group(StringUtil.toUTF8(group))); post.setGroups(groups); } final String description = StringUtil.toUTF8(entry.getField("description")); if (present(description)) post.setDescription(description); final String comment = StringUtil.toUTF8(entry.getField("comment")); if (present(comment)) post.setDescription(comment); final String month = StringUtil.toUTF8(entry.getField("month")); if (present(month)) bibtex.setMonth(month); return post; } /** * @param bibtex * target object * @param entry * source object * @return list of all copied property names */ public static List<String> copyStringPropertiesToBibsonomyModel(final BibTex bibtex, final BibtexEntry entry) { final List<String> knownFields = new ArrayList<String>(50); final BeanInfo info; try { info = Introspector.getBeanInfo(bibtex.getClass()); } catch (IntrospectionException e) { ExceptionUtils.logErrorAndThrowRuntimeException(log, e, "could not introspect"); return knownFields; } final PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); // set all known properties of the BibTex for (PropertyDescriptor pd : descriptors) { if (String.class.equals(pd.getPropertyType()) == false) { continue; } if (present(entry.getField((pd.getName().toLowerCase()))) && !JabRefModelConverter.EXCLUDE_FIELDS.contains(pd.getName().toLowerCase())) { final Object value = entry.getField(pd.getName().toLowerCase()); try { pd.getWriteMethod().invoke(bibtex, value); } catch (Exception e) { ExceptionUtils.logErrorAndThrowRuntimeException(log, e, "could not convert property " + pd.getName()); return knownFields; } knownFields.add(pd.getName()); } } return knownFields; } }