Skip to content

Commit

Permalink
Add TreeWriter API, SerializableProtocol, and implementations.
Browse files Browse the repository at this point in the history
  • Loading branch information
neilcsmith-net committed Oct 20, 2023
1 parent b9d8704 commit d2b3146
Show file tree
Hide file tree
Showing 24 changed files with 937 additions and 66 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
<configuration>
<skippedModules>praxiscore-video-pgl-natives,praxiscore-internal-httpd,praxiscore-internal-osc</skippedModules>
<detectOfflineLinks>false</detectOfflineLinks>
<release>11</release>
<release>17</release>
<additionalOptions>
<additionalOption>-Xdoclint:none</additionalOption>
</additionalOptions>
Expand Down
60 changes: 38 additions & 22 deletions praxiscore-api/src/main/java/org/praxislive/core/Component.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2018 Neil C Smith.
* Copyright 2023 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
Expand All @@ -22,29 +22,30 @@
package org.praxislive.core;

/**
* Components are the main building blocks (actors) within Praxis CORE. They may
* provide Controls (asynchronous message endpoints) and Ports (synchronous message
* points).
*
* Components expect to be used within a hierarchy, inside a Root
* component, and potentially inside other Container components.
* Components are the main building blocks (actors) within Praxis CORE. They may
* provide Controls (asynchronous message endpoints) and Ports (synchronous
* message points).
*
* Components expect to be used within a hierarchy, inside a Root component, and
* potentially inside other Container components.
*
*
*
*/
public interface Component {

/**
* Return the Container that is the immediate parent of this Component, or
* null if this Component is not currently contained within a Component
* hierarchy.
*
* @return Container
*/
public Container getParent();

/**
* Notify the Component that it has been added to the supplied Container, or
* removed from its parent if the supplied argument is null. The
* Component may throw a VetoException if it should not be added to the Container
* removed from its parent if the supplied argument is null. The Component
* may throw a VetoException if it should not be added to the Container
* provided. It should also throw this exception if a parent is already set.
*
* @param parent
Expand All @@ -55,42 +56,57 @@ public interface Component {
/**
* Notify the component that a change has happened in its component
* hierarchy. For example its direct parent or an ancestor has changed.
*
*
* This method will be called after parentNotify() if the result of an
* immediate parent change.
*
*/
public void hierarchyChanged();

/**
* Get a Control that can handle a Call to the given ID, or null if it does
* not exist. Component implementations are free to return a different Control
* for each ID, a single control to handle any message, or somewhere in between.
*
* Get a Control that can handle a Call to the given ID, or null if it does
* not exist. Component implementations are free to return a different
* Control for each ID, a single control to handle any message, or somewhere
* in between.
*
* A null return from this method shall be handled by the Root component by
* responding with an error message to the sender where required.
*
*
* @param id
* @return Control or null
*/

public Control getControl(String id);


/**
* Get the Port with the given ID, or null if it does not exist.
*
* @param id
* @return Port or null
*/
public Port getPort(String id);



/**
* Get the ComponentInfo object for this component.
*
* @return ComponentInfo
*/
public ComponentInfo getInfo();


/**
* If supported, write the state of this component to the provided
* {@link TreeWriter}. This should allow for the component to be recreated
* in as close to its current state as possible.
* <p>
* To fully support this method, the Component should write its type,
* component info, and property values, in that order. It may also add
* custom annotations.
* <p>
* The default implementation of this method does nothing.
*
* @param writer TreeWriter to write to
*/
public default void write(TreeWriter writer) {
// no op
}

}
131 changes: 131 additions & 0 deletions praxiscore-api/src/main/java/org/praxislive/core/Connection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2023 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License version 3
* along with this work; if not, see http://www.gnu.org/licenses/
*
*
* Please visit https://www.praxislive.org if you need additional information or
* have any questions.
*/
package org.praxislive.core;

import org.praxislive.core.protocols.ContainerProtocol;
import org.praxislive.core.types.PArray;
import org.praxislive.core.types.PString;

/**
* A type representing a connection between two ports.
*/
public final class Connection {

private final PArray dataArray;

/**
* Create a connection reference. The child IDs must be valid according to
* {@link ComponentAddress#isValidID(java.lang.String)}. The port IDs must
* be valid according to {@link PortAddress#isValidID(java.lang.String)}.
*
* @param child1 ID of first child
* @param port1 ID of port on first child
* @param child2 ID of second child
* @param port2 ID of port on second child
* @throws IllegalArgumentException if the IDs are not valid
*/
public Connection(String child1, String port1, String child2, String port2) {
verifyChildID(child1);
verifyChildID(child2);
verifyPortID(port1);
verifyPortID(port2);
dataArray = PArray.of(PString.of(child1), PString.of(port1),
PString.of(child2), PString.of(port2));
}

/**
* Query the component ID of the first connected component.
*
* @return ID of first child
*/
public String child1() {
return dataArray.get(0).toString();
}

/**
* Query the port ID of the connected port on the first component.
*
* @return ID of port on first child
*/
public String port1() {
return dataArray.get(1).toString();
}

/**
* Query the component ID of the second connected component.
*
* @return ID of the second child
*/
public String child2() {
return dataArray.get(2).toString();
}

/**
* Query the port ID of the connected port on the second component.
*
* @return ID of port on second child
*/
public String port2() {
return dataArray.get(3).toString();
}

/**
* Access the Connection as the backing PArray data. The data consists of
* four values, {@code child1 port1 child2 port2}.
* <p>
* This is the same format included in the list returned from
* {@link ContainerProtocol#CONNECTIONS}.
*
* @return backing data array
*/
public PArray dataArray() {
return dataArray;
}

@Override
public String toString() {
return dataArray.toString();
}

@Override
public int hashCode() {
return dataArray.hashCode();
}

@Override
public boolean equals(Object obj) {
return obj == this || (obj instanceof Connection c && dataArray.equals(c.dataArray));
}

private static void verifyChildID(String childID) {
if (!ComponentAddress.isValidID(childID)) {
throw new IllegalArgumentException("Invalid child ID : " + childID);
}
}

private static void verifyPortID(String portID) {
if (!PortAddress.isValidID(portID)) {
throw new IllegalArgumentException("Invalid port ID : " + portID);
}
}

}
20 changes: 19 additions & 1 deletion praxiscore-api/src/main/java/org/praxislive/core/Container.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2020 Neil C Smith.
* Copyright 2023 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 only, as
Expand Down Expand Up @@ -61,4 +61,22 @@ public interface Container extends Component, Lookup.Provider {
*/
public ComponentAddress getAddress(Component child);

/**
* If supported, write the state of this container to the provided
* {@link TreeWriter}. This should allow for the container, and its
* children, to be recreated in as close to its current state as possible.
* <p>
* To fully support this method, the Container should write its type,
* component info, property values, children and connections, in that order.
* It may also add custom annotations.
* <p>
* The default implementation of this method does nothing.
*
* @param writer TreeWriter to write to
*/
@Override
public default void write(TreeWriter writer) {
// no op
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.stream.Stream;
import org.praxislive.core.protocols.ComponentProtocol;
import org.praxislive.core.protocols.ContainerProtocol;
import org.praxislive.core.protocols.SerializableProtocol;
import org.praxislive.core.protocols.StartableProtocol;
import org.praxislive.core.services.ComponentFactoryService;
import org.praxislive.core.services.LogService;
Expand Down Expand Up @@ -191,6 +192,7 @@ private static <T extends Protocol> void register(Type<T> type) {
register(new Type<>(ComponentProtocol.class));
register(new Type<>(ContainerProtocol.class));
register(new Type<>(StartableProtocol.class));
register(new Type<>(SerializableProtocol.class));

register(new Type<>(ComponentFactoryService.class));
register(new Type<>(RootFactoryService.class));
Expand Down
Loading

0 comments on commit d2b3146

Please sign in to comment.