StateNode implements Serializable { public <T extends NodeFeature> T getFeature(Class<T> featureType) { int featureIndex = getFeatureIndex(featureType); NodeFeature feature; if (featureIndex == 0 && features instanceof NodeFeature) { feature = (NodeFeature) features; } else if (featureIndex == 0 && features == null) { feature = NodeFeatureRegistry.create(featureType, this); features = feature; } else { NodeFeature[] featuresArray; if (features instanceof NodeFeature[]) { featuresArray = (NodeFeature[]) features; } else { assert features == null || features instanceof NodeFeature; featuresArray = new NodeFeature[featureIndex + 1]; if (features instanceof NodeFeature) { featuresArray[0] = (NodeFeature) features; } features = featuresArray; } if (featureIndex >= featuresArray.length) { featuresArray = Arrays.copyOf(featuresArray, featureIndex + 1); features = featuresArray; } feature = featuresArray[featureIndex]; if (feature == null) { feature = NodeFeatureRegistry.create(featureType, this); featuresArray[featureIndex] = feature; } } return featureType.cast(feature); } @SafeVarargs  StateNode(Class<? extends NodeFeature>... featureTypes); @SuppressWarnings("unchecked")  StateNode(StateNode node); @SafeVarargs  StateNode(List<Class<? extends NodeFeature>> reportableFeatureTypes,
            Class<? extends NodeFeature>... additionalFeatureTypes); NodeOwner getOwner(); StateNode getParent(); void setParent(StateNode parent); void removeFromTree(); T getFeature(Class<T> featureType); Optional<T> getFeatureIfInitialized(
            Class<T> featureType); boolean hasFeature(Class<? extends NodeFeature> featureType); int getId(); void markAsDirty(); boolean isAttached(); void collectChanges(Consumer<NodeChange> collector); void clearChanges(); void visitNodeTree(Consumer<StateNode> visitor); Registration addAttachListener(Command attachListener); Registration addDetachListener(Command detachListener); @SuppressWarnings("unchecked") T getChangeTracker(NodeFeature feature,
            Supplier<T> factory); void runWhenAttached(SerializableConsumer<UI> command); boolean isReportedFeature(Class<? extends NodeFeature> featureType); void updateActiveState(); boolean isInactive(); boolean hasBeforeClientResponseEntries(); List<StateTree.BeforeClientResponseEntry> dumpBeforeClientResponseEntries(); ExecutionRegistration addBeforeClientResponseEntry(
            BeforeClientResponseEntry entry); void setEnabled(boolean enabled); boolean isEnabled(); boolean isEnabledSelf();  }
@Test(expected = IllegalStateException.class) public void getMissingFeatureThrows() { StateNode node = new StateNode(ElementData.class); node.getFeature(ElementPropertyMap.class); }