/** * This file Copyright (c) 2005-2008 Aptana, Inc. This program is * dual-licensed under both the Aptana Public License and the GNU General * Public license. You may elect to use one or the other of these licenses. * * This program is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. Redistribution, except as permitted by whichever of * the GPL or APL you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or modify this * program under the terms of the GNU General Public License, * Version 3, as published by the Free Software Foundation. You should * have received a copy of the GNU General Public License, Version 3 along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Aptana provides a special exception to allow redistribution of this file * with certain other free and open source software ("FOSS") code and certain additional terms * pursuant to Section 7 of the GPL. You may view the exception and these * terms on the web at http://www.aptana.com/legal/gpl/. * * 2. For the Aptana Public License (APL), this program and the * accompanying materials are made available under the terms of the APL * v1.0 which accompanies this distribution, and is available at * http://www.aptana.com/legal/apl/. * * You may view the GPL, Aptana's exception and additional terms, and the * APL in the file titled license.html at the root of the corresponding * plugin containing this source file. * * Any modifications to this file must keep this entire header intact. */ package com.aptana.ide.metadata; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import com.aptana.ide.lexer.Lexeme; import com.aptana.ide.parsing.nodes.ParseNodeBase; /** * The "environment" of metadata. This can be queried for documentation of items. * * @author Ingo Muschenetz */ public class MetadataRuntimeEnvironment implements com.aptana.ide.parsing.IRuntimeEnvironment, IMetadataEnvironment { private static final String EMPTY = ""; //$NON-NLS-1$ private ArrayList<MetadataEnvironment> environments = new ArrayList<MetadataEnvironment>(); private Hashtable<Integer, Hashtable<String, ParseNodeBase>> fileObjects = new Hashtable<Integer, Hashtable<String, ParseNodeBase>>(); private Hashtable<Integer, Hashtable<String, ParseNodeBase>> cssFileObjects = new Hashtable<Integer, Hashtable<String, ParseNodeBase>>(); /** * returns an hashtable of all "objects" of interest in all files * * @return An hashtable of every object */ public Hashtable<Integer, Hashtable<String, ParseNodeBase>> getFileObjects() { return fileObjects; } /** * Collects all ids in the environment and returns them. * * @return String[] */ public String[] getAllIds() { ArrayList<String> ids = new ArrayList<String>(); Hashtable<Integer, Hashtable<String, ParseNodeBase>> objs = getFileObjects(); Enumeration<Integer> keys = objs.keys(); while (keys.hasMoreElements()) { Integer fileIndex = (Integer) keys.nextElement(); if (fileIndex.intValue() >= 0) { Hashtable<String, ParseNodeBase> a = objs.get(fileIndex); ids.addAll(a.keySet()); } } return (String[]) ids.toArray(new String[0]); } /** * Adds the specified ID to the hashtable of ids * * @param id * @param fileIndex * @param hn */ public void addId(String id, int fileIndex, ParseNodeBase hn) { if (!fileObjects.containsKey(new Integer(fileIndex))) { Hashtable<String, ParseNodeBase> h = new Hashtable<String, ParseNodeBase>(); h.put(id, hn); fileObjects.put(new Integer(fileIndex), h); } else { Hashtable<String, ParseNodeBase> h = fileObjects.get(new Integer(fileIndex)); if (!h.containsKey(id)) { h.put(id, hn); } } } /** * Removes the particular ids of the file in question * * @param fileIndex */ public void removeFileIds(int fileIndex) { fileObjects.remove(new Integer(fileIndex)); } /** * Adds an environment to the metadata collection * * @param element * The element to add */ public void addEnvironment(MetadataEnvironment environment) { environments.add(environment); } /** * Removes an environment from the metadata collection * * @param element * The element to remove */ public void removeEnvironment(MetadataEnvironment environment) { environments.remove(environment); } /** * Return the list of metadata environments * * @return */ public MetadataEnvironment[] getEnvironments() { return environments.toArray(new MetadataEnvironment[0]); } /** * Returns all the elements */ public String[] getAllElements() { List<String> allElements = new ArrayList<String>(); for (Iterator<MetadataEnvironment> iterator = environments.iterator(); iterator.hasNext();) { MetadataEnvironment name = iterator.next(); ElementMetadata[] elements = name.getAllElements(); for (int i = 0; i < elements.length; i++) { ElementMetadata elementMetadata = elements[i]; String elementName = elementMetadata.getName().toLowerCase(); if (!allElements.contains(elementName)) { allElements.add(elementName); } } } return allElements.toArray(new String[0]); } /** * Return the set of all fields * * @return the Hashtable of all "global" fields; */ public Hashtable<String, FieldMetadata> getGlobalFields() { Hashtable<String, FieldMetadata> globalFields = new Hashtable<String, FieldMetadata>(); for (Iterator<MetadataEnvironment> iterator = environments.iterator(); iterator.hasNext();) { MetadataEnvironment name = iterator.next(); Hashtable<String, FieldMetadata> fields = name.getGlobalFields(); Enumeration<FieldMetadata> fieldSet = fields.elements(); while (fieldSet.hasMoreElements()) { FieldMetadata field = (FieldMetadata) fieldSet.nextElement(); if (!globalFields.containsKey(field.getName())) { globalFields.put(field.getName(), field); } else { globalFields.get(field.getName()).merge(field); } } } return globalFields; } /** * Return the set of all events * * @return the Hashtable of all "global" events; */ public Hashtable<String, EventMetadata> getGlobalEvents() { Hashtable<String, EventMetadata> globalEvents = new Hashtable<String, EventMetadata>(); for (Iterator<MetadataEnvironment> iterator = environments.iterator(); iterator.hasNext();) { MetadataEnvironment name = iterator.next(); Hashtable<String, EventMetadata> events = name.getGlobalEvents(); Enumeration<EventMetadata> eventsSet = events.elements(); while (eventsSet.hasMoreElements()) { EventMetadata field = (EventMetadata) eventsSet.nextElement(); if (!globalEvents.containsKey(field.getName())) { globalEvents.put(field.getName(), field); } else { globalEvents.get(field.getName()).merge(field); } } } return globalEvents; } /** * returns the specified element * * @param name * The element name to get * @return The specified element */ public ElementMetadata getElement(String tagNameLower) { return getMergedElement(tagNameLower); } /** * returns the specified element merged from all of the individual environments * * @param name * The element name to get * @return The specified element */ protected ElementMetadata getMergedElement(String tagNameLower) { ElementMetadata data = new ElementMetadata(); for (Iterator<MetadataEnvironment> iterator = environments.iterator(); iterator.hasNext();) { MetadataEnvironment name = iterator.next(); ElementMetadata d = name.getElement(tagNameLower); if (d != null) { data.merge(d); } } return data; } /** * Gets an element from the environment based upon a lexeme * * @param lexeme * The environment item * @return An element, or null if not found. */ public ElementMetadata getElement(Lexeme lexeme) { String lexemeText = lexeme.getText().replaceAll("</", EMPTY); //$NON-NLS-1$ lexemeText = lexeme.getText().replaceAll("<", EMPTY); //$NON-NLS-1$ return getElement(lexemeText); } /** * Given a metadata element, returns the documentation for it * * @param elementName * @return A string containing documentation */ public String getElementDocumentation(String elementName) { ElementMetadata element = getElement(elementName); return getElementDocumentation(element); } /** * Given a metadata element, returns the documentation for it * * @param element * @return A string containing documentation */ public String getElementDocumentation(ElementMetadata element) { StringBuffer docText = new StringBuffer(); docText.append("<b>" + element.getName() + "</b>"); //$NON-NLS-1$ //$NON-NLS-2$ if (element.getFullName() != EMPTY) { docText.append(" (" + element.getFullName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ } docText.append("<br>" + element.getDescription()); //$NON-NLS-1$ UserAgent[] agents = element.getUserAgents(); if (agents.length > 0) { docText.append("<br><br><b>").append(Messages.MetadataEnvironment_Supported_Header).append("</b> "); //$NON-NLS-1$ //$NON-NLS-2$ for (int i = 0; i < agents.length; i++) { UserAgent ua = agents[i]; docText.append(ua.getPlatform() + " " + ua.getVersion()); //$NON-NLS-1$ if (i < agents.length - 1) { docText.append(", "); //$NON-NLS-1$ } } } return docText.toString(); } /** * Returns a list of all the platforms this item is supported by * * @return Returns a list of all the platforms this item is supported by */ public String[] getUserAgentPlatformNames(String elementName) { ElementMetadata element = getElement(elementName); return element.getUserAgentPlatformNames(); } /** * Given a metadata element, returns the documentation for it * * @param element * The element to look at * @return A string containing documentation */ public String getFieldDocumentation(FieldMetadata element) { StringBuffer docText = new StringBuffer(); docText.append("<b>" + element.getName() + "</b>"); //$NON-NLS-1$ //$NON-NLS-2$ if (element.getType() != EMPTY) { docText.append(": " + element.getType()); //$NON-NLS-1$ } docText.append("<br>" + element.getDescription()); //$NON-NLS-1$ UserAgent[] agents = element.getUserAgents(); if (agents.length > 0) { docText.append("<br><br><b>").append(Messages.MetadataEnvironment_Supported_Header).append("</b> "); //$NON-NLS-1$ //$NON-NLS-2$ for (int i = 0; i < agents.length; i++) { UserAgent ua = agents[i]; docText.append(ua.getPlatform() + " " + ua.getVersion()); //$NON-NLS-1$ if (i < agents.length - 1) { docText.append(", "); //$NON-NLS-1$ } } } return docText.toString(); } /** * Given a metadata element, returns the documentation for it * * @param element * @return A string containing the documentation */ public String getEventDocumentation(EventMetadata element) { StringBuffer docText = new StringBuffer(); docText.append("<b>" + element.getName() + "</b>"); //$NON-NLS-1$ //$NON-NLS-2$ if (element.getType() != EMPTY) { docText.append(": " + element.getType()); //$NON-NLS-1$ } docText.append("<br>" + element.getDescription()); //$NON-NLS-1$ UserAgent[] agents = element.getUserAgents(); if (agents.length > 0) { docText.append("<br><br><b>").append(Messages.MetadataEnvironment_Supported_Header).append("</b> "); //$NON-NLS-1$ //$NON-NLS-2$ for (int i = 0; i < agents.length; i++) { UserAgent ua = agents[i]; docText.append(ua.getPlatform() + " " + ua.getVersion()); //$NON-NLS-1$ if (i < agents.length - 1) { docText.append(", "); //$NON-NLS-1$ } } } return docText.toString(); } public void addClass(String cssClass, int fileIndex, ParseNodeBase hn) { if (!cssFileObjects.containsKey(new Integer(fileIndex))) { Hashtable<String, ParseNodeBase> h = new Hashtable<String, ParseNodeBase>(); h.put(cssClass, hn); cssFileObjects.put(new Integer(fileIndex), h); } else { Hashtable<String, ParseNodeBase> h = cssFileObjects.get(new Integer(fileIndex)); if (!h.containsKey(hn)) { h.put(cssClass, hn); } } } public List<String> getAllClasses() { List<String> classes = new ArrayList<String>(); Hashtable<Integer, Hashtable<String, ParseNodeBase>> objs = cssFileObjects; Enumeration<Integer> keys = objs.keys(); while (keys.hasMoreElements()) { Integer fileIndex = (Integer) keys.nextElement(); if (fileIndex.intValue() >= 0) { Hashtable<String, ParseNodeBase> a = objs.get(fileIndex); classes.addAll(a.keySet()); } } return classes; } }