/******************************************************************************* * Copyright (c) 2010 Association for Decentralized Information Management in * Industry THTH ry. * 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: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.databoard.type; import java.util.HashSet; import java.util.Set; import org.simantics.databoard.Datatypes; import org.simantics.databoard.accessor.error.ReferenceException; import org.simantics.databoard.accessor.reference.ChildReference; import org.simantics.databoard.accessor.reference.ComponentReference; import org.simantics.databoard.accessor.reference.IndexReference; import org.simantics.databoard.accessor.reference.LabelReference; import org.simantics.databoard.accessor.reference.NameReference; import org.simantics.databoard.annotations.Referable; import org.simantics.databoard.util.IdentityPair; public @Referable class UnionType extends Datatype { public static UnionType newEnum(String...choices) { UnionType result = new UnionType(); for ( String choice : choices ) result.addComponent(choice, Datatypes.VOID); return result; } public static final Component[] NO_COMPONENTS = new Component[0]; public Component[] components = NO_COMPONENTS; public UnionType() {} public UnionType(Component...components) { if (components.length==0) throw new IllegalArgumentException("need atleast 1 tag type"); this.components = components; } public void addComponent(String name, Datatype type) { Component c = new Component(name, type); if (components == null) { components = new Component[] { c }; } else { Component[] newComponents = new Component[ components.length +1 ]; System.arraycopy(components, 0, newComponents, 0, components.length); newComponents[ components.length ] = c; components = newComponents; } } public void removeComponent(String tagName) { int index = getComponentIndex2(tagName); if (index<0) return; Component[] newComponents = new Component[ components.length -1 ]; if (index>0) System.arraycopy(components, 0, newComponents, 0, index); if (index subtypes, Set recursiveSubtypes) { if(!subtypes.add(this)) { recursiveSubtypes.add(this); return; } for(Component component : components) component.type.collectSubtypes(subtypes, recursiveSubtypes); } @Override protected boolean deepEquals(Object obj, Set> compareHistory) { if (this==obj) return true; if ( !hasEqualMetadata(obj) ) return false; if (obj instanceof UnionType == false) return false; UnionType other = (UnionType) obj; if (components.length!= other.components.length) return false; // Verify names for (int i = 0; i>(1); IdentityPair pair = new IdentityPair(this, other); if (compareHistory.contains(pair)) return true; compareHistory.add(pair); for (int i = 0; i T accept(Visitor v) { return v.visit(this); } public int getComponentCount() { return components.length; } @Override public Datatype getComponentType(ChildReference path) { if (path==null) return this; if (path instanceof IndexReference) { IndexReference ir = (IndexReference) path; return components[ir.index].type.getComponentType(path.childReference); } if (path instanceof NameReference) { NameReference nr = (NameReference) path; return getComponent( nr.name ).type.getComponentType(path.childReference); } if (path instanceof LabelReference) { LabelReference lr = (LabelReference) path; try { Integer i = new Integer(lr.label); return getComponent( i ).type.getComponentType(path.childReference); } catch (NumberFormatException nfe) { return getComponent( lr.label ).type.getComponentType(path.childReference); } } throw new IllegalArgumentException(); } public Component getComponent(int i) { return components[i]; } public Component[] getComponents() { return components; } /** * Get tag by name. * * @param fieldName component name * @return component index or null if one does not exist */ public Integer getComponentIndex(String fieldName) { for (int i=0; inull */ public Datatype getComponentType(String fieldName) { int index = getComponentIndex2(fieldName); if (index<0) return null; return components[index].type; } /** * Get component by name. * * @param fieldName component name * @return component or null if one does not exist */ public Component getComponent(String fieldName) { for (Component c : components) if (c.name.equals(fieldName)) return c; return null; } @Override public Datatype getComponentType(int index) { return components[index].type; } /** * UnionType is enumeration if all its components are empty records * @return true if enumeration type */ public boolean isEnumeration() { boolean isEnum = true; for (Component c : components) isEnum &= c.type.equals( Datatypes.VOID ); return isEnum; } @SuppressWarnings("unchecked") @Override public T getChildType(ChildReference reference) throws ReferenceException { if (reference==null) return (T) this; if (reference instanceof LabelReference) { LabelReference lr = (LabelReference) reference; int tag = getComponentIndex( lr.label ); if (tag<0 && lr.label.equals("uv")) { throw new ReferenceException("Cannot get component reference without an instance"); } return components[tag].type.getChildType(reference.getChildReference()); } if (reference instanceof ComponentReference) { throw new ReferenceException("Cannot get component reference without an instance"); } if (reference instanceof IndexReference) { IndexReference ir = (IndexReference) reference; int tag = ir.index; if (tag<0 || tag>=getComponentCount()) throw new ReferenceException("Tag index out of bounds"); return components[tag].type.getChildType(reference.getChildReference()); } if (reference instanceof NameReference) { NameReference nr = (NameReference) reference; int tag = getComponentIndex2( nr.name ); if (tag<0) throw new ReferenceException("Tag by name \""+nr.name+"\" is not found"); return components[tag].type.getChildType(reference.getChildReference()); } throw new ReferenceException(reference.getClass()+" is not a reference of UnionType"); } }