All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cat.inspiracio.html.ElementCreator Maven / Gradle / Ivy

Go to download

HTML-parser provides a parser for HTML 5 that produces HTML 5 document object model. It aims to be a Java-implementation of http://www.w3.org/TR/html5/. It is for use in the server. It does not implement features that are relevant in the client, like event handling. It is for use from javascript, via Java's scripting library.

The newest version!
/*
Copyright 2015 Alexander Bunkenburg 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cat.inspiracio.html;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.DOMException;

/** A factory for html elements.
 * 
 * This class is only known to HTMLDOMImplementation.
 * */
class ElementCreator implements Serializable{
	private static final long serialVersionUID = -5325529085204909410L;

	/** Registered classes for custom elements. 
	 * The key is the tag name (lowercase). */
	private Map>registered=null;
	
	ElementCreator(){}
	
	/** Creates an html5 element for this tag.
	 * 
	 * @param d The html document that will contain the element.
	 * @param tag The element tag, like "div". 
	 * @return the new html5 element
	 * 
	 * */
	HTMLElement create(HTMLDocumentImp d, String tag) throws DOMException {
		tag=tag.toLowerCase();//can be skipped?

		//Try the registered custom elements
		if(registered!=null){
			Classcl=registered.get(tag);
			if(cl!=null)
				return instantiate(cl, d, tag);			
		}
		
		//Find the element implementation class for this tag.
		//The standard HTML5 tags, written explicitly so that execution is direct.
		//No looking up Strings in collections, no reflection.
		switch(tag){
		
		//Root element and document metadata
		case"html":		return new HTMLHtmlElementImp(d);
		case"head":		return new HTMLHeadElementImp(d);
		case"title":	return new HTMLTitleElementImp(d);
		case"base":		return new HTMLBaseElementImp(d);
		case"link":		return new HTMLLinkElementImp(d);
		case"meta":		return new HTMLMetaElementImp(d);
		case"style":	return new HTMLStyleElementImp(d);
		
		//Sections
		case"body":		return new HTMLBodyElementImp(d);
		case"article":	return new HTMLElementImp(d, tag);
		case"section":	return new HTMLElementImp(d, tag);
		case"nav":		return new HTMLElementImp(d, tag);
		case"aside":	return new HTMLElementImp(d, tag);
		case"h1":		return new HTMLElementImp(d, tag);
		case"h2":		return new HTMLElementImp(d, tag);
		case"h3":		return new HTMLElementImp(d, tag);
		case"h4":		return new HTMLElementImp(d, tag);
		case"h5":		return new HTMLElementImp(d, tag);
		case"h6":		return new HTMLElementImp(d, tag);
		case"header":	return new HTMLElementImp(d, tag);
		case"footer":	return new HTMLElementImp(d, tag);
		case"address":	return new HTMLElementImp(d, tag);
		
		//Grouping content
		case"p":		return new HTMLParagraphElementImp(d);
		case"hr":		return new HTMLHRElementImp(d);
		case"pre":		return new HTMLPreElementImp(d);
		case"blockquote":return new HTMLBlockquoteElementImp(d);
		case"ol":		return new HTMLOListElementImp(d);
		case"ul":		return new HTMLUListElementImp(d);
		case"li":		return new HTMLLIElementImp(d);
		case"dl":		return new HTMLDListElementImp(d);
		case"dt":		return new HTMLElementImp(d, tag);
		case"dd":		return new HTMLElementImp(d, tag);
		case"figure":	return new HTMLElementImp(d, tag);
		case"figcaption":return new HTMLElementImp(d, tag);
		case"div":		return new HTMLDivElementImp(d);
		case"main":		return new HTMLElementImp(d, tag);
		
		//Text-level semantics
		case"a":		return new HTMLAnchorElementImp(d);
		case"em":		return new HTMLElementImp(d, tag);
		case"strong":	return new HTMLElementImp(d, tag);
		case"small":	return new HTMLElementImp(d, tag);
		case"s":		return new HTMLElementImp(d, tag);
		case"cite":		return new HTMLElementImp(d, tag);
		case"q":		return new HTMLQuoteElementImp(d, tag);
		case"dfn":		return new HTMLElementImp(d, tag);
		case"abbr":		return new HTMLElementImp(d, tag);
		case"data":		return new HTMLDataElementImp(d);
		case"time":		return new HTMLTimeElementImp(d);
		case"code":		return new HTMLElementImp(d, tag);
		case"var":		return new HTMLElementImp(d, tag);
		case"samp":		return new HTMLElementImp(d, tag);
		case"kbd":		return new HTMLElementImp(d, tag);
		case"sub":		return new HTMLElementImp(d, tag);
		case"sup":		return new HTMLElementImp(d, tag);
		case"i":		return new HTMLElementImp(d, tag);
		case"b":		return new HTMLElementImp(d, tag);
		case"u":		return new HTMLElementImp(d, tag);
		case"mark":		return new HTMLElementImp(d, tag);
		case"ruby":		return new HTMLElementImp(d, tag);
		case"rb":		return new HTMLElementImp(d, tag);
		case"rt":		return new HTMLElementImp(d, tag);
		case"rtc":		return new HTMLElementImp(d, tag);
		case"rp":		return new HTMLElementImp(d, tag);
		case"bdi":		return new HTMLElementImp(d, tag);
		case"bdo":		return new HTMLElementImp(d, tag);
		case"span":		return new HTMLSpanElementImp(d);
		case"br":		return new HTMLBRElementImp(d);
		case"wbr":		return new HTMLElementImp(d, tag);
		
		//Edits
		case"ins":		return new HTMLModElementImp(d, tag);
		case"del":		return new HTMLModElementImp(d, tag);
		
		//Embedded content 
		case"img":		return new HTMLImageElementImp(d);
		case"picture":	return new HTMLPictureElementImp(d);
		case"iframe":	return new HTMLIFrameElementImp(d);
		case"embed":	return new HTMLEmbedElementImp(d);
		case"object":	return new HTMLObjectElementImp(d);
		case"param":	return new HTMLParamElementImp(d);
		case"video":	return new HTMLVideoElementImp(d);
		case"audio":	return new HTMLAudioElementImp(d);
		case"source":	return new HTMLSourceElementImp(d);
		case"track":	return new HTMLTrackElementImp(d);
		case"map":		return new HTMLMapElementImp(d);
		case"area":		return new HTMLAreaElementImp(d);
		
		//Tabular data
		case"table":	return new HTMLTableElementImp(d);
		case"caption":	return new HTMLTableCaptionElementImp(d);
		case"colgroup":	return new HTMLTableColGroupElementImp(d);
		case"col":		return new HTMLTableColElementImp(d);
		case"tbody":	return new HTMLTableBodyElementImp(d);
		case"thead":	return new HTMLTableHeadElementImp(d);
		case"tfoot":	return new HTMLTableFootElementImp(d);
		case"tr":		return new HTMLTableRowElementImp(d);
		case"td":		return new HTMLTableDataCellElementImp(d);
		case"th":		return new HTMLTableHeaderCellElementImp(d);
		
		//Forms
		case"form":		return new HTMLFormElementImp(d);
		case"label":	return new HTMLLabelElementImp(d);
		case"input":	return new HTMLInputElementImp(d);
		case"button":	return new HTMLButtonElementImp(d);
		case"select":	return new HTMLSelectElementImp(d);
		case"datalist":	return new HTMLDataListElementImp(d);
		case"optgroup":	return new HTMLOptGroupElementImp(d);
		case"option":	return new HTMLOptionElementImp(d);
		case"textarea":	return new HTMLTextAreaElementImp(d);
		case"keygen":	return new HTMLKeygenElementImp(d);
		case"output":	return new HTMLOutputElementImp(d);
		case"progress":	return new HTMLProgressElementImp(d);
		case"meter":	return new HTMLMeterElementImp(d);
		case"fieldset":	return new HTMLFieldSetElementImp(d);
		case"legend":	return new HTMLLegendElementImp(d);
		
		//Script
		case"script":	return new HTMLScriptElementImp(d);
		case"noscript":	return new HTMLElementImp(d, tag);
		case"template":	return new HTMLTemplateElementImp(d);
		case"canvas":	return new HTMLCanvasElementImp(d);
		
		//obsolete: I don't implement them.
		//applet
		//marquee
		}
		
		//Unknown tags.
		return new HTMLUnknownElementImp(d, tag);
	}

	/** During document construction, instantiates a custom element. 
	 * 
	 * This method uses reflection and therefore is slow and could throw exceptions. 
	 * 
	 * @param cl
	 * @param d
	 * @param tag
	 * */
	private HTMLElementImp instantiate(Class cl, HTMLDocumentImp d, String tag){
		try {

			try{

				//Call new HTMLFultonElement(d, tag)
				Constructor constructor=cl.getConstructor(HTMLDocumentImp.class, String.class);
				return constructor.newInstance(d, tag);
				
			}catch(NoSuchMethodException e){

				//Call new HTMLFultonElement(d)
				Constructor constructor=cl.getConstructor(HTMLDocumentImp.class);
				return constructor.newInstance(d);
				
			}

		
		}catch(NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			throw new RuntimeException(e);
		}
		
	}

	/** During document construction, instantiates a custom element. 
	 * 
	 * This method uses reflection and therefore is slow and could throw exceptions. 
	 * 
	 * @param cl A class that extends HTMLElementImp, therefore an implementation of an element
	 * @param d The containing document for the new element
	 * */
	private HTMLElementImp instantiate(Class cl, HTMLDocumentImp d){
		try {
			//Call new HTMLFultonElement(d)
			Constructor constructor=cl.getConstructor(HTMLDocumentImp.class);
			return constructor.newInstance(d);
		}
		catch(NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			throw new RuntimeException(e);
		}
	}

	/** Register a class as implementation for a custom element.
	 *  
	 * @param cl A class for the custom element. 
	 * 	The class must have a public constructor with one parameter of type HTMLDocumentImp 
	 * 	that calls the super-constructor with two parameters: the same HTMLDocumentImp and the desired tag name. 
	 * 
	 * @param tags Registers the class for these tag names. 
	 * 
	 * 	There may be zero tag names. In that case, the implementation will try to get the tag name
	 * 	from the class by instantiating it (with owner == null) and calling getTagName().
	 * 
	 * 	There may be exactly one tag name. That is a usual case.
	 * 
	 * 	There may be several tag names. In that case, the constructor of the class must remember the
	 * 	tag name.
	 * 
	 *  */
	void register(Class cl, String... tags){
		
		//No tag name given. Try to guess it.
		if(tags==null || tags.length==0){
			String tag=guess(cl);//IllegalArgumentException
			register(cl, tag);
			return;
		}
		
		//Got some tag names. Register the class.
		if(registered==null)
			registered=new HashMap>();
		for(String tag : tags){
			tag=tag.toLowerCase();
			registered.put(tag, cl);
		}
	}

	/** For an element class, tries to guess which tag name it is for,
	 * by instantiating it and calling getTagName(). */
	private String guess(Classcl){
		try {
			HTMLDocumentImp o=null;
			Constructorconstructor=cl.getConstructor(HTMLDocumentImp.class);
			HTMLElementImp e=constructor.newInstance(o);
			String tag=e.getTagName();
			return tag;
		} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			throw new IllegalArgumentException("No tag name given for " + cl);
		}

	}

    /** Create an element of this class.
	 * 
	 * Convenience during java programming: the return type is exact.
	 * 
	 * Not implemented for all element classes.
	 * 
	 * Some element classes are used to several tags,
	 * for those this method does not work. 
	 * 
	 * @param  A subinterface of HTMLElement that represents one html element
	 * @param c The class object
	 * @return A fresh instance of the element
	 * @throws UnsupportedOperationException Not (yet) implemented for this interface.
	 * */
	@SuppressWarnings("unchecked")
	 T create(HTMLDocumentImp d, Class c){
		
		boolean isInterface=c.isInterface();
		boolean haveRegistrations=registered!=null;
		
		//Try the registered custom elements, if c really is an implementation class, that is, c extends HTMLElementImp
		if(!isInterface && haveRegistrations){
			Class imp=c.asSubclass(HTMLElementImp.class);
			if(registered.containsValue(imp)){
				//if c is a class and implements HTMLElementImp
				HTMLElementImp o=instantiate(imp, d);
				return (T) o;
			}
		}
				
		if(c==HTMLAnchorElement.class)			return(T)new HTMLAnchorElementImp(d);
		if(c==HTMLAreaElement.class)			return(T)new HTMLAreaElementImp(d);
		if(c==HTMLAudioElement.class)			return(T)new HTMLAudioElementImp(d);
		if(c==HTMLBaseElement.class)			return(T)new HTMLBaseElementImp(d);
		if(c==HTMLBlockquoteElement.class)		return(T)new HTMLBlockquoteElementImp(d);
		if(c==HTMLBodyElement.class)			return(T)new HTMLBodyElementImp(d);
		if(c==HTMLBRElement.class)				return(T)new HTMLBRElementImp(d);
		if(c==HTMLButtonElement.class)			return(T)new HTMLButtonElementImp(d);
		if(c==HTMLCanvasElement.class)			return(T)new HTMLCanvasElementImp(d);
		if(c==HTMLDataElement.class)			return(T)new HTMLDataElementImp(d);
		if(c==HTMLDataListElement.class)		return(T)new HTMLDataListElementImp(d);
		if(c==HTMLDivElement.class)				return(T)new HTMLDivElementImp(d);
		if(c==HTMLDListElement.class)			return(T)new HTMLDListElementImp(d);
		if(c==HTMLEmbedElement.class)			return(T)new HTMLEmbedElementImp(d);
		if(c==HTMLFieldSetElement.class)		return(T)new HTMLFieldSetElementImp(d);
		if(c==HTMLFormElement.class)			return(T)new HTMLFormElementImp(d);
		if(c==HTMLHeadElement.class)			return(T)new HTMLHeadElementImp(d);
		if(c==HTMLHRElement.class)				return(T)new HTMLHRElementImp(d);
		if(c==HTMLHtmlElement.class)			return(T)new HTMLHtmlElementImp(d);
		if(c==HTMLIFrameElement.class)			return(T)new HTMLIFrameElementImp(d);
		if(c==HTMLImageElement.class)			return(T)new HTMLImageElementImp(d);
		if(c==HTMLInputElement.class)			return(T)new HTMLInputElementImp(d);
		if(c==HTMLKeygenElement.class)			return(T)new HTMLKeygenElementImp(d);
		if(c==HTMLLabelElement.class)			return(T)new HTMLLabelElementImp(d);
		if(c==HTMLLegendElement.class)			return(T)new HTMLLegendElementImp(d);
		if(c==HTMLLIElement.class)				return(T)new HTMLLIElementImp(d);
		if(c==HTMLLinkElement.class)			return(T)new HTMLLinkElementImp(d);
		if(c==HTMLMapElement.class)				return(T)new HTMLMapElementImp(d);
		if(c==HTMLMetaElement.class)			return(T)new HTMLMetaElementImp(d);
		if(c==HTMLMeterElement.class)			return(T)new HTMLMeterElementImp(d);
		if(c==HTMLObjectElement.class)			return(T)new HTMLObjectElementImp(d);
		if(c==HTMLOListElement.class)			return(T)new HTMLOListElementImp(d);
		if(c==HTMLOptGroupElement.class)		return(T)new HTMLOptGroupElementImp(d);
		if(c==HTMLOptionElement.class)			return(T)new HTMLOptionElementImp(d);
		if(c==HTMLOutputElement.class)			return(T)new HTMLOutputElementImp(d);
		if(c==HTMLParagraphElement.class)		return(T)new HTMLParagraphElementImp(d);
		if(c==HTMLParamElement.class)			return(T)new HTMLParamElementImp(d);
		if(c==HTMLPictureElement.class)			return(T)new HTMLPictureElementImp(d);
		if(c==HTMLPreElement.class)				return(T)new HTMLPreElementImp(d);
		if(c==HTMLProgressElement.class)		return(T)new HTMLProgressElementImp(d);
		if(c==HTMLQuoteElement.class)			return(T)new HTMLQuoteElementImp(d);
		if(c==HTMLScriptElement.class)			return(T)new HTMLScriptElementImp(d);
		if(c==HTMLSelectElement.class)			return(T)new HTMLSelectElementImp(d);
		if(c==HTMLSourceElement.class)			return(T)new HTMLSourceElementImp(d);
		if(c==HTMLSpanElement.class)			return(T)new HTMLSpanElementImp(d);
		if(c==HTMLStyleElement.class)			return(T)new HTMLStyleElementImp(d);
		if(c==HTMLTableBodyElement.class)		return(T)new HTMLTableBodyElementImp(d);
		if(c==HTMLTableCaptionElement.class)	return(T)new HTMLTableCaptionElementImp(d);
		if(c==HTMLTableCellElement.class)		return(T)new HTMLTableDataCellElementImp(d);
		if(c==HTMLTableColElement.class)		return(T)new HTMLTableColElementImp(d);
		if(c==HTMLTableColGroupElement.class)	return(T)new HTMLTableColGroupElementImp(d);
		if(c==HTMLTableDataCellElement.class)	return(T)new HTMLTableDataCellElementImp(d);
		if(c==HTMLTableElement.class)			return(T)new HTMLTableElementImp(d);
		if(c==HTMLTableFootElement.class)		return(T)new HTMLTableFootElementImp(d);
		if(c==HTMLTableHeadElement.class)		return(T)new HTMLTableHeadElementImp(d);
		if(c==HTMLTableHeaderCellElement.class)	return(T)new HTMLTableHeaderCellElementImp(d);
		if(c==HTMLTableRowElement.class)		return(T)new HTMLTableRowElementImp(d);
		if(c==HTMLTemplateElement.class)		return(T)new HTMLTemplateElementImp(d);
		if(c==HTMLTextAreaElement.class)		return(T)new HTMLTextAreaElementImp(d);
		if(c==HTMLTimeElement.class)			return(T)new HTMLTimeElementImp(d);
		if(c==HTMLTitleElement.class)			return(T)new HTMLTitleElementImp(d);
		if(c==HTMLTrackElement.class)			return(T)new HTMLTrackElementImp(d);
		if(c==HTMLUListElement.class)			return(T)new HTMLUListElementImp(d);
		if(c==HTMLVideoElement.class)			return(T)new HTMLVideoElementImp(d);
		throw new UnsupportedOperationException("class " + c);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy