/******************************************************************************* * Copyright (c) 2001, 2008 Oracle Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Oracle Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.jsf.facesconfig.util; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.jst.jsf.facesconfig.emf.DynamicElement; import org.eclipse.jst.jsf.facesconfig.internal.translator.IAnyTranslator; import org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapter; import org.eclipse.wst.common.internal.emf.resource.EMF2DOMRenderer; import org.eclipse.wst.common.internal.emf.resource.Renderer; import org.eclipse.wst.common.internal.emf.resource.Translator; import org.eclipse.wst.common.internal.emf.resource.TranslatorResource; import org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSEAdapter; import org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSERenderer; import org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSERendererFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * This class should not be referenced or sub-classed externally. * * The custom render factory for the Faces Config model EMF2DOM translations. * A singleton factory. */ final class FacesRendererFactory extends EMF2DOMSSERendererFactory { /** * The singleton factory instance. */ @SuppressWarnings("hiding") public static FacesRendererFactory INSTANCE = new FacesRendererFactory(); private FacesRendererFactory() { super(); } /** * @see org.eclipse.wst.common.internal.emf.resource.RendererFactory#createRenderer() */ public Renderer createRenderer() { return new MyRenderer(); } private static class MyRenderer extends EMF2DOMSSERenderer { protected EMF2DOMAdapter createRootDOMAdapter() { return new MyEMF2DOMAdapterRoot(getResource(), document, this, getResource().getRootTranslator()); } } /** * Customized adapter that lets us inject arbitrary DOM children * into for ANY elements */ private static class MyEMF2DOMAdapterRoot extends EMF2DOMSSEAdapter { /** * @param object * @param node * @param renderer * @param translator */ public MyEMF2DOMAdapterRoot(org.eclipse.emf.common.notify.Notifier object, Node node, EMF2DOMRenderer renderer, Translator translator) { super(object, node, renderer, translator); } /** * @param node * @param renderer * @param translator */ public MyEMF2DOMAdapterRoot(Node node, EMF2DOMRenderer renderer, Translator translator) { super(node, renderer, translator); } /** * @param resource * @param document * @param renderer * @param translator */ public MyEMF2DOMAdapterRoot(TranslatorResource resource, Document document, EMF2DOMRenderer renderer, Translator translator) { super(resource, document, renderer, translator); } protected void initChildTranslators() { // if this is an ANY translator, then we have prepend the list after // initialization with any dynamic attribute translators super.initChildTranslators(); if (fTranslator instanceof IAnyTranslator) { final Translator[] dynamicAttrs = ((IAnyTranslator)fTranslator) .getDynamicAttributeTranslators(fNode); // avoid an array copy if not necessary if (dynamicAttrs.length > 0) { final Translator[] allTranslators = new Translator[childTranslators.length+dynamicAttrs.length]; // prepend the dynamic attributes so they are queried first System.arraycopy(dynamicAttrs, 0, allTranslators, 0, dynamicAttrs.length); System.arraycopy(childTranslators, 0, allTranslators, dynamicAttrs.length, childTranslators.length); childTranslators = allTranslators; } } } protected Translator[] getChildTranslators() { Translator[] translators = super.getChildTranslators(); // TODO: I'm thinking there must be a more efficient way to do this if (fTranslator instanceof IAnyTranslator) { EObject eObj = getEObject(); if (eObj instanceof DynamicElement) { List newArrayList = new ArrayList(); Translator[] dynamicTranslators = ((IAnyTranslator)fTranslator).getDynamicAttributeTranslators((DynamicElement)eObj); // loop through the dynamic translators and add any to the list // that aren't already there for (int i = 0; i < dynamicTranslators.length; i++) { Translator translator = dynamicTranslators[i]; for (int j = 0; j < translators.length; j++) { final Translator testTranslator = translators[j]; if (testTranslator.isDOMAttribute() // TODO: not fond of passing null, but the arg is ignored anyway (for now) && testTranslator.getDOMName(null).equals(translator.getDOMName(null))) { // null indicates found translator = null; break; } } // if not found, add to list if (translator != null) { newArrayList.add(translator); } } if (newArrayList.size() > 0) { newArrayList.addAll(Arrays.asList(translators)); translators = (Translator[]) newArrayList.toArray(translators); } } } return translators; } protected List getDOMChildren(Node node, Translator map) { if (map instanceof IAnyTranslator) { List children = new ArrayList(); for (int i = 0; i < node.getChildNodes().getLength(); i++) { Node child = node.getChildNodes().item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { children.add(child); } } return children; } return super.getDOMChildren(node, map); } /** * Create an adapter for a child DOM node * * @param mofObject * org.w3c.dom.Node The node to create the adapter for. */ protected EMF2DOMAdapter primCreateAdapter(EObject mofObject, Translator childMap) { // TODO: this may only be necessary when childMap is an IAnyTranslator... Element newNode = createNewNode(mofObject, childMap); return new MyEMF2DOMAdapterRoot(mofObject, newNode, fRenderer, childMap); } /** * Create an adapter for a child DOM node * * @param node * org.w3c.dom.Node The node to create the adapter for. */ protected EMF2DOMAdapter primCreateAdapter(Node node, Translator childMap) { return new MyEMF2DOMAdapterRoot(node, fRenderer, childMap); } } }