/******************************************************************************* * Copyright (c) 2003-2005, 2013 Till Zoppke. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Till Zoppke - initial API and implementation ******************************************************************************/ /* * SkinReader.java * * Created on 05.02.2004 */ package eniac.skin; import java.awt.Image; import java.awt.image.BufferedImage; import java.lang.reflect.Array; import java.util.Hashtable; import java.util.List; import java.util.Vector; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; import eniac.data.type.EType; import eniac.io.Progressor; import eniac.io.Proxy; import eniac.io.XMLUtil; import eniac.lang.Dictionary; import eniac.log.Log; /** * @author zoppke */ public class SkinHandler extends DefaultHandler { // keys indicating states of parsing private static final short DEFAULT = 0; private static final short IN_DESCRIPTOR = 1; private static final short CREATING = 2; // ============================ references // ================================== // reference to the skin-object that we are serving private Skin _skin; // hashtables for storing lod-related objects. private Hashtable<EType, Descriptor> _overviewDescriptors; private Hashtable<EType, Descriptor> _detailDescriptors; // reference to factory, where we get our creators from. private CreatorFactory _factory; // ======================= temporary data while parsing // ===================== // name of a single or an array private Descriptor.Key _name; // the current lod number private int _lod = -1; // current status of parsing private short _state = DEFAULT; // current creator private Creator _creator; // current descriptor private Descriptor _descriptor; // current shapeVector private List<Object> _list; // current hashtable for descriptors private Hashtable<EType, Descriptor> _descriptorsTable; // ============================== lifecycle // ================================= public SkinHandler(Skin skin) { // set reference to skin _skin = skin; // get imageBase for loading images Proxy proxy = _skin.getProxy(); String imageBase = proxy.get(Proxy.Tag.NAME) + "/"; //$NON-NLS-1$ // create new factory _factory = new CreatorFactory(imageBase); // create and init hashtables to store descriptors _overviewDescriptors = new Hashtable<>(); _detailDescriptors = new Hashtable<>(); } // ========================== defaultHandler methods // ======================== public void startDocument() { // init progressor Proxy proxy = _skin.getProxy(); int max = Integer.parseInt(proxy.get(Proxy.Tag.NUMBER_OF_DESCRIPTORS)); Progressor.getInstance().setText(Dictionary.SKIN_LOADING.getText()); Progressor.getInstance().setProgress(0, max); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { // try to read TAG Skin.Tag tag = convertToTag(qName); if (tag == null) { return; } try { // switch on current parsing state switch (_state) { // ============================ default case //================== case DEFAULT : if (tag == Skin.Tag.LOD) { // lod tag. Parse attributes int min = XMLUtil.parseInt(attrs, Skin.Attribute.MIN_HEIGHT); int max = XMLUtil.parseInt(attrs, Skin.Attribute.MAX_HEIGHT); String name = attrs.getValue(Proxy.Tag.NAME.name().toLowerCase()); // add lod to skin _skin.setLod(++_lod, min, max); // set lod name to creatorFactory _factory.setLodName(name); // set current descriptors hashtable _descriptorsTable = _lod == 0 ? _overviewDescriptors : _detailDescriptors; } else if (tag == Skin.Tag.DESCRIPTOR) { // create descriptor _descriptor = new Descriptor(); // set type EType type = getType(XMLUtil.parseString(attrs, Skin.Attribute.TYPE)); // set width, height and fill _descriptor.setWidth(XMLUtil.parseInt(attrs, Skin.Attribute.WIDTH)); _descriptor.setHeight(XMLUtil.parseInt(attrs, Skin.Attribute.HEIGHT)); _descriptor.setFill(XMLUtil.parseEnum(attrs, Skin.Attribute.FILL, Descriptor.Fill.class)); // add descriptor to hashtable array _descriptorsTable.put(type, _descriptor); // Set flag and tell progressor _state = IN_DESCRIPTOR; Progressor.getInstance().incrementValue(); // try { // Thread.sleep(100); // // } catch (Exception e) { // e.printStackTrace(); // } } break; // ====================== in_descriptor case //============== case IN_DESCRIPTOR : if (tag == Skin.Tag.ARRAY) { // get Creator, init list and adjust flag String cls = XMLUtil.parseString(attrs, Skin.Attribute.CLASS); _creator = _factory.get(cls); _list = new Vector<>(); _name = XMLUtil.parseEnum(attrs, Skin.Attribute.NAME, Descriptor.Key.class); } else if (tag == Skin.Tag.ENTRY) { // pass call to creator _creator.startElement(qName, attrs); _state = CREATING; } else if (tag == Skin.Tag.SINGLE) { // get creator and pass call to him _name = XMLUtil.parseEnum(attrs, Skin.Attribute.NAME, Descriptor.Key.class); String cls = XMLUtil.parseString(attrs, Skin.Attribute.CLASS); _creator = _factory.get(cls); _creator.startElement(qName, attrs); _state = CREATING; } break; // ====================== creating case //=================== case CREATING : // pass call to creator _creator.startElement(qName, attrs); break; } } catch (Exception e) { e.printStackTrace(); throw new SAXException(e); } } public void endElement(String uri, String localName, String qName) throws SAXException { // try to read TAG Skin.Tag tag = convertToTag(qName); if (tag == null) { return; } try { // switch on current parsing state switch (_state) { // ============================ default case //================== case DEFAULT : break; // ====================== in_descriptor case //============== case IN_DESCRIPTOR : if (tag == Skin.Tag.DESCRIPTOR) { // end of descriptor. Set descriptor to // reset flag _state = DEFAULT; } else if (tag == Skin.Tag.ARRAY) { // convert list to array and put to descriptor Class<?> cls = _list.get(0).getClass(); // if bufferedImage, there are some images missing. // create array of Images in this case. if (cls.equals(BufferedImage.class)) { cls = Image.class; } // System.out.println(cls); // System.out.println(_list.get(0)); Object[] array = (Object[]) Array.newInstance(cls, _list.size()); _descriptor.put(_name, _list.toArray(array)); } else { // pass call to creator _creator.endElement(qName); } break; // ===================== creating case //==================== case CREATING : if (tag == Skin.Tag.ENTRY) { // end of entry. add created object to list _creator.endElement(qName); _list.add(_creator.getObject()); _state = IN_DESCRIPTOR; } else if (tag == Skin.Tag.SINGLE) { // put created object to descriptor _creator.endElement(qName); _descriptor.put(_name, _creator.getObject()); _state = IN_DESCRIPTOR; } break; } } catch (Exception e) { e.printStackTrace(); throw new SAXException(e); } } public void warning(SAXParseException e) throws SAXException { Log.log(e.toString()); } public void error(SAXParseException e) throws SAXException { Log.log(e.toString()); } public void characters(char[] ch, int start, int length) { if (_state == CREATING) { _creator.characters(new String(ch, start, length)); } } // =========================== other methods // ================================ public void setDescriptorsToType(EType type) { type.setDescriptors(new Descriptor[]{_overviewDescriptors.get(type), _detailDescriptors.get(type)}); } public boolean hasMissingImages() { return _factory.hasMissingImages(); } private Skin.Tag convertToTag(String name) { try { return Enum.valueOf(Skin.Tag.class, name.toUpperCase()); } catch (IllegalArgumentException exc) { // check, if this is a proxy tag try { Enum.valueOf(Proxy.Tag.class, name.toUpperCase()); } catch (IllegalArgumentException exc2) { // completely unknown tag. System.out.println("Ignoring unknown tag: " + name); } return null; } } private EType getType(String name) { return Enum.valueOf(EType.class, name.toUpperCase()); } }