/******************************************************************************* * Copyright (c) 2004, 2012 IBM 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.html.core.internal.modelquery; import java.util.Hashtable; import java.util.Iterator; import java.util.Locale; import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl; /** */ abstract class CMNamedNodeMapForBuddySystem implements CMNamedNodeMap { private boolean isXHTML = false; private Hashtable map = new Hashtable(); /** * Constructor of CMNamedNodeMapForBuddySystem. * CAUTION: Each derived class must call 'makeBuddySystem' method in its * constructor to build up its contents. */ public CMNamedNodeMapForBuddySystem(boolean isXHTML) { super(); this.isXHTML = isXHTML; } /* * @see CMNamedNodeMap#getLength() */ public int getLength() { return map.size(); } /* * @see CMNamedNodeMap#getNamedItem(String) */ public CMNode getNamedItem(String name) { String key = canonicalName(name); if (!map.containsKey(key)) return null; return (CMNode) map.get(key); } /* * @see CMNamedNodeMap#item(int) */ public CMNode item(int index) { synchronized (map) { Iterator iter = iterator(); while (iter.hasNext()) { Object node = iter.next(); if (--index < 0) return (CMNode) node; } } return null; } /* * @see CMNamedNodeMap#iterator() */ public Iterator iterator() { return map.values().iterator(); } /* package scope. */ void put(String name, CMNode cmnode) { if (name == null || cmnode == null) return; map.put(canonicalName(name), cmnode); } abstract protected String getKeyName(CMNode original); abstract protected CMNode createBuddySystem(CMNode original); protected boolean isXHTML() { return isXHTML; } /** * Each derived class must call this method in its constructor * to build up its contents. */ protected void makeBuddySystem(CMNamedNodeMap original) { if (original instanceof CMNamedNodeMapImpl) { final Hashtable table = ((CMNamedNodeMapImpl) original).getHashtable(); if (table != null) { synchronized (table) { buddy(table.values().iterator()); } } } else { buddy(original.iterator()); } } private void buddy(Iterator i) { if (i == null) return; while (i.hasNext()) { CMNode org = (CMNode) i.next(); String key = getKeyName(org); CMNode newNode = createBuddySystem(org); put(key, newNode); } } private String canonicalName(String name) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=171918 // we are able to "cheat" here a little and use US Locale // to get a good canonical form, since we are using this only // for HTML and JSP standard tags. // Long term, for similar needs with XML 1.1 (for example) // we should use a class such as com.ibm.icu.text.Normalizer return name.toUpperCase(Locale.US); } }