From 0b8a199743bc60d2b0912f196d5cd6a26a2f3583 Mon Sep 17 00:00:00 2001 From: Daniel <daniel@harvey> Date: Mon, 23 Nov 2020 16:39:52 +0100 Subject: [PATCH] DOC: Added (C) notices and some documentation and comments. --- .../caosdb/server/entity/ClientMessage.java | 26 +++- .../org/caosdb/server/jobs/ScheduledJob.java | 23 ++++ .../jobs/core/CheckStateTransition.java | 36 +++++- .../server/jobs/core/EntityStateJob.java | 111 ++++++++++++++---- .../server/jobs/core/InitEntityStateJobs.java | 30 ++++- .../server/jobs/core/MakeStateMessage.java | 23 ++++ .../server/jobs/core/MakeStateProperty.java | 27 +++++ .../org/caosdb/server/transaction/Update.java | 2 + .../server/utils/AbstractObservable.java | 1 + .../org/caosdb/server/utils/Observer.java | 2 + 10 files changed, 254 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/caosdb/server/entity/ClientMessage.java b/src/main/java/org/caosdb/server/entity/ClientMessage.java index 40a8c713..f6b99677 100644 --- a/src/main/java/org/caosdb/server/entity/ClientMessage.java +++ b/src/main/java/org/caosdb/server/entity/ClientMessage.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.entity; import java.util.HashMap; @@ -12,7 +35,7 @@ import org.jdom2.Element; * * <p>If no plug-in handles the client message, it is printed back to the response unaltered. * - * <p>Client message can have arbitrary key-value tuples {@link #properties}. + * <p>Client message can have arbitrary key-value (string-string typed) tuples {@link #properties}. * * @author Timm Fitschen (t.fitschen@indiscale.com) */ @@ -40,6 +63,7 @@ public class ClientMessage extends Message { parent.addContent(e); } + /** NB: This is the only place where properties are set in this class. */ public static ClientMessage fromXML(Element pe) { ClientMessage result = new ClientMessage(pe.getName(), pe.getText()); for (Attribute a : pe.getAttributes()) { diff --git a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java index d9fa9c42..ee0c2980 100644 --- a/src/main/java/org/caosdb/server/jobs/ScheduledJob.java +++ b/src/main/java/org/caosdb/server/jobs/ScheduledJob.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs; /** diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java b/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java index b64acf50..9634192b 100644 --- a/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java +++ b/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs.core; import org.caosdb.server.entity.DeleteEntity; @@ -11,6 +34,9 @@ import org.caosdb.server.transaction.WriteTransaction; /** * Check if the attempted state transition is allowed. * + * <p>This job checks if the attempted state transition is in compliance with the state model. This + * job runs during the CHECK phase and should do all necessary consistency and permission checks. + * * @author Timm Fitschen (t.fitschen@indiscale.com) */ @JobAnnotation(time = JobExecutionTime.CHECK, transaction = WriteTransaction.class) @@ -41,7 +67,7 @@ public class CheckStateTransition extends EntityStateJob { checkStateTransition(oldState, newState); } else if (getEntity() instanceof DeleteEntity) { if (newState != null) checkFinalState(newState); - } else { + } else { // fresh Entity if (newState != null) checkInitialState(newState); } } catch (Message m) { @@ -52,6 +78,8 @@ public class CheckStateTransition extends EntityStateJob { /** * Check if the state belongs to the state model. * + * <p>In practical terms, throw a Message if the state is invalid. + * * @param state * @throws Message */ @@ -65,6 +93,10 @@ public class CheckStateTransition extends EntityStateJob { /** * Check if state is valid and transition is allowed. * + * <p>Especially, transitions between {@code null} states are allowed, non-trivial transitions + * from or to {@code null} must be initial or final states, respectively ({@link + * FORCE_FINAL_STATE} exception applies). + * * @param oldState * @param newState * @throws Message if not @@ -98,6 +130,8 @@ public class CheckStateTransition extends EntityStateJob { } /** + * Return the two State's common StateModel, or {@code null} if they don't have one in common. + * * @param oldState * @param newState * @return the state model which contains both of the states. diff --git a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java index 83ec96f7..1e536ded 100644 --- a/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java +++ b/src/main/java/org/caosdb/server/jobs/core/EntityStateJob.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs.core; import java.util.ArrayList; @@ -27,24 +50,25 @@ import org.caosdb.server.utils.EntityStatus; import org.jdom2.Element; /** - * The EntityStateJob is the abstract base class for four EntityJobs. + * The EntityStateJob is the abstract base class for four EntityJobs: * - * <p>1. The InitEntityState job reads ClientMessages or StateProperties with tag state and converts - * them into instances of State. This job runs during WriteTransactions. This job runs during the - * INIT Phase and does not perform any checks other than those necessary for the conversion. + * <p>1. The {@link InitEntityState} job reads ClientMessages or StateProperties with tag state and + * converts them into instances of State. This job runs during WriteTransactions. This job runs + * during the INIT Phase and does not perform any checks other than those necessary for the + * conversion. * - * <p>2. The CheckStateTransition job checks if the attempted state transition is in compliance with - * the state model. This job runs during the CHECK phase and should do all necessary consistency and - * permission checks. + * <p>2. The {@link CheckStateTransition} job checks if the attempted state transition is in + * compliance with the state model. This job runs during the CHECK phase and should do all necessary + * consistency and permission checks. * - * <p>3. The MakeStateProperty job constructs an ordinary Property from the State right before the - * entity is being written to the back-end and after any checks run. + * <p>3. The {@link MakeStateProperty} job constructs an ordinary Property from the State right + * before the entity is being written to the back-end and after any checks run. * - * <p>4. The MakeStateMessage job converts a state property (back) into State messages and appends - * them to the entity. + * <p>4. The {@link MakeStateMessage} job converts a state property (back) into State messages and + * appends them to the entity. * - * <p>Only the 4th job runs during Retrieve transitions. During WriteTransactions all four jobs do - * run. + * <p>Only the 4th job ({@link MakeStateMessage}) runs during Retrieve transitions. During + * WriteTransactions all four jobs do run. * * @author Timm Fitschen (t.fitschen@indiscale.com) */ @@ -91,6 +115,10 @@ public abstract class EntityStateJob extends EntityJob { private State toState; private String name; + /** + * @param transition The transition Entity, from which the Transition is created. Relevant + * Properties are "to" and "from" + */ public Transition(EntityInterface transition) throws Message { this.name = transition.getName(); this.fromState = getFromState(transition); @@ -167,9 +195,9 @@ public abstract class EntityStateJob extends EntityJob { } /** - * The State instance represents a single entity state. This class is used for concrete state (the - * state of a stateful entity, say a Record) and abstract states (states which belong to a - * StateModel entity). + * The State instance represents a single entity state. This class is used for concrete states + * (the state of a stateful entity, say a Record) and abstract states (states which are part of a + * {@link StateModel}). * * <p>States are identified via their name and the name of the model to which they belong. * @@ -177,8 +205,8 @@ public abstract class EntityStateJob extends EntityJob { * StateModel iff the StateModel RecordType references the State Record. Each State should only * belong to one StateModel. * - * <p>Furthermore, States are the start or end point of Transitions which belong to the same - * StateModel. Each State can be part of several transitions at the same time. + * <p>Furthermore, States are the start or end point of {@link Transition Transitions} which + * belong to the same StateModel. Each State can be part of several transitions at the same time. * * <p>Note: The purpose of this should not be confused with {@link EntityStatus} which is purely * for internal use. @@ -194,6 +222,7 @@ public abstract class EntityStateJob extends EntityJob { private StateModel stateModel; public State(String stateName, String stateModelName) throws Message { + // TODO Make constructors private or protected and outsource to caching factory methods. this.stateName = stateName; this.stateModelName = stateModelName; } @@ -220,7 +249,12 @@ public abstract class EntityStateJob extends EntityJob { return 21364234 + this.getStateName().hashCode() + this.getStateModelName().hashCode(); } - /** Serialize this State into XML. */ + /** + * Serialize this State into XML. + * + * <p>The result looks approximately like this: {@code <State name="My name" model="Model's + * name"/>} + */ @Override public void addToElement(Element ret) { Element e = new Element(STATE_XML_TAG); @@ -265,7 +299,7 @@ public abstract class EntityStateJob extends EntityJob { } /** - * Create a property which represents the current entity state of a stateful entity. + * Create a Property which represents the current entity state of a stateful entity. * * @return stateProperty * @throws Message @@ -295,7 +329,27 @@ public abstract class EntityStateJob extends EntityJob { @Override public String toString() { - return "State (name=" + getStateName() + ", model=" + getStateModelName() + ")"; + String isInitial = null; + String isFinal = null; + try { + isInitial = String.valueOf(isInitial()); + } catch (Message e) { + isInitial = "null"; + } + try { + isFinal = String.valueOf(isFinal()); + } catch (Message e) { + isFinal = "null"; + } + return "State (name=" + + getStateName() + + ", model=" + + getStateModelName() + + ", initial=" + + isInitial + + ", final=" + + isFinal + + ")"; } } @@ -323,6 +377,7 @@ public abstract class EntityStateJob extends EntityJob { public StateModel(EntityInterface stateModelEntity) throws Message { long time1 = System.currentTimeMillis(); + // TODO Maybe check if a parent is STATE_MODEL_RECORD_TYPE_NAME? this.name = stateModelEntity.getName(); this.transitions = getTransitions(stateModelEntity); this.states = getStates(transitions, this); @@ -335,6 +390,7 @@ public abstract class EntityStateJob extends EntityJob { } private State getInitialState(EntityInterface stateModelEntity) throws Message { + // TODO maybe check if there is more than one "initial" Property? for (Property p : stateModelEntity.getProperties()) { if (p.getName().equals(INITIAL_STATE_PROPERTY_NAME)) { return createState(p); @@ -344,6 +400,7 @@ public abstract class EntityStateJob extends EntityJob { } private State getFinalState(EntityInterface stateModelEntity) throws Message { + // TODO maybe check if there is more than one "final" Property? for (Property p : stateModelEntity.getProperties()) { if (p.getName().equals(FINAL_STATE_PROPERTY_NAME)) { return createState(p); @@ -352,6 +409,7 @@ public abstract class EntityStateJob extends EntityJob { return null; } + /** Transitions are taken from list Property with name="Transition". */ private Set<Transition> getTransitions(EntityInterface stateModelEntity) throws Message { for (Property p : stateModelEntity.getProperties()) { if (p.getName().equals(TRANSITION_RECORD_TYPE_NAME)) { @@ -372,6 +430,7 @@ public abstract class EntityStateJob extends EntityJob { Set<Transition> result = new HashSet<>(); try { if (!(p.getDatatype() instanceof AbstractCollectionDatatype)) { + // FIXME raise an exception instead? return result; } p.parseValue(); @@ -402,6 +461,7 @@ public abstract class EntityStateJob extends EntityJob { */ private Set<State> getStates(Set<Transition> transitions, StateModel stateModel) throws Message { + // TODO Move outside of this class Iterator<Transition> it = transitions.iterator(); Set<State> result = new HashSet<>(); while (it.hasNext()) { @@ -452,7 +512,9 @@ public abstract class EntityStateJob extends EntityJob { Iterator<Transition> iterator = this.transitions.iterator(); while (iterator.hasNext()) { sb.append(iterator.next().name); + sb.append(" -> "); sb.append(iterator.next().name); + sb.append(", "); } sb.append("])"); return sb.toString(); @@ -505,6 +567,7 @@ public abstract class EntityStateJob extends EntityJob { return getState(getEntity(), remove); } + /** Return (and possibly remove) the States Properties of `entity`. */ protected List<Property> getStateProperties(EntityInterface entity, boolean remove) { Iterator<Property> it = entity.getProperties().iterator(); List<Property> result = new ArrayList<>(); @@ -527,6 +590,7 @@ public abstract class EntityStateJob extends EntityJob { return getStateProperties(getEntity(), remove); } + /** Get the {@code ClientMessage}s which denote a state. */ protected List<ClientMessage> getStateClientMessages(EntityInterface entity, boolean remove) { Iterator<Message> stateMessages = entity.getMessages(STATE_XML_TAG).iterator(); List<ClientMessage> result = new ArrayList<>(); @@ -561,13 +625,15 @@ public abstract class EntityStateJob extends EntityJob { /** * Create a State instance from the value of the state property. * - * <p>This method also retrieves the state entity from the back-end. + * <p>This method also retrieves the state entity from the back-end. The StateModel is deduced + * from finding an appropriately referencing StateModel Record. * * @param p the entity's state property * @return The state of the entity * @throws Message */ protected State createState(Property p) throws Message { + // TODO this should be cached try { p.parseValue(); ReferenceValue refid = (ReferenceValue) p.getValue(); @@ -584,6 +650,7 @@ public abstract class EntityStateJob extends EntityJob { EntityInterface findStateModel(EntityInterface stateEntity) throws Exception { // TODO this should be cached + // TODO This should throw a meaningful Exception if no matching StateModel can be found. TransactionContainer c = new TransactionContainer(); Query query = new Query( diff --git a/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java b/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java index 8bb1e00a..66d3db12 100644 --- a/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java +++ b/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs.core; import java.util.ArrayList; @@ -19,8 +42,8 @@ import org.caosdb.server.utils.Observable; import org.caosdb.server.utils.Observer; /** - * Initialize the other entity jobs by converting the client message with type "State" into {@link - * State} instances. + * Initialize the other entity jobs by converting the client message with type "State" or + * StateProperties into {@link State} instances. * * <p>This job also needs to initialize the other jobs even if the current entity version does not * have a state anymore but the previous version had, because it has to be checked if the stateModel @@ -105,7 +128,8 @@ public class InitEntityStateJobs extends EntityStateJob implements Observer { } /** - * Returns a list of states as the are represented as properties or client messages in the entity. + * Return a list of states from their representations as properties or client messages in the + * entity. * * @param entity * @return list of state instances for the entity. diff --git a/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java b/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java index 38fd2398..245b90b0 100644 --- a/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java +++ b/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs.core; import java.util.List; diff --git a/src/main/java/org/caosdb/server/jobs/core/MakeStateProperty.java b/src/main/java/org/caosdb/server/jobs/core/MakeStateProperty.java index 0d290c0f..56682921 100644 --- a/src/main/java/org/caosdb/server/jobs/core/MakeStateProperty.java +++ b/src/main/java/org/caosdb/server/jobs/core/MakeStateProperty.java @@ -1,3 +1,26 @@ +/* + * ** header v3.0 + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2020 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + * ** end header + */ + package org.caosdb.server.jobs.core; import org.caosdb.server.entity.Message; @@ -5,6 +28,10 @@ import org.caosdb.server.jobs.JobAnnotation; import org.caosdb.server.jobs.JobExecutionTime; import org.caosdb.server.transaction.WriteTransaction; +/** + * This job constructs an ordinary Property from the State right before the entity is being written + * to the back-end and after any checks run. + */ @JobAnnotation(transaction = WriteTransaction.class, time = JobExecutionTime.PRE_TRANSACTION) public class MakeStateProperty extends EntityStateJob { diff --git a/src/main/java/org/caosdb/server/transaction/Update.java b/src/main/java/org/caosdb/server/transaction/Update.java index 50d7f978..894728cc 100644 --- a/src/main/java/org/caosdb/server/transaction/Update.java +++ b/src/main/java/org/caosdb/server/transaction/Update.java @@ -4,6 +4,8 @@ * * Copyright (C) 2018 Research Group Biomedical Physics, * Max-Planck-Institute for Dynamics and Self-Organization Göttingen + * Copyright (C) 2020 Indiscale GmbH <info@indiscale.com> + * Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as diff --git a/src/main/java/org/caosdb/server/utils/AbstractObservable.java b/src/main/java/org/caosdb/server/utils/AbstractObservable.java index a19fff9d..abc7f0a0 100644 --- a/src/main/java/org/caosdb/server/utils/AbstractObservable.java +++ b/src/main/java/org/caosdb/server/utils/AbstractObservable.java @@ -37,6 +37,7 @@ public abstract class AbstractObservable implements Observable { return this.observers.add(o); } + /** @param e A String denoting the notification event. */ @Override public void notifyObservers(final String e) { if (this.observers != null) { diff --git a/src/main/java/org/caosdb/server/utils/Observer.java b/src/main/java/org/caosdb/server/utils/Observer.java index be89dff4..b4c8f544 100644 --- a/src/main/java/org/caosdb/server/utils/Observer.java +++ b/src/main/java/org/caosdb/server/utils/Observer.java @@ -25,6 +25,8 @@ package org.caosdb.server.utils; public interface Observer { /** + * Notify this observer that an event {@code e} has happened to the {@code sender}. + * * @param e * @param sender * @return true, iff the Observable has to keep it in the list of observers. -- GitLab