/*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.model.builder;
//~--- JDK imports ------------------------------------------------------------
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
//~--- non-JDK imports --------------------------------------------------------
import javafx.concurrent.Task;
import sh.isaac.api.DataTarget;
import sh.isaac.api.Get;
import sh.isaac.api.IdentifiedComponentBuilder;
import sh.isaac.api.chronicle.ObjectChronology;
import sh.isaac.api.commit.ChangeCheckerMode;
import sh.isaac.api.component.sememe.SememeBuilder;
import sh.isaac.api.component.sememe.SememeChronology;
import sh.isaac.api.component.sememe.SememeType;
import sh.isaac.api.component.sememe.version.SememeVersion;
import sh.isaac.api.component.sememe.version.dynamicSememe.DynamicSememeData;
import sh.isaac.api.coordinate.EditCoordinate;
import sh.isaac.api.identity.StampedVersion;
import sh.isaac.api.logic.LogicalExpression;
import sh.isaac.api.task.OptionalWaitTask;
import sh.isaac.model.sememe.SememeChronologyImpl;
import sh.isaac.model.sememe.version.ComponentNidSememeImpl;
import sh.isaac.model.sememe.version.DescriptionSememeImpl;
import sh.isaac.model.sememe.version.DynamicSememeImpl;
import sh.isaac.model.sememe.version.LogicGraphSememeImpl;
import sh.isaac.model.sememe.version.LongSememeImpl;
import sh.isaac.model.sememe.version.SememeVersionImpl;
import sh.isaac.model.sememe.version.StringSememeImpl;
//~--- classes ----------------------------------------------------------------
/**
* The Class SememeBuilderImpl.
*
* @author kec
* @param <C> the generic type
*/
public class SememeBuilderImpl<C extends SememeChronology<? extends SememeVersion<?>>>
extends ComponentBuilder<C>
implements SememeBuilder<C> {
/** The referenced component nid. */
int referencedComponentNid = Integer.MAX_VALUE;
/** The referenced component builder. */
IdentifiedComponentBuilder referencedComponentBuilder;
/** The assemblage concept sequence. */
int assemblageConceptSequence;
/** The sememe type. */
SememeType sememeType;
/** The parameters. */
Object[] parameters;
//~--- constructors --------------------------------------------------------
/**
* Instantiates a new sememe builder impl.
*
* @param referencedComponentBuilder the referenced component builder
* @param assemblageConceptSequence the assemblage concept sequence
* @param sememeType the sememe type
* @param paramaters the paramaters
*/
public SememeBuilderImpl(IdentifiedComponentBuilder referencedComponentBuilder,
int assemblageConceptSequence,
SememeType sememeType,
Object... paramaters) {
this.referencedComponentBuilder = referencedComponentBuilder;
this.assemblageConceptSequence = assemblageConceptSequence;
this.sememeType = sememeType;
this.parameters = paramaters;
}
/**
* Instantiates a new sememe builder impl.
*
* @param referencedComponentNid the referenced component nid
* @param assemblageConceptSequence the assemblage concept sequence
* @param sememeType the sememe type
* @param paramaters the paramaters
*/
public SememeBuilderImpl(int referencedComponentNid,
int assemblageConceptSequence,
SememeType sememeType,
Object... paramaters) {
this.referencedComponentNid = referencedComponentNid;
this.assemblageConceptSequence = assemblageConceptSequence;
this.sememeType = sememeType;
this.parameters = paramaters;
}
//~--- methods -------------------------------------------------------------
/**
* Builds the.
*
* @param stampSequence the stamp sequence
* @param builtObjects the built objects
* @return the c
* @throws IllegalStateException the illegal state exception
*/
@Override
public C build(int stampSequence,
List<ObjectChronology<? extends StampedVersion>> builtObjects)
throws IllegalStateException {
if (this.referencedComponentNid == Integer.MAX_VALUE) {
this.referencedComponentNid = Get.identifierService()
.getNidForUuids(this.referencedComponentBuilder.getUuids());
}
SememeChronologyImpl sememeChronicle;
final int sememeNid = Get.identifierService()
.getNidForUuids(this.getUuids());
if (Get.sememeService()
.hasSememe(sememeNid)) {
sememeChronicle = (SememeChronologyImpl) Get.sememeService()
.getSememe(sememeNid);
if ((sememeChronicle.getSememeType() != this.sememeType) ||
!sememeChronicle.getPrimordialUuid().equals(getPrimordialUuid()) ||
(sememeChronicle.getAssemblageSequence() != this.assemblageConceptSequence) ||
(sememeChronicle.getReferencedComponentNid() != this.referencedComponentNid)) {
throw new RuntimeException("Builder is being used to attempt a mis-matched edit of an existing sememe!");
}
} else {
sememeChronicle = new SememeChronologyImpl(this.sememeType,
getPrimordialUuid(),
sememeNid,
this.assemblageConceptSequence,
this.referencedComponentNid,
Get.identifierService().getSememeSequenceForUuids(this.getUuids()));
}
sememeChronicle.setAdditionalUuids(this.additionalUuids);
switch (this.sememeType) {
case COMPONENT_NID:
final ComponentNidSememeImpl cnsi =
(ComponentNidSememeImpl) sememeChronicle.createMutableVersion(ComponentNidSememeImpl.class,
stampSequence);
cnsi.setComponentNid((Integer) this.parameters[0]);
break;
case LONG:
final LongSememeImpl lsi = (LongSememeImpl) sememeChronicle.createMutableVersion(LongSememeImpl.class,
stampSequence);
lsi.setLongValue((Long) this.parameters[0]);
break;
case LOGIC_GRAPH:
final LogicGraphSememeImpl lgsi =
(LogicGraphSememeImpl) sememeChronicle.createMutableVersion(LogicGraphSememeImpl.class,
stampSequence);
lgsi.setGraphData(((LogicalExpression) this.parameters[0]).getData(DataTarget.INTERNAL));
break;
case MEMBER:
sememeChronicle.createMutableVersion(SememeVersionImpl.class, stampSequence);
break;
case STRING:
final StringSememeImpl ssi = (StringSememeImpl) sememeChronicle.createMutableVersion(StringSememeImpl.class,
stampSequence);
ssi.setString((String) this.parameters[0]);
break;
case DESCRIPTION: {
final DescriptionSememeImpl dsi =
(DescriptionSememeImpl) sememeChronicle.createMutableVersion(DescriptionSememeImpl.class,
stampSequence);
dsi.setCaseSignificanceConceptSequence((Integer) this.parameters[0]);
dsi.setDescriptionTypeConceptSequence((Integer) this.parameters[1]);
dsi.setLanguageConceptSequence((Integer) this.parameters[2]);
dsi.setText((String) this.parameters[3]);
break;
}
case DYNAMIC: {
final DynamicSememeImpl dsi = (DynamicSememeImpl) sememeChronicle.createMutableVersion(DynamicSememeImpl.class,
stampSequence);
if ((this.parameters != null) && (this.parameters.length > 0)) {
// See notes in SememeBuilderProvider - this casting / wrapping nonesense it to work around Java being stupid.
dsi.setData(((AtomicReference<DynamicSememeData[]>) this.parameters[0]).get());
}
// TODO Dan this needs to fire the validator!
break;
}
default:
throw new UnsupportedOperationException("Can't handle: " + this.sememeType);
}
this.sememeBuilders.forEach((builder) -> builder.build(stampSequence, builtObjects));
builtObjects.add(sememeChronicle);
return (C) sememeChronicle;
}
/**
* Builds the.
*
* @param editCoordinate the edit coordinate
* @param changeCheckerMode the change checker mode
* @param builtObjects the built objects
* @return the optional wait task
* @throws IllegalStateException the illegal state exception
*/
@Override
public OptionalWaitTask<C> build(EditCoordinate editCoordinate,
ChangeCheckerMode changeCheckerMode,
List<ObjectChronology<? extends StampedVersion>> builtObjects)
throws IllegalStateException {
if (this.referencedComponentNid == Integer.MAX_VALUE) {
this.referencedComponentNid = Get.identifierService()
.getNidForUuids(this.referencedComponentBuilder.getUuids());
}
SememeChronologyImpl sememeChronicle;
final int sememeNid = Get.identifierService()
.getNidForUuids(this.getUuids());
if (Get.sememeService()
.hasSememe(sememeNid)) {
sememeChronicle = (SememeChronologyImpl) Get.sememeService()
.getSememe(sememeNid);
if ((sememeChronicle.getSememeType() != this.sememeType) ||
!sememeChronicle.getPrimordialUuid().equals(getPrimordialUuid()) ||
(sememeChronicle.getAssemblageSequence() != this.assemblageConceptSequence) ||
(sememeChronicle.getReferencedComponentNid() != this.referencedComponentNid)) {
throw new RuntimeException("Builder is being used to attempt a mis-matched edit of an existing sememe!");
}
} else {
sememeChronicle = new SememeChronologyImpl(this.sememeType,
getPrimordialUuid(),
sememeNid,
this.assemblageConceptSequence,
this.referencedComponentNid,
Get.identifierService().getSememeSequenceForUuids(this.getUuids()));
}
sememeChronicle.setAdditionalUuids(this.additionalUuids);
switch (this.sememeType) {
case COMPONENT_NID:
final ComponentNidSememeImpl cnsi =
(ComponentNidSememeImpl) sememeChronicle.createMutableVersion(ComponentNidSememeImpl.class,
this.state,
editCoordinate);
cnsi.setComponentNid((Integer) this.parameters[0]);
break;
case LONG:
final LongSememeImpl lsi = (LongSememeImpl) sememeChronicle.createMutableVersion(LongSememeImpl.class,
this.state,
editCoordinate);
lsi.setLongValue((Long) this.parameters[0]);
break;
case LOGIC_GRAPH:
final LogicGraphSememeImpl lgsi =
(LogicGraphSememeImpl) sememeChronicle.createMutableVersion(LogicGraphSememeImpl.class,
this.state,
editCoordinate);
lgsi.setGraphData(((LogicalExpression) this.parameters[0]).getData(DataTarget.INTERNAL));
break;
case MEMBER:
sememeChronicle.createMutableVersion(SememeVersionImpl.class, this.state, editCoordinate);
break;
case STRING:
final StringSememeImpl ssi = (StringSememeImpl) sememeChronicle.createMutableVersion(StringSememeImpl.class,
this.state,
editCoordinate);
ssi.setString((String) this.parameters[0]);
break;
case DESCRIPTION: {
final DescriptionSememeImpl dsi =
(DescriptionSememeImpl) sememeChronicle.createMutableVersion(DescriptionSememeImpl.class,
this.state,
editCoordinate);
dsi.setCaseSignificanceConceptSequence((Integer) this.parameters[0]);
dsi.setDescriptionTypeConceptSequence((Integer) this.parameters[1]);
dsi.setLanguageConceptSequence((Integer) this.parameters[2]);
dsi.setText((String) this.parameters[3]);
break;
}
case DYNAMIC: {
final DynamicSememeImpl dsi = (DynamicSememeImpl) sememeChronicle.createMutableVersion(DynamicSememeImpl.class,
this.state,
editCoordinate);
if ((this.parameters != null) && (this.parameters.length > 0)) {
// See notes in SememeBuilderProvider - this casting / wrapping nonesense it to work around Java being stupid.
dsi.setData(((AtomicReference<DynamicSememeData[]>) this.parameters[0]).get());
}
// TODO DAN this needs to fire the validator!
break;
}
default:
throw new UnsupportedOperationException("Can't handle: " + this.sememeType);
}
Task<Void> primaryNested;
if (changeCheckerMode == ChangeCheckerMode.ACTIVE) {
primaryNested = Get.commitService()
.addUncommitted(sememeChronicle);
} else {
primaryNested = Get.commitService()
.addUncommittedNoChecks(sememeChronicle);
}
final ArrayList<OptionalWaitTask<?>> nested = new ArrayList<>();
this.sememeBuilders.forEach((builder) -> nested.add(builder.build(editCoordinate,
changeCheckerMode,
builtObjects)));
builtObjects.add(sememeChronicle);
return new OptionalWaitTask<>(primaryNested, (C) sememeChronicle, nested);
}
}