| /******************************************************************************* |
| * Copyright (c) 2004 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.contentmodel; |
| |
| |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; |
| import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; |
| |
| /** |
| */ |
| abstract class DeclCollection implements CMNamedNodeMap { |
| |
| |
| protected class DualMap { |
| public DualMap() { |
| super(); |
| } |
| |
| public DualMap(Object[] objects) { |
| super(); |
| initialize(objects); |
| } |
| |
| public int size() { |
| return table.length; |
| } |
| |
| public Object getValue(int key) { |
| if (!isValidIndex(key)) |
| return null; |
| return table[key]; |
| } |
| |
| public int getKey(Object value) { |
| Integer keyObj = (Integer) map.get(value); |
| if (keyObj == null) |
| return ID_UNKNOWN; |
| return keyObj.intValue(); |
| } |
| |
| protected void initialize(Object[] objects) { |
| if (objects == null) |
| return; |
| table = objects; |
| map = new HashMap(); |
| for (int key = 0; key < objects.length; key++) { |
| Object value = table[key]; |
| map.put(value, new Integer(key)); |
| } |
| } |
| |
| private Object[] table = null; |
| private HashMap map = null; |
| |
| private boolean isValidIndex(int index) { |
| return index >= 0 && index < table.length; |
| } |
| } |
| |
| protected class TolerantStringDualMap extends DualMap { |
| public TolerantStringDualMap(String[] names) { |
| super(); |
| Object[] objects = new Object[names.length]; |
| for (int i = 0; i < names.length; i++) { |
| objects[i] = makeCanonicalForm(names[i]); |
| } |
| initialize(objects); |
| } |
| |
| public int getKey(Object value) { |
| try { |
| String name = (String) value; |
| return super.getKey(makeCanonicalForm(name)); |
| } |
| catch (ClassCastException e) { |
| return ID_UNKNOWN; |
| } |
| } |
| |
| private String makeCanonicalForm(String raw) { |
| return raw.toUpperCase(); |
| } |
| } |
| |
| private class DeclIterator implements Iterator { |
| public DeclIterator() { |
| maxid = fDecls.length - 1; |
| } |
| |
| public boolean hasNext() { |
| return id < maxid; |
| } |
| |
| public Object next() { |
| if (!hasNext()) |
| return null; |
| return item(++id); |
| } |
| |
| public void remove() { /* nothing should be done. */ |
| } |
| |
| private int id = -1; |
| private int maxid = -1; |
| } |
| |
| CMNode[] fDecls = null; |
| protected final static boolean STRICT_CASE = false; |
| protected final static boolean TOLERANT_CASE = true; |
| protected final static int ID_UNKNOWN = -1; |
| private DualMap fMap = null; |
| |
| /** |
| */ |
| public DeclCollection(String[] names, boolean tolerant) { |
| super(); |
| fDecls = new CMNode[names.length]; |
| if (tolerant) { |
| fMap = new TolerantStringDualMap(names); |
| } |
| else { |
| fMap = new DualMap(names); |
| } |
| } |
| |
| /** |
| * @return org.eclipse.wst.xml.core.internal.contentmodel.CMNode |
| * @param id int |
| */ |
| protected abstract CMNode create(String name); |
| |
| /** |
| */ |
| public CMNamedNodeMap getDeclarations(String[] names) { |
| CMNamedNodeMapImpl map = new CMNamedNodeMapImpl(); |
| for (int i = 0; i < names.length; i++) { |
| String name = names[i]; |
| CMNode node = getNamedItem(name); |
| if (node == null) |
| continue; |
| map.putNamedItem(name, node); |
| } |
| return map; |
| } |
| |
| /** |
| * @param names java.util.Iterator |
| */ |
| public void getDeclarations(CMGroupImpl group, Iterator names) { |
| while (names.hasNext()) { |
| String entityName = (String) names.next(); |
| CMNode dec = getNamedItem(entityName); |
| if (dec != null) |
| group.appendChild(dec); |
| } |
| } |
| |
| /** |
| * Map name to id. |
| * @return int |
| * @param name java.lang.String |
| */ |
| protected int getID(String name) { |
| return fMap.getKey(name); |
| } |
| |
| /** |
| * getLength method |
| * @return int |
| */ |
| public int getLength() { |
| return fDecls.length; |
| } |
| |
| /** |
| * @return java.lang.String |
| * @param id int |
| */ |
| protected String getName(int id) { |
| return (String) fMap.getValue(id); |
| } |
| |
| /** |
| * getNamedItem method |
| * @return CMNode |
| * @param name java.lang.String |
| */ |
| public CMNode getNamedItem(String name) { |
| int id = getID(name); |
| if (!isValidID(id)) |
| return null; |
| return item(id); |
| } |
| |
| /** |
| * @return boolean |
| * @param id int |
| */ |
| private boolean isValidID(int id) { |
| return id >= 0 && id < fDecls.length; |
| } |
| |
| /** |
| * item method |
| * @return CMNode |
| * @param index int |
| */ |
| public CMNode item(int index) { |
| if (!isValidID(index)) |
| return null; |
| CMNode decl = fDecls[index]; |
| if (decl != null) |
| return decl; // already exist. |
| |
| decl = create(getName(index)); |
| fDecls[index] = decl; |
| return decl; |
| } |
| |
| /** |
| */ |
| public Iterator iterator() { |
| return new DeclIterator(); |
| } |
| } |