package org.fluxtream.core.connectors.vos; import org.fluxtream.core.OutsideTimeBoundariesException; import org.fluxtream.core.TimeInterval; import org.fluxtream.core.connectors.Connector; import org.fluxtream.core.connectors.ObjectType; import org.fluxtream.core.connectors.annotations.ObjectTypeSpec; import org.fluxtream.core.domain.AbstractFacet; import org.fluxtream.core.domain.GuestSettings; import org.fluxtream.core.utils.SecurityUtils; import org.fluxtream.core.utils.TimeUtils; import org.joda.time.DateTimeZone; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.*; public abstract class AbstractFacetVO<T extends AbstractFacet> { public String type; public String description; public long id; public Boolean isEmpty = false; public String comment; public final SortedSet<String> tags = new TreeSet<String>(); public String subType; public String ogLink; public transient int api; public transient int objectType; public String date; /** * Thread-safe cache for vo classes */ private static Hashtable<String, Class<? extends AbstractFacetVO<? extends AbstractFacet>>> voClasses; private static Hashtable<Class<? extends AbstractFacet>,String> objectTypeNames; static { voClasses = new Hashtable<String, Class<? extends AbstractFacetVO<? extends AbstractFacet>>>(); objectTypeNames = new Hashtable<Class<? extends AbstractFacet>, String>(); } public void extractValues(T facet, TimeInterval timeInterval, GuestSettings settings) throws OutsideTimeBoundariesException { getType(facet); this.id = facet.getId(); this.api = facet.api; this.objectType = facet.objectType; if (facet.comment!=null&&!facet.comment.equals("")) { if (SecurityUtils.isDemoUser()) this.comment = "***demo - comment hidden***"; else { try { this.comment = new String(facet.comment.getBytes(), "utf-8"); } catch (UnsupportedEncodingException e) {} } } if (facet.hasTags()) { if (!SecurityUtils.isDemoUser()) { tags.addAll(facet.getTagsAsStrings()); } } // Set default date which subclasses can overwrite if they want to DateTimeZone zone = DateTimeZone.forTimeZone(timeInterval.getTimeZone(facet.start)); this.date = TimeUtils.dateFormatter.withZone(zone).print(facet.start); fromFacet(facet, timeInterval, settings); ResourceBundle res = ResourceBundle.getBundle("facetSharing"); final ArrayList<String> openGraphSharableFacets = new ArrayList(Arrays.asList(res.getString("opengraph").split(","))); final Connector connector = Connector.fromValue(facet.api); String facetName = String.format("%s.%s", connector.getName(), ObjectType.getObjectType(connector, facet.objectType)); if (openGraphSharableFacets.contains(facetName)&&isShareable(facet)) { String encryptedUrl = settings.config.encrypt(String.format("%s/%s/%s", facet.api, facet.objectType, String.valueOf(id))); try { encryptedUrl = URLEncoder.encode(encryptedUrl, "UTF-8"); } catch (UnsupportedEncodingException e) {} ogLink = String.format("%sopenGraph/%s.html", settings.config.get("homeBaseUrl"), encryptedUrl); } } protected boolean isShareable(T facet) { return true; } /** * Returns a copy of this VO's set of tags. Assumes {@link #extractValues} has already been called. Guaranteed to * not return <code>null</code>, but may return an empty {@link SortedSet}. */ public SortedSet<String> getTags() { return new TreeSet<String>(tags); } protected void getType(T facet) { Connector connector = Connector.fromValue(facet.api); this.type = connector.getName(); if (facet.objectType != -1) { final String objectTypeName = getObjectTypeName(facet); this.type += "-" + objectTypeName; } this.subType = getSubtype(facet); if (subType!=null) this.type += "-" + subType; } protected String getObjectTypeName(T facet) { if (objectTypeNames.containsKey(facet.getClass())) return objectTypeNames.get(facet.getClass()); String objectTypeName = facet.getClass().getAnnotation(ObjectTypeSpec.class).name(); objectTypeNames.put(facet.getClass(), objectTypeName); return objectTypeName; } protected String getSubtype(T facet) { return null; } protected abstract void fromFacet(T facet, TimeInterval timeInterval, GuestSettings settings) throws OutsideTimeBoundariesException; public static int toMinuteOfDay(java.util.Date date, TimeZone tz) { if (date == null) return 0; Calendar c = new GregorianCalendar(tz); c.setTime(date); int startMinute = c.get(Calendar.HOUR_OF_DAY) * 60 + c.get(Calendar.MINUTE); return startMinute; } /** * We return a corresponding class to extract a value object from * a facet, using a naming convention: MyFacet becomes MyFacetVO * @param facet * @return * @throws ClassNotFoundException */ @SuppressWarnings("unchecked") public static <T extends AbstractFacet> Class<? extends AbstractFacetVO<T>> getFacetVOClass( T facet) throws ClassNotFoundException { try { String name = facet.getClass().getName(); if (voClasses.get(name) == null) { String namePrefix = name.substring(0, name.length() - 5); String jsonFacetClassName = namePrefix + "FacetVO"; voClasses.put(name, (Class<? extends AbstractFacetVO<T>>) Class .forName(jsonFacetClassName)); } Class<? extends AbstractFacetVO<? extends AbstractFacet>> voClass = voClasses .get(name); return (Class<? extends AbstractFacetVO<T>>) voClass; } catch (ClassNotFoundException e) { // logger.generalError("Could not find corresponding \"FacetVO\" class for " // + facet.getClass().getName()); throw e; } } protected static final float round(float v, int decimals) { float mul = (float)Math.pow(10, decimals); return (float) Math.round(v * mul) / mul; } protected static final double round(double v, int decimals) { double mul = Math.pow(10, decimals); return Math.round(v * mul) / mul; } }