/** * This class is responsible for updating chart value of extension chart elements. * * @since 3.7 */ public class ChartExtensionValueUpdater { private ILogger logger = Logger.getLogger("org.eclipse.birt.chart.engine/trace"); // $NON-NLS-1$ /** This set identifies which elements has visible attribute. */ private static Set<String> hasVisibleElementSet = new HashSet<String>(); static { hasVisibleElementSet.add(LineAttributes.class.getSimpleName()); hasVisibleElementSet.add(Marker.class.getSimpleName()); hasVisibleElementSet.add(Label.class.getSimpleName()); hasVisibleElementSet.add(Series.class.getSimpleName()); hasVisibleElementSet.add(Block.class.getSimpleName()); hasVisibleElementSet.add(ClientArea.class.getSimpleName()); } /** * Returns <code>true</code> if specified class contains 'visible' attribute. * * @param clazz * @return */ static boolean contanisVisibleElement(EClass clazz) { boolean contains = hasVisibleElementSet.contains(clazz.getName()); if (contains) { return true; } EList<EClass> supers = clazz.getEAllSuperTypes(); if (supers.size() > 0) { for (EClass eSuper : supers) { contains = hasVisibleElementSet.contains(eSuper.getName()); if (contains) { return true; } } } return contains; } public static boolean isMapEntry(EClass eClass) { return (eClass.getInstanceClass() == Map.Entry.class); } @SuppressWarnings({"unchecked", "rawtypes"}) private void updateAttrs( EClass eClass, EObject eParentObj, EObject eObj, EObject eRef, EObject eDef) { List<EAttribute> listMany = new LinkedList<EAttribute>(); List<EAttribute> list = new LinkedList<EAttribute>(); for (EAttribute eAttr : eClass.getEAllAttributes()) { if (eAttr.isMany()) { listMany.add(eAttr); } else { list.add(eAttr); } } for (EAttribute eAttr : listMany) { List<?> vList = (List<?>) eObj.eGet(eAttr); if (vList.size() == 0) { if (eRef != null && ((List<?>) eRef.eGet(eAttr)).size() > 0) { vList.addAll((List) eRef.eGet(eAttr)); } else if (eDef != null) { vList.addAll((List) eDef.eGet(eAttr)); } } } for (EAttribute eAttr : list) { Object val = eObj.eGet(eAttr); if (eAttr.isUnsettable()) { if (!eObj.eIsSet(eAttr)) { if (eRef != null && eRef.eIsSet(eAttr)) { eObj.eSet(eAttr, eRef.eGet(eAttr)); } else if (eDef != null && eDef.eIsSet(eAttr)) { eObj.eSet(eAttr, eDef.eGet(eAttr)); } } } else if (val == null) { if (eRef != null && eRef.eGet(eAttr) != null) { eObj.eSet(eAttr, eRef.eGet(eAttr)); } else if (eDef != null) { eObj.eSet(eAttr, eDef.eGet(eAttr)); } } } } /** * Updates chart element object. * * @param expected class of expected chart element. * @param name chart element name * @param eParentObj container of chart element object. * @param eObj chart element object. * @param eRef reference chart object to be used to update chart object's values. * @param eDef default chart object to be used to update chart object's values. */ public void update( EClass expected, String name, EObject eParentObj, EObject eObj, EObject eRef, EObject eDef) { if (eObj == null) { if (eRef != null) { if (eRef instanceof IChartObject) { eObj = ((IChartObject) eRef).copyInstance(); ChartElementUtil.setEObjectAttribute(eParentObj, name, eObj, false); } } else if (eDef != null) { if (eDef instanceof IChartObject) { eObj = ((IChartObject) eDef).copyInstance(); ChartElementUtil.setEObjectAttribute(eParentObj, name, eObj, false); return; } } } if (eObj == null || (eRef == null && eDef == null)) { return; } // Process visible case. if (contanisVisibleElement(eObj.eClass())) { if (eObj.eIsSet(eObj.eClass().getEStructuralFeature("visible"))) // $NON-NLS-1$ { if (eObj.eGet(eObj.eClass().getEStructuralFeature("visible")) != Boolean.TRUE) // $NON-NLS-1$ { // If the visible attribute is set to false, directly return, no need // to update other attributes. return; } } else { // If eObj isn't set visible and the visible attribute of // reference object is set to false, directly return, no need to // update other attributes. if (eRef != null && eRef.eIsSet(eRef.eClass().getEStructuralFeature("visible"))) // $NON-NLS-1$ { if (eRef.eGet(eRef.eClass().getEStructuralFeature("visible")) != Boolean.TRUE) // $NON-NLS-1$ { eObj.eSet(eRef.eClass().getEStructuralFeature("visible"), Boolean.FALSE); // $NON-NLS-1$ return; } } else if (eDef != null && eDef.eIsSet(eDef.eClass().getEStructuralFeature("visible"))) // $NON-NLS-1$ { if (eDef.eGet(eDef.eClass().getEStructuralFeature("visible")) != Boolean.TRUE) // $NON-NLS-1$ { eObj.eSet(eDef.eClass().getEStructuralFeature("visible"), Boolean.FALSE); // $NON-NLS-1$ return; } } } } EClass eClass = eObj.eClass(); // attributes updateAttrs(eClass, eParentObj, eObj, eRef, eDef); // list attributes // references for (EReference ref : eClass.getEAllReferences()) { String childName = ref.getName(); Object child = eObj.eGet(ref); Object refChild = eRef != null ? eRef.eGet(ref) : null; Object defChild = eDef != null ? eDef.eGet(ref) : null; EObject eChildParntObj = eObj; if (child == null) { if (refChild != null) { if (refChild instanceof IChartObject) { child = updateFromReference(childName, refChild, eChildParntObj); } } else if (defChild != null) { if (defChild instanceof IChartObject) { child = ((IChartObject) defChild).copyInstance(); ChartElementUtil.setEObjectAttribute(eChildParntObj, childName, child, false); continue; } } } if (child != null) { if (ref.isMany()) { int size = ((List<?>) child).size(); for (int i = 0; i < size; i++) { Object item = ((List<?>) child).get(i); Object refItem = (refChild == null || (i >= ((List<?>) refChild).size())) ? null : ((List<?>) refChild).get(i); Object defItem = (defChild == null || (i >= ((List<?>) defChild).size())) ? null : ((List<?>) defChild).get(i); update(ref, eObj, (EObject) item, (EObject) refItem, (EObject) defItem); } } else { update(ref, eObj, (EObject) child, (EObject) refChild, (EObject) defChild); } } } } protected Object updateFromReference(String childName, Object refChild, EObject eChildParntObj) { Object child = ((IChartObject) refChild).copyInstance(); ChartElementUtil.setEObjectAttribute(eChildParntObj, childName, child, false); return child; } private Map<String, EObject> defaultObjCache = new HashMap<String, EObject>(); /** * Returns a chart element instance with default value. * * @param expected * @param name * @param eObj * @return a chart element instance with default value. */ public EObject getDefault(EClass expected, String name, EObject eObj) { EObject def = defaultObjCache.get(eObj.getClass().getSimpleName()); if (def != null) { return def; } Method m; try { m = eObj.getClass().getMethod("create"); // $NON-NLS-1$ EObject object = (EObject) m.invoke(eObj); defaultObjCache.put(eObj.getClass().getSimpleName(), object); return object; } catch (SecurityException e) { logger.log(e); } catch (NoSuchMethodException e) { logger.log(e); } catch (IllegalArgumentException e) { logger.log(e); } catch (IllegalAccessException e) { logger.log(e); } catch (InvocationTargetException e) { logger.log(e); } return null; } private void update( EReference ref, EObject eParentObj, EObject eObj, EObject eRef, EObject eDef) { if (eObj != null && eObj instanceof DataPointComponent) { eDef = ChartDefaultValueUtil.getPercentileDataPointDefObj( (DataPointComponent) eObj, (DataPointComponent) eDef); } update(ref.getEReferenceType(), ref.getName(), eParentObj, eObj, eRef, eDef); } }
/** * Used as base class for Plot computation. Abstract useful methods from PlotWithAxes and * PlotWithoutAxes. */ public abstract class PlotComputation { protected static final ILogger logger = Logger.getLogger("org.eclipse.birt.chart.engine/computation"); // $NON-NLS-1$ protected static final IGObjectFactory goFactory = GObjectFactory.instance(); /** An internal XServer implementation capable of obtaining text metrics, etc. */ protected final IDisplayServer ids; /** The runtime context associated with chart generation */ protected final RunTimeContext rtc; protected final IChartComputation cComp; /** A final internal reference to the model used in rendering computations */ protected final Chart cm; /** * Insets maintained as pixels equivalent of the points value specified in the model used here for * fast computations */ protected Insets insCA = null; /** Ratio for converting a point to a pixel */ protected transient double dPointToPixel = 0; public PlotComputation(IDisplayServer ids, RunTimeContext rtc, Chart cm) { this.rtc = rtc; this.cComp = rtc.getState(StateKey.CHART_COMPUTATION_KEY); this.ids = ids; this.cm = cm; dPointToPixel = ids.getDpiResolution() / 72d; } /** * A computed plot area based on the block dimensions and the axis attributes and label values * (within axes) */ protected Bounds boPlotBackground = goFactory.createBounds(0, 0, 100, 100); /** * This method computes the entire chart within the given bounds. If the dataset has changed but * none of the axis attributes have changed, simply re-compute without 'rebuilding axes'. * * @param bo */ public abstract void compute(Bounds bo) throws ChartException, IllegalArgumentException; /** * @param sdOrthogonal * @param seOrthogonal * @return ISeriesRenderingHints * @throws ChartException * @throws IllegalArgumentException */ public abstract ISeriesRenderingHints getSeriesRenderingHints( SeriesDefinition sdOrthogonal, Series seOrthogonal) throws ChartException, IllegalArgumentException; /** @return The plot bounds in pixels */ public final Bounds getPlotBounds() { return boPlotBackground; } public Chart getModel() { return cm; } public final Insets getPlotInsets() { return insCA; } public final RunTimeContext getRunTimeContext() { return rtc; } public IChartComputation getChartComputation() { return cComp; } /** * Returns current rate for Point->Pixel. * * @return * @since 2.5 */ public double getPointToPixel() { return dPointToPixel; } }